./PaxHeaders.10889/openssh-10.0p1040755 001750 001750 0000000003614775415623 0013242xustar0030 atime=1744182234.451000158 openssh-10.0p1004075500017500001750000000000001477541562300114635ustar00djmdjmopenssh-10.0p1/PaxHeaders.10889/.depend100644 001750 001750 0000000003614775415623 0014414xustar0030 atime=1744182234.452953362 openssh-10.0p1/.depend010064400017500001750000004176401477541562300130130ustar00djmdjm# Automatically generated by makedepend. # Run "make depend" to rebuild. # DO NOT DELETE addr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h addrmatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h match.h log.h ssherr.h atomicio.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h audit-bsm.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h audit-linux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h audit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h auth-bsdauth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h auth-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h sshbuf.h sshkey.h misc.h servconf.h uidswap.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h log.h sshbuf.h misc.h sshkey.h match.h ssh2.h auth-options.h auth-pam.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h auth-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h ssherr.h log.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h auth-rhosts.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h uidswap.h pathnames.h log.h ssherr.h misc.h xmalloc.h sshbuf.h sshkey.h servconf.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-shadow.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h auth-sia.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h auth.o: authfile.h monitor_wrap.h channels.h auth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h groupaccess.h log.h ssherr.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h dispatch.h auth2-chall.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h misc.h servconf.h auth2-gss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h auth2-hostbased.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h kex.h mac.h crypto_api.h sshbuf.h log.h ssherr.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h canohost.h auth2-hostbased.o: monitor_wrap.h pathnames.h match.h auth2-kbdint.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h log.h ssherr.h misc.h servconf.h auth2-methods.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h misc.h servconf.h openbsd-compat/sys-queue.h xmalloc.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth2-none.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h misc.h servconf.h ssh2.h monitor_wrap.h auth2-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h monitor_wrap.h misc.h servconf.h auth2-pubkey.o: audit.h loginrec.h pathnames.h uidswap.h auth-options.h canohost.h monitor_wrap.h authfile.h match.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h kex.h mac.h crypto_api.h sshbuf.h log.h ssherr.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h auth2-pubkeyfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h log.h ssherr.h misc.h sshkey.h digest.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfile.h match.h auth2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h sshbuf.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h monitor_wrap.h digest.h kex.h auth2.o: mac.h crypto_api.h authfd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h sshbuf.h sshkey.h authfd.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h log.h ssherr.h atomicio.h misc.h authfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h ssh.h log.h ssherr.h authfile.h misc.h atomicio.h sshkey.h sshbuf.h krl.h bitmap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h bitmap.h canohost.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h canohost.h misc.h chacha.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h chacha.h channels.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h ssherr.h sshbuf.h packet.h dispatch.h log.h misc.h channels.h compat.h canohost.h sshkey.h authfd.h pathnames.h match.h cipher-aes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h cipher-aesctr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher-aesctr.h rijndael.h cipher-chachapoly-libcrypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher-chachapoly.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h cipher-chachapoly.h chacha.h poly1305.h cipher.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h misc.h sshbuf.h ssherr.h digest.h openbsd-compat/openssl-compat.h cleanup.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h clientloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h packet.h dispatch.h sshbuf.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h clientloop.o: myproposal.h log.h ssherr.h misc.h readconf.h clientloop.h sshconnect.h authfd.h atomicio.h sshpty.h match.h msg.h hostfile.h compat.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h log.h ssherr.h match.h dh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest-libc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h digest.h digest-openssl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h dispatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh2.h log.h ssherr.h dispatch.h packet.h openbsd-compat/sys-queue.h dns.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h ssherr.h dns.h log.h digest.h ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h entropy.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h fatal.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h groupaccess.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h groupaccess.h match.h log.h ssherr.h gss-genr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h gss-serv-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h ssherr.h misc.h pathnames.h digest.h hmac.h sshbuf.h kex-names.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h kex.h mac.h crypto_api.h log.h ssherr.h match.h digest.h misc.h xmalloc.h kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h ssh2.h atomicio.h version.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h log.h ssherr.h kex.o: match.h misc.h monitor.h myproposal.h sshbuf.h digest.h xmalloc.h kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h sshbuf.h digest.h ssherr.h ssh2.h kexdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h kexecdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h kexgen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h log.h ssherr.h packet.h openbsd-compat/sys-queue.h dispatch.h ssh2.h sshbuf.h digest.h kexgex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h kexgexc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h kexgexs.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h kexmlkem768x25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 log.h kexsntrup761x25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h krl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h sshbuf.h ssherr.h sshkey.h authfile.h misc.h log.h digest.h bitmap.h utf8.h krl.h log.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h match.h loginrec.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h hostfile.h ssh.h loginrec.h log.h ssherr.h atomicio.h packet.h openbsd-compat/sys-queue.h dispatch.h canohost.h auth.h auth-pam.h audit.h sshbuf.h misc.h logintest.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h loginrec.h mac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest.h hmac.h umac.h mac.h misc.h ssherr.h sshbuf.h openbsd-compat/openssl-compat.h match.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h misc.h misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h log.h ssherr.h ssh.h sshbuf.h moduli.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h monitor.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h dh.h packet.h dispatch.h auth-options.h sshpty.h channels.h session.h sshlogin.h canohost.h log.h ssherr.h misc.h servconf.h monitor.h monitor_wrap.h monitor_fdpass.h compat.h ssh2.h authfd.h match.h sk-api.h srclimit.h monitor.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h openbsd-compat/openssl-compat.h atomicio.h xmalloc.h ssh.h sshkey.h sshbuf.h hostfile.h auth.h auth-pam.h audit.h loginrec.h cipher.h cipher-chachapoly.h monitor_fdpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h monitor_fdpass.h monitor_wrap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h monitor_wrap.o: loginrec.h auth-options.h packet.h dispatch.h log.h ssherr.h monitor.h atomicio.h monitor_fdpass.h misc.h channels.h session.h servconf.h monitor_wrap.h srclimit.h msg.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssherr.h log.h atomicio.h msg.h misc.h mux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h log.h ssherr.h ssh.h ssh2.h pathnames.h misc.h match.h sshbuf.h channels.h msg.h packet.h dispatch.h monitor_fdpass.h sshpty.h sshkey.h readconf.h clientloop.h nchan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h ssh2.h sshbuf.h ssherr.h packet.h dispatch.h channels.h compat.h log.h packet.o: channels.h ssh.h packet.h dispatch.h sshbuf.h packet.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h compat.h ssh2.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h digest.h log.h ssherr.h canohost.h misc.h platform-listen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h misc.h platform-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h platform-pledge.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h platform-tracing.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h platform.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h poly1305.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h poly1305.h progressmeter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h progressmeter.h atomicio.h misc.h utf8.h readconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h xmalloc.h ssh.h ssherr.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h pathnames.h log.h sshkey.h misc.h readconf.h match.h kex.h mac.h crypto_api.h uidswap.h readconf.o: myproposal.h digest.h version.h readpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h pathnames.h log.h ssherr.h ssh.h uidswap.h rijndael.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h rijndael.h sandbox-capsicum.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sandbox-darwin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sandbox-null.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sandbox-rlimit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sandbox-seccomp-filter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sandbox-solaris.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h scp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h xmalloc.h ssh.h atomicio.h pathnames.h log.h ssherr.h misc.h progressmeter.h utf8.h sftp.h sftp-common.h sftp-client.h servconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h openbsd-compat/sys-queue.h xmalloc.h ssh.h log.h ssherr.h sshbuf.h misc.h servconf.h pathnames.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h servconf.o: mac.h crypto_api.h match.h channels.h groupaccess.h canohost.h packet.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h myproposal.h digest.h version.h serverloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h packet.h dispatch.h sshbuf.h log.h ssherr.h misc.h servconf.h canohost.h sshpty.h channels.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h serverloop.o: rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h loginrec.h session.h auth-options.h serverloop.h session.o: hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfd.h pathnames.h log.h misc.h servconf.h sshlogin.h serverloop.h canohost.h session.h kex.h mac.h crypto_api.h monitor_wrap.h sftp.h atomicio.h session.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h sshbuf.h ssherr.h match.h uidswap.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sftp-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h sshbuf.h log.h atomicio.h progressmeter.h misc.h utf8.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h sftp-common.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssherr.h sshbuf.h log.h misc.h sftp.h sftp-common.h sftp-glob.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h sftp-realpath.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sftp-server-main.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sftp.h misc.h xmalloc.h sftp-server.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h sshbuf.h ssherr.h log.h misc.h match.h uidswap.h sftp.h sftp-common.h sftp-usergroup.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h log.h ssherr.h xmalloc.h sftp-common.h sftp-client.h openbsd-compat/glob.h sftp-usergroup.h sftp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h pathnames.h misc.h utf8.h sftp.h sshbuf.h sftp-common.h sftp-client.h openbsd-compat/glob.h sftp-usergroup.h sk-usbhid.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sntrup761.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h srclimit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h addr.h canohost.h log.h ssherr.h misc.h srclimit.h xmalloc.h servconf.h openbsd-compat/sys-queue.h match.h ssh-add.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h log.h ssherr.h sshkey.h sshbuf.h authfd.h authfile.h pathnames.h misc.h digest.h ssh-sk.h sk-api.h hostfile.h ssh-agent.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h sshkey.h authfd.h log.h ssherr.h misc.h digest.h match.h msg.h pathnames.h ssh-pkcs11.h sk-api.h myproposal.h ssh-dss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh-ecdsa-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h sshbuf.h ssherr.h digest.h sshkey.h ssh-ecdsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh-ed25519-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h ssherr.h sshbuf.h sshkey.h ssh.h digest.h ssh-ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h ssherr.h sshbuf.h sshkey.h ssh.h ssh-keygen.o: cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h ssh-keygen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h authfile.h sshbuf.h pathnames.h log.h ssherr.h misc.h match.h hostfile.h dns.h ssh.h ssh2.h ssh-pkcs11.h atomicio.h krl.h digest.h utf8.h authfd.h sshsig.h ssh-sk.h sk-api.h cipher.h ssh-keyscan.o: dispatch.h log.h ssherr.h atomicio.h misc.h hostfile.h ssh_api.h ssh2.h dns.h addr.h ssh-keyscan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h kex.h mac.h crypto_api.h compat.h myproposal.h packet.h ssh-keysign.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h sshkey.h ssh.h ssh2.h misc.h sshbuf.h authfile.h msg.h canohost.h pathnames.h readconf.h uidswap.h ssh-pkcs11-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh-pkcs11-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h sshbuf.h log.h ssherr.h misc.h sshkey.h authfd.h ssh-pkcs11.h ssh-pkcs11.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshkey.h ssh-rsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh-sk-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h sshkey.h msg.h digest.h pathnames.h ssh-sk.h misc.h ssh-sk-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h sshkey.h authfd.h misc.h sshbuf.h msg.h uidswap.h ssh-sk.h ssh-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h canohost.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h packet.h dispatch.h sshbuf.h channels.h ssh.o: sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h ssherr.h misc.h readconf.h sshconnect.h kex.h mac.h crypto_api.h sshpty.h match.h msg.h version.h myproposal.h utf8.h ssh_api.o: authfile.h dh.h misc.h version.h myproposal.h sshbuf.h openbsd-compat/openssl-compat.h ssh_api.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh_api.h openbsd-compat/sys-queue.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h ssh.h ssh2.h packet.h dispatch.h compat.h log.h ssherr.h sshbuf-getput-basic.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h sshbuf-getput-crypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf-io.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h atomicio.h sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h sshconnect.o: authfd.h kex.h mac.h crypto_api.h sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h sshkey.h sshconnect.h log.h ssherr.h match.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h sshconnect2.o: sshconnect.h authfile.h dh.h authfd.h log.h ssherr.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h utf8.h ssh-sk.h sk-api.h sshd-auth.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h kex.h mac.h crypto_api.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h auth-options.h version.h sk-api.h srclimit.h ssh-sandbox.h dh.h sshd-auth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h log.h ssherr.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h sshd-session.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h kex.h mac.h crypto_api.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h auth-options.h version.h sk-api.h srclimit.h dh.h sshd-session.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h log.h ssherr.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h sshd.o: audit.h loginrec.h authfd.h msg.h version.h sk-api.h addr.h srclimit.h atomicio.h sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshpty.h log.h ssherr.h sshbuf.h misc.h servconf.h compat.h digest.h sshkey.h authfile.h pathnames.h canohost.h hostfile.h auth.h auth-pam.h ssherr.o: ssherr.h sshkey-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h ssh2.h ssherr.h misc.h sshbuf.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h match.h ssh-sk.h openbsd-compat/openssl-compat.h sshlogin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshlogin.h ssherr.h loginrec.h log.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h sshpty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h log.h ssherr.h misc.h sshsig.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h authfd.h authfile.h log.h ssherr.h misc.h sshbuf.h sshsig.h sshkey.h match.h digest.h sshtty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h ttymodes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h compat.h sshbuf.h ttymodes.h uidswap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h uidswap.h xmalloc.h umac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h umac128.o: umac.c includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h utf8.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h utf8.h xmalloc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h xmss_commons.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmss_fast.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmss_hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmss_hash_address.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmss_wots.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openssh-10.0p1/PaxHeaders.10889/.git_allowed_signers100644 001750 001750 0000000003614775415623 0017201xustar0030 atime=1744182234.452953362 openssh-10.0p1/.git_allowed_signers010064400017500001750000000027361477541562300155740ustar00djmdjmdtucker@dtucker.net valid-before="20241206" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKecyjh9aNmD4rb8WblA8v91JjRb0Cd2JtkzqxcggGeG dtucker@dtucker.net sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBDV81zWQ1+XVfWH5z4L4klDQ/z/6l2GLphfSTX/Rmq6kL5H8mkfzUlryxLlkN8cD9srtVJBAmwJWfJBNsCo958YAAAAEc3NoOg== dtucker@dtucker.net sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIElSYahCw60CGct39Eg9EY8OLV9Ppr7tsudvSiMyNHOhAAAABHNzaDo= djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBLnJo3ZVDENYZGXm5uO9lU7b0iDFq5gHpTu1MaHPWTEfPdvw+AjFQQ/q5YizuMJkXGsMdYmblJEJZYHpm9IS7ZkAAAAEc3NoOg== djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBJoAXBTQalfg+kC5wy1vE7HkIHtVnmV6AUuuIo9KQ1P+70juHwvsFKpsGaqQbrHJkTVgYDGVP02XHj8+Fb18yBIAAAAEc3NoOg== djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBH+z1I48s6ydOhP5SJmI02zVCLf0K15B+UMHgoTIKVfUIv5oDoVX7e9f+7QiRmTeEOdZfQydiaVqsfi7qPSve+0AAAAEc3NoOg== djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBPM4BmUg/fMnsl42JwktTekk/mB8Be3M+yK2ayg6lqYsqEri8yhRx84gey51OHKVk1TwlGbJjcMHI4URreDBEMQAAAAEc3NoOg== tim@multitalents.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC/L8E1DfiZ9cHzygqx0IzRCSAlmh4tXH7mZPwWZEY1L openssh-10.0p1/PaxHeaders.10889/.git_allowed_signers.asc100644 001750 001750 0000000003614775415623 0017746xustar0030 atime=1744182234.452953362 openssh-10.0p1/.git_allowed_signers.asc010064400017500001750000000015011477541562300163260ustar00djmdjm-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmYHnZ8ACgkQKj9BTnNg YLquuQ/6A8E6P2jcgn3wmbbCTXP7kmxoh3nmw/e6PC8CEua1512oT3GHOKVD5cGK cgYRObpWvjOjg7L1HRABftq7a9M2zfsGnY/WNe3/fbetfkyY8hG8c31vA1ePIOt2 AjBLCWFblH0CtyH/MssoQ19JCLtXK/GmekB1Q0JzyOog7w/0r3CKuUnZ0juCYR1R 4FBePl5l3nFSZEcFEdptGlNGeuolS5XBCqB9Y91TCzkVkH5eXUUW+shgjNhWCEhT pZvkxfhsmOEnwNofyPdgKVfDBVkHmvuC67EU395mJVN4c2NZ8pOztb9hOt3xr980 q44I4kT2NpaApCx1dWIGhMy/37LJ8heI0W1B+ofTA5n34/RU8UXH3SCkj2AK6Ao5 H2u8vbmuWKUCiECmrw35EeKGmtuK/bWJzx3KBP7fx5J9S3mWUgT4W4xlWNN9RWoU sSvH1ppie5ARINVaAWl5k44fk60ahTf80DbQBIOZBmQn7myZZka+yGcQbAiZZ1Gc 0l8+Nf5Ao1ckmuyY5o8FyWdsyDeK3+MqjPn5Rr1CqbKCn2VnqrVWbI33Eyu8c96U bxVgU5H1BDhNjJC8UrT3LFPvJMO8p3a0IJ3eHydjk2jVOhOdBZmA0yoqUTrhPpXq ymIHESjDJR8TDe4TCfb46o9oEC3cdbDwgnzPqdg0n+0uIsJLYiU= =gl+l -----END PGP SIGNATURE----- openssh-10.0p1/PaxHeaders.10889/.github040755 001750 001750 0000000003614775415623 0014445xustar0030 atime=1744182234.453931021 openssh-10.0p1/.github004075500017500001750000000000001477541562300130235ustar00djmdjmopenssh-10.0p1/.github/PaxHeaders.10889/ci-status.md100644 001750 001750 0000000003614775415623 0016752xustar0030 atime=1744182234.453931021 openssh-10.0p1/.github/ci-status.md010064400017500001750000000047031477541562300153410ustar00djmdjmmaster : [![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:master) [![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:master) [![Upstream self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/upstream.yml/badge.svg)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/upstream.yml?query=branch:master) [![CIFuzz](https://github.com/openssh/openssh-portable/actions/workflows/cifuzz.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/cifuzz.yml) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:openssh) [![Coverity Status](https://scan.coverity.com/projects/21341/badge.svg)](https://scan.coverity.com/projects/openssh-portable) 9.9 : [![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg?branch=V_9_9)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:V_9_9) [![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_9_9)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_9_9) 9.8 : [![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg?branch=V_9_8)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:V_9_8) [![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_9_8)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_9_8) 9.7 : [![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg?branch=V_9_7)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:V_9_7) [![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_9_7)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_9_7) openssh-10.0p1/.github/PaxHeaders.10889/configs100755 001750 001750 0000000003614775415623 0016072xustar0030 atime=1744182234.453931021 openssh-10.0p1/.github/configs010075500017500001750000000311501477541562300144550ustar00djmdjm#!/bin/sh # # usage: configs vmname test_config (or '' for default) # # Sets the following variables: # CONFIGFLAGS options to ./configure # SSHD_CONFOPTS sshd_config options # TEST_TARGET make target used when testing. defaults to "tests". # LTESTS config=$1 if [ "$config" = "" ]; then config="default" fi unset CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO TEST_TARGET="tests compat-tests" LTESTS="" SKIP_LTESTS="" SUDO=sudo # run with sudo by default TEST_SSH_UNSAFE_PERMISSIONS=1 # Stop on first test failure to minimize logs TEST_SSH_FAIL_FATAL=yes CONFIGFLAGS="" LIBCRYPTOFLAGS="" case "$config" in default|sol64) ;; c89) # If we don't have LLONG_MAX, configure will figure out that it can # get it by setting -std=gnu99, at which point we won't be testing # C89 any more. To avoid this, feed it in via CFLAGS. llong_max=`gcc -E -dM - /dev/null)" ]; then REGRESS_INTEROP_PUTTY=yes export REGRESS_INTEROP_PUTTY fi export CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO export TEST_TARGET TEST_SSH_UNSAFE_PERMISSIONS TEST_SSH_FAIL_FATAL openssh-10.0p1/.github/PaxHeaders.10889/configure.sh100755 001750 001750 0000000003614775415623 0017034xustar0030 atime=1744182234.453931021 openssh-10.0p1/.github/configure.sh010075500017500001750000000005441477541562300154220ustar00djmdjm#!/bin/sh . .github/configs $1 printf "$ " if [ "x$CC" != "x" ]; then printf "CC='$CC' " fi if [ "x$CFLAGS" != "x" ]; then printf "CFLAGS='$CFLAGS' " fi if [ "x$CPPFLAGS" != "x" ]; then printf "CPPFLAGS='$CPPFLAGS' " fi if [ "x$LDFLAGS" != "x" ]; then printf "LDFLAGS='$LDFLAGS' " fi echo ./configure ${CONFIGFLAGS} ./configure ${CONFIGFLAGS} 2>&1 openssh-10.0p1/.github/PaxHeaders.10889/run_test.sh100755 001750 001750 0000000003614775415623 0016716xustar0030 atime=1744182234.453931021 openssh-10.0p1/.github/run_test.sh010075500017500001750000000036161477541562300153070ustar00djmdjm#!/bin/sh . .github/configs $1 [ -z "${SUDO}" ] || ${SUDO} mkdir -p /var/empty set -ex # If we want to test hostbased auth, set up the host for it. if [ ! -z "$SUDO" ] && [ ! -z "$TEST_SSH_HOSTBASED_AUTH" ]; then sshconf=/usr/local/etc $SUDO mkdir -p "${sshconf}" hostname | $SUDO tee $sshconf/shosts.equiv >/dev/null echo "EnableSSHKeysign yes" | $SUDO tee $sshconf/ssh_config >/dev/null $SUDO mkdir -p $sshconf $SUDO cp -p /etc/ssh/ssh_host*key* $sshconf $SUDO make install for key in $sshconf/ssh_host*key*.pub; do echo `hostname` `cat $key` | \ $SUDO tee -a $sshconf/ssh_known_hosts >/dev/null done fi output_failed_logs() { for i in regress/failed*.log; do if [ -f "$i" ]; then echo ------------------------------------------------------------------------- echo LOGFILE $i cat $i echo ------------------------------------------------------------------------- fi done } trap output_failed_logs 0 env="" if [ ! -z "${SUDO}" ]; then env="${env} SUDO=${SUDO}" fi if [ ! -z "${TCMALLOC_STACKTRACE_METHOD}" ]; then env="${env} TCMALLOC_STACKTRACE_METHOD=${TCMALLOC_STACKTRACE_METHOD}" fi if [ ! -z "${TEST_SSH_SSHD_ENV}" ]; then env="${env} TEST_SSH_SSHD_ENV=${TEST_SSH_SSHD_ENV}" fi if [ ! -z "${env}" ]; then env="env${env}" fi if [ -z "${LTESTS}" ]; then ${env} make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" else ${env} make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}" fi if [ ! -z "${SSHD_CONFOPTS}" ]; then echo "rerunning t-exec with TEST_SSH_SSHD_CONFOPTS='${SSHD_CONFOPTS}'" if [ -z "${LTESTS}" ]; then ${env} make t-exec SKIP_LTESTS="${SKIP_LTESTS}" TEST_SSH_SSHD_CONFOPTS="${SSHD_CONFOPTS}" else ${env} make t-exec SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}" TEST_SSH_SSHD_CONFOPTS="${SSHD_CONFOPTS}" fi fi openssh-10.0p1/.github/PaxHeaders.10889/setup_ci.sh100755 001750 001750 0000000003614775415623 0016666xustar0030 atime=1744182234.454906447 openssh-10.0p1/.github/setup_ci.sh010075500017500001750000000171031477541562300152530ustar00djmdjm#!/bin/sh PACKAGES="" . .github/configs $@ host=`./config.guess` echo "config.guess: $host" case "$host" in *cygwin) PACKAGER=setup echo Setting CYGWIN system environment variable. setx CYGWIN "binmode" echo Removing extended ACLs so umask works as expected. setfacl -b . regress PACKAGES="$PACKAGES,autoconf,automake,cygwin-devel,gcc-core" PACKAGES="$PACKAGES,make,openssl,libssl-devel,zlib-devel" ;; *-darwin*) PACKAGER=brew PACKAGES="automake" ;; *) PACKAGER=apt esac TARGETS=$@ INSTALL_FIDO_PPA="no" export DEBIAN_FRONTEND=noninteractive set -e if [ -x "`which lsb_release 2>&1`" ]; then lsb_release -a fi if [ ! -z "$SUDO" ]; then # Ubuntu 22.04 defaults to private home dirs which prevent the # agent-getpeerid test from running ssh-add as nobody. See # https://github.com/actions/runner-images/issues/6106 if ! "$SUDO" -u nobody test -x ~; then echo ~ is not executable by nobody, adding perms. chmod go+x ~ fi # Some of the Mac OS X runners don't have a nopasswd sudo rule. Regular # sudo still works, but sudo -u doesn't. Restore the sudo rule. if ! "$SUDO" grep -E 'runner.*NOPASSWD' /etc/passwd >/dev/null; then echo "Restoring runner nopasswd rule to sudoers." echo 'runner ALL=(ALL) NOPASSWD: ALL' |$SUDO tee -a /etc/sudoers fi if ! "$SUDO" -u nobody -S test -x ~ remote_sshd echo "exec /usr/bin/ssh ${TARGET_DOMAIN} exec /home/builder/$(basename ${GITHUB_WORKSPACE})/sshd "'$@' >>remote_sshd chmod 755 remote_sshd make t-exec TEST_SSH_SSHD=`pwd`/remote_sshd LTESTS="try-ciphers kextype keytype" - name: bigendian interop - save logs if: failure() && env.BIGENDIAN == 'true' uses: actions/upload-artifact@main with: name: ${{ matrix.target }}-${{ matrix.config }}-interop-logs path: | config.h config.log regress/*.log regress/log/* - name: bigendian interop - unmount regress if: always() && env.SSHFS == 'true' && env.BIGENDIAN == 'true' run: fusermount -z -u ${GITHUB_WORKSPACE}/regress || true working-directory: ${{ runner.temp }} - name: lazily unmount workspace if: always() && env.SSHFS == 'true' run: fusermount -z -u ${GITHUB_WORKSPACE} || true working-directory: ${{ runner.temp }} - name: shutdown VM if: always() && env.VM == 'true' run: vmshutdown openssh-10.0p1/.github/workflows/PaxHeaders.10889/upstream.yml100644 001750 001750 0000000003614775415623 0021134xustar0030 atime=1744182234.454906447 openssh-10.0p1/.github/workflows/upstream.yml010064400017500001750000000061741477541562300175270ustar00djmdjmname: Upstream self-hosted on: push: branches: [ master ] paths: [ '**.c', '**.h', '**.sh', '.github/configs', '.github/workflows/upstream.yml' ] jobs: selfhosted: name: "upstream ${{ matrix.target }} ${{ matrix.config }}" if: github.repository == 'openssh/openssh-portable-selfhosted' runs-on: ${{ matrix.host }} env: DEBUG_ACTIONS: true EPHEMERAL: true HOST: ${{ matrix.host }} TARGET_HOST: ${{ matrix.target }} TARGET_CONFIG: ${{ matrix.config }} TARGET_DOMAIN: ${{ format('{0}-{1}-{2}', matrix.target, matrix.config, github.run_id) || matrix.target }} strategy: fail-fast: false matrix: host: - libvirt target: [ obsdsnap, obsdsnap-i386 ] config: [ default, without-openssl, ubsan ] include: - { host: libvirt-arm64, target: obsdsnap-arm64, config: default } - { host: libvirt-arm64, target: obsdsnap-arm64, config: without-openssl } - { host: libvirt-arm64, target: obsdsnap-arm64, config: ubsan } steps: - name: unmount stale workspace run: fusermount -u ${GITHUB_WORKSPACE} || true working-directory: ${{ runner.temp }} - name: shutdown VM if running run: vmshutdown working-directory: ${{ runner.temp }} - uses: actions/checkout@main - name: startup VM run: vmstartup working-directory: ${{ runner.temp }} - name: copy and mount workspace run: sshfs_mount working-directory: ${{ runner.temp }} - name: update source run: vmrun "cd /usr/src && cvs up -dPA usr.bin/ssh regress/usr.bin/ssh" - name: make clean run: vmrun "cd /usr/src/usr.bin/ssh && make obj && make clean && cd /usr/src/regress/usr.bin/ssh && make obj && make clean && sudo chmod -R g-w /usr/src /usr/obj" - name: make run: vmrun "cd /usr/src/usr.bin/ssh && case ${{ matrix.config }} in without-openssl) make OPENSSL=no;; ubsan) make DEBUG='-fsanitize-minimal-runtime -fsanitize=undefined';; *) make; esac" - name: make install run: vmrun "cd /usr/src/usr.bin/ssh && sudo make install && sudo /etc/rc.d/sshd -f restart" - name: make tests` run: vmrun "cd /usr/src/regress/usr.bin/ssh && case ${{ matrix.config }} in without-openssl) make OPENSSL=no;; ubsan) make DEBUG='-fsanitize-minimal-runtime -fsanitize=undefined';; *) make; esac" env: SUDO: sudo timeout-minutes: 300 - name: show logs if: failure() run: vmrun 'for i in /usr/src/regress/usr.bin/ssh/obj/*.log; do echo ====; echo logfile $i; echo =====; cat $i; done' - name: save logs if: failure() uses: actions/upload-artifact@main with: name: ${{ matrix.target }}-${{ matrix.config }}-logs path: | /usr/src/regress/usr.bin/ssh/obj/*.log /usr/src/regress/usr.bin/ssh/obj/log/* - name: unmount workspace if: always() run: | fusermount -u ${GITHUB_WORKSPACE} || true fusermount -z -u ${GITHUB_WORKSPACE} || true working-directory: ${{ runner.temp }} - name: shutdown VM if: always() run: vmshutdown working-directory: ${{ runner.temp }} openssh-10.0p1/PaxHeaders.10889/.gitignore100644 001750 001750 0000000003614775415623 0015144xustar0030 atime=1744182234.454906447 openssh-10.0p1/.gitignore010064400017500001750000000007071477541562300135330ustar00djmdjmMakefile buildpkg.sh config.h config.h.in~ config.log config.status openbsd-compat/Makefile openbsd-compat/regress/Makefile openssh.xml opensshd.init survey.sh **/*.o **/*.lo **/*.so **/*.dylib **/*.dll **/*.out **/*.a **/*.un~ **/.*.swp autom4te.cache/ scp sftp sftp-server ssh ssh-add ssh-agent ssh-keygen ssh-keyscan ssh-keysign ssh-pkcs11-helper ssh-sk-helper sshd sshd-session sshd-auth !regress/misc/**/Makefile !regress/unittests/**/Makefile tags openssh-10.0p1/PaxHeaders.10889/.skipped-commit-ids100644 001750 001750 0000000003614775415623 0016657xustar0030 atime=1744182234.454906447 openssh-10.0p1/.skipped-commit-ids010064400017500001750000000075461477541562300152560ustar00djmdjm509bb19bb9762a4b3b589af98bac2e730541b6d4 clean sshd random relinking kit 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 52ff0e3205036147b2499889353ac082e505ea54 moduli update 07b5031e9f49f2b69ac5e85b8da4fc9e393992a0 Makefile.inc cc12a9029833d222043aecd252d654965c351a69 moduli-gen Makefile 7ac6c252d2a5be8fbad4c66d9d35db507c9dac5b moduli update 6b52cd2b637f3d29ef543f0ce532a2bce6d86af5 makefile change f9a0726d957cf10692a231996a1f34e7f9cdfeb0 moduli update 1e0a2692b7e20b126dda60bf04999d1d30d959d8 sshd relinking makefile changes e1dc11143f83082e3154d6094f9136d0dc2637ad more relinking makefile tweaks 5a636f6ca7f25bfe775df4952f7aac90a7fcbbee moduli update ef9341d5a50f0d33e3a6fbe995e92964bc7ef2d3 Makefile relinking changes 2fe8d707ae35ba23c7916adcb818bb5b66837ba0 ssh-agent relink kit 866cfcc1955aef8f3fc32da0b70c353a1b859f2e ssh-agent relink changes 8b3820adb4da4e139c4b3cffbcc0bde9f08bf0c6 sshd-session relink kit 6d2ded4cd91d4d727c2b26e099b91ea935bed504 relink kit fb39324748824cb0387e9d67c41d1bef945c54ea Makefile change 5f378c38ad8976d507786dc4db9283a879ec8cd0 Makefile change 112aacedd3b61cc5c34b1fa6d9fb759214179172 Makefile change a959fc45ea3431b36f52eda04faefc58bcde00db groupaccess.c changes 6d07e4606997e36b860621a14dd41975f2902f8f Makefile.inc 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 openssh-10.0p1/PaxHeaders.10889/CREDITS100644 001750 001750 0000000003614775415623 0014174xustar0030 atime=1744182234.455883505 openssh-10.0p1/CREDITS010064400017500001750000000125661477541562300125710ustar00djmdjmTatu Ylonen - Creator of SSH Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt, and Dug Song - Creators of OpenSSH Ahsan Rashid - UnixWare long passwords Alain St-Denis - Irix fix Alexandre Oliva - AIX fixes Andre Lucas - new login code, many fixes Andreas Steinmetz - Shadow password expiry support Andrew McGill - SCO fixes Andrew Morgan - PAM bugfixes Andrew Stribblehill - Bugfixes Andy Sloane - bugfixes Aran Cox - SCO bugfixes Arkadiusz Miskiewicz - IPv6 compat fixes Ben Lindstrom - NeXT support Ben Taylor - Solaris debugging and fixes Bratislav ILICH - Configure fix Charles Levert - SunOS 4 & bug fixes Chip Salzenberg - Assorted patches Chris Adams - OSF SIA support Chris Saia - SuSE packaging Chris, the Young One - Password auth fixes Christos Zoulas - Autoconf fixes Chun-Chung Chen - RPM fixes Corinna Vinschen - Cygwin support Chad Mynhier - Solaris Process Contract support Dan Brosemer - Autoconf support, build fixes Darren Hall - AIX patches Darren Tucker - AIX BFF package scripts David Agraz - Build fixes David Del Piero - bug fixes David Hesprich - Configure fixes David Rankin - libwrap, AIX, NetBSD fixes Dag-Erling Smørgrav - Challenge-Response PAM code. Dhiraj Gulati - UnixWare long passwords Ed Eden - configure fixes Garrick James - configure fixes Gary E. Miller - SCO support Ged Lodder - HPUX fixes and enhancements Gert Doering - bug and portability fixes HARUYAMA Seigo - Translations & doc fixes Hideaki YOSHIFUJI - IPv6 and bug fixes Hiroshi Takekawa - Configure fixes Holger Trapp - KRB4/AFS config patch IWAMURO Motonori - bugfixes Jani Hakala - Patches Jarno Huuskonen - Bugfixes Jim Knoble - Many patches Jonchen (email unknown) - the original author of PAM support of SSH Juergen Keil - scp bugfixing KAMAHARA Junzo - Configure fixes Kees Cook - scp fixes Kenji Miyake - Configure fixes Kevin Cawlfield - AIX fixes. Kevin O'Connor - RSAless operation Kevin Steves - HP support, bugfixes, improvements Kiyokazu SUTO - Bugfixes Larry Jones - Bugfixes Lutz Jaenicke - Bugfixes Marc G. Fournier - Solaris patches Mark D. Baushke - bug fixes Martin Johansson - Linux fixes Mark D. Roth - Features, bug fixes Mark Miller - Bugfixes Matt Richards - AIX patches Michael Steffens - HP-UX fixes Michael Stone - Irix enhancements Nakaji Hiroyuki - Sony News-OS patch Nalin Dahyabhai - PAM environment patch Nate Itkin - SunOS 4.1.x fixes Niels Kristian Bech Jensen - Assorted patches Pavel Kankovsky - Security fixes Pavel Troller - Bugfixes Pekka Savola - Bugfixes Peter Kocks - Makefile fixes Peter Stuge - mdoc2man.awk script Phil Hands - Debian scripts, assorted patches Phil Karn - Autoconf fixes Philippe WILLEM - Bugfixes Phill Camp - login code fix Rip Loomis - Solaris package support, fixes Robert Dahlem - Reliant Unix fixes Roumen Petrov - Compile & configure fixes SAKAI Kiyotaka - Multiple bugfixes Simon Wilkinson - PAM fixes, Compat with MIT KrbV Solar Designer - many patches and technical assistance Svante Signell - Bugfixes Thomas Neumann - Shadow passwords Tim Rice - Portability & SCO fixes Tobias Oetiker - Bugfixes Tom Bertelson's - AIX auth fixes Tor-Ake Fransson - AIX support Tudor Bosman - MD5 password support Udo Schweigert - ReliantUNIX support Wendy Palm - Cray support. Zack Weinberg - GNOME askpass enhancement Apologies to anyone I have missed. Damien Miller openssh-10.0p1/PaxHeaders.10889/ChangeLog100644 001750 001750 0000000003514775415623 0014725xustar0029 atime=1744182234.46076586 openssh-10.0p1/ChangeLog010064400017500001750000007472711477541562300133330ustar00djmdjmcommit 8725dbc5b5fcc3e326fc71189ef8dba4333362cc Author: Damien Miller Date: Wed Apr 9 17:02:17 2025 +1000 update version numbers commit cc7feb9458ad3b893b53dc9c7500d1affd208bde Author: djm@openbsd.org Date: Wed Apr 9 07:00:21 2025 +0000 upstream: openssh-10.0 OpenBSD-Commit-ID: db5b4a1f1c9e988f8f166b56dc5643606294b403 commit fc86875e6acb36401dfc1dfb6b628a9d1460f367 Author: djm@openbsd.org Date: Wed Apr 9 07:00:03 2025 +0000 upstream: Fix logic error in DisableForwarding option. This option was documented as disabling X11 and agent forwarding but it failed to do so. Spotted by Tim Rice. OpenBSD-Commit-ID: fffc89195968f7eedd2fc57f0b1f1ef3193f5ed1 commit dd73459e351b0a2908aed90910c8ff9b0b381c6d Author: djm@openbsd.org Date: Wed Apr 9 01:24:40 2025 +0000 upstream: oops, I accidentally backed out the typo fix OpenBSD-Commit-ID: f485f79bf3e9ebbe1de13ac96150cf458956cfd8 commit 0cb945891944bada5850e85d60afa3c807cf1af6 Author: djm@openbsd.org Date: Wed Apr 9 01:23:47 2025 +0000 upstream: typo OpenBSD-Commit-ID: f912725c7d303720706b3ccfb2cb846d46296d13 commit cd4a6bd50b658d707867caa1f5aa40b35c2b6c19 Author: Damien Miller Date: Wed Apr 9 09:49:55 2025 +1000 initialise websafe_allowlist in agent fuzzer commit 55b7cb48af96c1102ef8ab5a73bb329cbed30945 Author: djm@openbsd.org Date: Tue Apr 8 23:10:46 2025 +0000 upstream: typo OpenBSD-Regress-ID: 08477b936d1d0c1e8a98aa1c0e1bdde8871894c9 commit 985d8cbcd3438cc36b4e709476f1783e358ddfb1 Author: djm@openbsd.org Date: Tue Apr 8 23:10:08 2025 +0000 upstream: typo OpenBSD-Commit-ID: 6e683e13e72bf1e43bbd3bbc6a8332d5a98bdc99 commit 000c3d14e94d8f7597087c457260ea9417045b65 Author: dtucker@openbsd.org Date: Mon Apr 7 08:12:22 2025 +0000 upstream: Include time.h for time(). Fixes warning on some platforms when building without openssl. OpenBSD-Commit-ID: 04ca29b8eaae1860c7adde3e770baa1866e30a54 commit 49b8b9bf829e08af22366530614a5e59ac341ca9 Author: tb@openbsd.org Date: Wed Apr 2 04:28:03 2025 +0000 upstream: Wrap #include in #ifdef WITH_DSA ok djm OpenBSD-Commit-ID: ed01a7c102243f84e4a317aefb431916d98aab15 commit f80fb819e5521e13f167edbcc3eed66e22ad0c2a Author: Damien Miller Date: Thu Apr 3 09:10:19 2025 +1100 remove all instances of -pie from LDFLAGS Previously only the first instance of this flag was removed. Unbreaks build on OpenSUSE Tumbleweed. Patch from Antonio Larrosa commit 6c9872faa1c297a84c6d3e3b95a927be99eadbf6 Author: djm@openbsd.org Date: Tue Apr 1 23:23:20 2025 +0000 upstream: remove ability to enable DSA support. Actual code will be g/c'd separately. ok deraadt@ OpenBSD-Commit-ID: 2a032b75156c4d922e8343fa97ff6bc227f09819 commit 8460aaa4e1f8680f03cc5334556b9440b401f010 Author: dtucker@openbsd.org Date: Fri Mar 28 21:45:55 2025 +0000 upstream: Add TEST_SSH_SSHD_ENV to sshd lines here too. OpenBSD-Regress-ID: 045f2c88b42d694b404db51c5de5eca20d748ff1 commit 5e60f5937b9c33190b9d7614f72d85d4a9b38d3d Author: dtucker@openbsd.org Date: Fri Mar 28 06:04:07 2025 +0000 upstream: Pass "ControlMaster no" to ssh when invoked by scp & sftp. If you have ControlMaster auto (or yes) in your config, and the first connection you make is via scp or sftp, then you may get a few unexpected options applied to it (eg ForwardX11 no), since sftp and sftp explicitly disable those for reasons. These effects will persist beyond the initial scp or sftp command. This explicitly disables persistent session *creation* by scp and sftp. It will not prevent them from using an existing session if one has already been created. From Github PR#557, ok djm@ kn@ OpenBSD-Commit-ID: 9dad7c737466837e0150c4318920f46d844770c4 commit bbd36869dfb4b770cc9e6a345c04a585a0955aec Author: dtucker@openbsd.org Date: Fri Mar 28 05:41:15 2025 +0000 upstream: Set sshd environment variables during sshd test run too. OpenBSD-Regress-ID: 50cb325d92c390a2909662c901f6ac5d80b6f74d commit 98f05b1484daddef2f56b79e24540523b5016143 Author: dtucker@openbsd.org Date: Fri Mar 28 05:36:24 2025 +0000 upstream: Add TEST_SSH_SSHD_ENV variable which is added to sshd's environment. Will be used in Portable to tweak behaviour of tcmalloc's debugging. OpenBSD-Regress-ID: 67e38c3c4517ddb72c8a3549a3325a166d7bb6d6 commit 8cd9ed4df0eccc825eca0c45354a37332e125e38 Author: dtucker@openbsd.org Date: Fri Mar 28 05:33:30 2025 +0000 upstream: chown log directory in addition to log files. OpenBSD-Regress-ID: b520d54a0bbf2c6554413c798218bda26b385ad9 commit e32de6bf4f3229d4838beb127de45eed1377ccc5 Author: Darren Tucker Date: Fri Mar 28 16:47:58 2025 +1100 Be explicit about environment variables for tests. This will make it easier to reproduce a test failure by cut-and-paste of the corresponding line from the github log. commit 77a3e6ba47381547b3fe4b29223256f276fbd07e Author: Darren Tucker Date: Fri Mar 28 16:46:40 2025 +1100 Add tcmalloc flags to TEST_SSH_SSHD_ENV. This will get passed to sshd via test-exec.sh. commit a73890e340fbd6121251854b658a72d738b86c84 Author: Darren Tucker Date: Thu Mar 27 23:04:44 2025 +1100 Add PuTTY 0.81, 0.82 and 0.83 to tests. commit 90a28de0d49570324d1695c0b4686354ef3bcae0 Author: Darren Tucker Date: Thu Mar 27 22:30:40 2025 +1100 Include TCMALLOC_STACKTRACE_METHOD in output. If TCMALLOC_STACKTRACE_METHOD happens to be set, include it in the debug output to make reproducing test cases easier. commit fd5a6bb6dd7657c4bd8cd0ee11d5c8ddf0d927b2 Author: Darren Tucker Date: Thu Mar 27 20:15:11 2025 +1100 Test with-linux-memlock-onfault in kitchensink. commit 22330711e2459c23d9736ee16e0e2ee0fcc30b9a Author: Collin Funk Date: Wed Mar 26 18:24:59 2025 -0700 Include fcntl.h so AT_FDCWD does not get redefined. commit 6c49e5f7dcaf886b4a702a6c003cae9dca04d3ea Author: Daniil Tatianin Date: Thu Feb 27 11:37:13 2025 +0300 Add support for locking memory on Linux Linux wakes up kcompactd threads in order to make more contiguous memory available on the system, it does this by migrating live movable pages (actively modifying live processes' page tables and constantly flooding them with page invalidation IPIs, which can be up to millions per second), which causes the process to become unresponsive for up to seconds or even minutes in some severe cases. In case of sshd, we want to always be able to connect to the system, even if it's under heavy kcompactd load. Introduce an option to protect sshd and its children sessions from being compacted by kcompactd (this works in cojunction with compact_unevictable_allowed = 0). Note that we depend on MCL_ONFAULT being available, which was introduced in linux 4.4. MCL_ONFAULT allows the system to lock pages lazily, thus drastically reducing memory usage of a locked process (without MCL_ONFAULT, every existing mapping in the process is instantly write-faulted). commit fdc4853c5b1567934d43ab13282f03033cc21325 Author: Daniil Tatianin Date: Thu Feb 27 11:46:25 2025 +0300 platform: introduce a way to hook new session start Previously this was possible via post_fork_child, but ever since sshd was split into multiple binaries, this is now no longer possible becase of execv. commit 1b311b6b17be81577514c38e8be4f5740d7df496 Author: dtucker@openbsd.org Date: Wed Mar 19 06:11:15 2025 +0000 upstream: Prevent theoretical NULL deref in throughlocal_sftp. Coverity CID 405019, although at the moment it's not reachable. ok djm@ OpenBSD-Commit-ID: 630d46c1021b69fbb470e349976c70e9a48b7644 commit 96493ebd6ff48bbb802576e208794a26928569b0 Author: Darren Tucker Date: Wed Mar 19 17:35:10 2025 +1100 Fix workflow syntax again. commit 575c43fd4c44d376b1771c0fdaf4941021ba88c9 Author: Darren Tucker Date: Tue Mar 18 20:54:48 2025 +1100 Differentiate logfiles better. commit 8a1294638f3a47d46263ea574fa85c8e115ea893 Author: Darren Tucker Date: Tue Mar 18 20:27:46 2025 +1100 Fix another typo in workflow. commit bd9e6bbcc864b3e10c4e11f5aec1b3a5e3a89b55 Author: Darren Tucker Date: Tue Mar 18 18:16:12 2025 +1100 Fix syntax error in workflow. commit ce88a1bb4a2e6425752094f7a2eb4adfb0ca7971 Author: Darren Tucker Date: Tue Mar 18 18:13:14 2025 +1100 Identify each logfile while printing them. commit b58e429960c4791fc4e30bb7c70d1f77d538b546 Author: djm@openbsd.org Date: Tue Mar 18 04:53:14 2025 +0000 upstream: fix NULL dereference for Match conditions missing arguments, e.g. "Match user". Spotted by Coverity (CID 477813) OpenBSD-Commit-ID: 13584281cfa23b8ebc41f9d128a6b9464ae960d4 commit 0ce5281f017c3ad7bdcc2bbd9745119a73e0cbb8 Author: tb@openbsd.org Date: Fri Mar 14 09:49:49 2025 +0000 upstream: Fix EVP_CIPHER_CTX_ctrl() return checks While this API tries to translate negative return values (i.e. -1) to 0 in BoringSSL and LibreSSL, it is still possible for it to return negative values in prinicple. We even incorrectly document that -1 can be returned while Boring and OpenSSL plead the Fifth. In OpenSSL 3 there are now code paths that explicitly return -1 and they started shifting their return checks to <= 0 - of course they do this in inconsistent and sometimes incorrect manner. While these paths aren't reachable from ssh right now, who can really tell what happens in the two hundred lines of inscrutable bloated mess this has become. So error check with <= 0 to ensure that we don't accidentally translate an error to success. ok markus schwarze OpenBSD-Commit-ID: a855c833cf4ecfce43bedc761f26ad924f70483c commit 2e81100763d5885e500f065b04c16ed87ce74318 Author: Darren Tucker Date: Mon Mar 17 21:35:55 2025 +1100 Fix debug log path. commit 442a44970179d70ebb62bba792699eaec978a1db Author: Darren Tucker Date: Fri Mar 14 16:24:06 2025 +1100 Also lazily unmount workspace in case of straggers. commit 20427f6735fe5ddab31911ce5315adc71acf47d8 Author: Darren Tucker Date: Fri Mar 14 16:17:39 2025 +1100 Make sure upstream tests run on correct hardware. commit 91a2f70a56827ae31649baf17227b0914ac5aa36 Author: Darren Tucker Date: Fri Mar 14 13:47:27 2025 +1100 Add OpenBSD upstream test on obsdsnap-arm64. commit c20f7413525602b0ea786d8974d03a81f7ca2a92 Author: Damien Miller Date: Thu Mar 13 10:45:53 2025 +1100 rebuild .depend commit d47ef958b89c6fa809302d654009d3dfabe11b75 Author: djm@openbsd.org Date: Wed Mar 12 22:43:44 2025 +0000 upstream: remove assumption that the sshd_config and any configs included from it can fit in a (possibly enlarged) socket buffer, by having the sshd listener mainloop actively manage sending the configuration to the sshd-session subprocess. work by markus@ w/ a little feedback from me; ok me and committing on his behalf OpenBSD-Commit-ID: 8f54451483f64951853074adb76bc4f838eaf3ae commit 9c90b563943c16418d737433ac478974b8761ee5 Author: dtucker@openbsd.org Date: Tue Mar 11 11:46:44 2025 +0000 upstream: Prime caches for DNS names needed for tests. When running the SSHFP tests, particularly on an ephemeral VM, the first query or two can fail for some reason, presumably because something isn't fully initialized or something. To work around this, issue queries for the names we'll need before we need them. OpenBSD-Regress-ID: 900841133540e7dead253407db5a874a6ed09eca commit 10124eefe875a3e4e1cfb84ebe6a613ed3213b78 Author: dtucker@openbsd.org Date: Tue Mar 11 09:06:50 2025 +0000 upstream: Some dd's don't understand "1m", so handle seperately. OpenBSD-Regress-ID: 1d983b27c96f28f69d3a288c19e8d8c58e1b2ee3 commit c21c8fc319376c2f5e0da166e9e89a97a245ae72 Author: Darren Tucker Date: Tue Mar 11 19:17:46 2025 +1100 Lazily unmount github workspace at end of workflow. Sometimes when a test times out the workspace is still busy when we try to unmount it, which leaves the runner unusable until it's cleaned up manually. We try to unmount this in the first step, but that usually doesn't work since it fails during setup before it starts our workflow. Move it to the end and make it a lazy unmount so it hopefully works eventually. commit 4bcbac742968f5086cfd4c570a51de25ef77931f Author: dtucker@openbsd.org Date: Tue Mar 11 07:50:20 2025 +0000 upstream: Add regress test for sftp resume. OpenBSD-Regress-ID: 37f629b3014338fa23a85df1e1bb320ea12282e1 commit e2c4f070b43a4fd7d59a9350e2fe78df605830b5 Author: dtucker@openbsd.org Date: Tue Mar 11 07:46:02 2025 +0000 upstream: Use ssh binary instead of the (smaller) script when preparing test data files since it's faster. OpenBSD-Regress-ID: 4215e42682fdb73e131e10645d4a1a23a91d64f5 commit 62f02e95ba5cda4649c482d30f4370e2360eb94d Author: dtucker@openbsd.org Date: Tue Mar 11 07:43:45 2025 +0000 upstream: Set up dbclient's known_hosts as it expects. OpenBSD-Regress-ID: 9e0898e8423237ce5023be53787bb4062e0d0418 commit 395284bd52887dbaf7e78200c857d7f2d9ce398e Author: dtucker@openbsd.org Date: Tue Mar 11 07:43:03 2025 +0000 upstream: Use $DBCLIENT to access dbclient for consistency. OpenBSD-Regress-ID: 81e1b41e1ffc49aba1e6fcaeb6242f3b7875ea3c commit 97e10c0005a784622c61cb4e8bb7858b410bbcc6 Author: dtucker@openbsd.org Date: Tue Mar 11 07:42:08 2025 +0000 upstream: Check if dbclient supports SHA1 before trying SHA1-based KEX. Dropbear 2025.87 removed SHA1 support by default, which means diffie-hellman-group14-sha1 is not available. Unfortunately there isn't a flag to query supported KEX, so instead check MACs and if it doesn't have SHA1 methods, assuming SHA1 based KEXes are likewise not available. Spotted by anton@. OpenBSD-Regress-ID: acfa8e26c001cb18b9fb81a27271c3b51288d304 commit 29a5127f808d00aa539fd27d83a65c2c56179b0e Author: dtucker@openbsd.org Date: Tue Mar 11 07:48:51 2025 +0000 upstream: Set highwater when resuming a "put". Prevents bogus "server reordered acks" debug message. ok djm@ OpenBSD-Commit-ID: aa7f6d0fc2e893c8c278ea3e6e0974c2eca83f5d commit 6575859d7acb110acf408707f98ed9744ca7d692 Author: dtucker@openbsd.org Date: Mon Mar 3 06:54:37 2025 +0000 upstream: Test for %-token and env var expansion in SetEnv. OpenBSD-Regress-ID: bd6139a6177ac4afb29a0ce4afc23567b22ef9f9 commit fd7ad8d7bf7dbdeb8f11a8b51aa9d31df1a17e52 Author: dtucker@openbsd.org Date: Sun Mar 2 07:41:06 2025 +0000 upstream: Also test User expansions when supplied via -l option and user@host. OpenBSD-Regress-ID: 56415859260b53ef0dd20f71225ba5fdf6320f50 commit e6cfd783f1491b502db9322aa970822c63f1667d Author: dtucker@openbsd.org Date: Sat Mar 1 06:12:47 2025 +0000 upstream: Tests for User expansion of %-tokens and environment variables. OpenBSD-Regress-ID: 7ed21dd0e09fb1f3537b8b177f171018aa501628 commit 197e503b8e4b642ce0f405a5d65da4256fa96431 Author: djm@openbsd.org Date: Fri Dec 6 16:25:58 2024 +0000 upstream: use glob(3) wildcards in AuthorizedKeys/PrincipalsFile tests to exercise this feature; ok dtucker OpenBSD-Regress-ID: 7f7b19c0b05b1862cc6521ce61b2b301a3f9cc3b commit 396202180180a4ac16788d469508a348789dafa1 Author: djm@openbsd.org Date: Fri Dec 6 10:37:42 2024 +0000 upstream: implement attestation verification for ED25519 keys OpenBSD-Regress-ID: c44fa5cdb434375a8b5545fdb4fc651061afca1f commit b49875428cda9c16c5bd52552100da2b419cda5f Author: dtucker@openbsd.org Date: Mon Mar 3 06:53:09 2025 +0000 upstream: Add %-token and environment variable expansion to SetEnv. feedback deraadt@ jmc@, nits and ok djm@ OpenBSD-Commit-ID: 2f6e5070481cb73e6f35fd1c6608c1eeff88a5c1 commit b6bba67e6c31d268480773e4fed16d0a32b4218e Author: djm@openbsd.org Date: Sun Mar 2 22:44:00 2025 +0000 upstream: fix PerSourcePenalty incorrectly using "crash" penalty when LoginGraceTime was exceeded. Reported by irwin AT princeton.edu via bz3797 OpenBSD-Commit-ID: 1ba3e490a5a9451359618c550d995380af454d25 commit 38d69fee1b06948f160d94abd07b6b297630d30a Author: Damien Miller Date: Sun Mar 2 22:06:53 2025 +1100 include __builtin_popcount replacement function Some systems/compilers lack __builtin_popcount(), so replace it as necessary. Reported by Dennis Clarke; ok dtucker@ commit c94138d02a45dda5015f38f5a60b0bdde29019c1 Author: djm@openbsd.org Date: Sun Mar 2 11:03:13 2025 +0000 upstream: whitespace OpenBSD-Commit-ID: 1bd8953a37451ef7e0991f9fceec5e8005fe986a commit 65d2c59628e68e166046efa69e76c1d395a8df6e Author: dtucker@openbsd.org Date: Sun Mar 2 07:02:49 2025 +0000 upstream: Make a copy of the user when handling ssh -l, so that later during User token expansion we don't end up freeing a member of argv. Spotted by anton@'s regress tests. OpenBSD-Commit-ID: 2f671a4f5726b66d123b88b1fdd1a90581339955 commit bd30cf784d6e825ef71592fb723c41d4f2fd407b Author: dtucker@openbsd.org Date: Sat Mar 1 06:11:26 2025 +0000 upstream: Allow %-token and environment variable expansion in User, with the exception of %r and %C which are self-referential. Requested in bz#3477, ok djm@, man page improvements jmc@ OpenBSD-Commit-ID: caeb46251ee073662f6f5864c6f7b92d8ac80fa8 commit 94f59dcfc57f95ae044f75c3ce544329c8956c35 Author: Darren Tucker Date: Sat Mar 1 10:28:59 2025 +1100 Rebuild config files if Makefile changes. This ensures paths are updated if they are changed by re-running configure. Patch from rapier at psc.edu. commit dfd9880585db1570656022f9fe1519df673f7b8a Author: Darren Tucker Date: Wed Feb 26 18:16:03 2025 +1100 Check for le32toh, le64toh, htole64 individually. It appears that at least some versions of endian.h in glibc do not have the latter two, so check for and replace each one individually. bz#3794, ok djm@ commit cb99e8eb228df366af33f4fe88d7a9dd0dbf0756 Author: djm@openbsd.org Date: Tue Feb 25 06:25:30 2025 +0000 upstream: ressurect fix for "match invalid-user" that got clobbered by 1.423 OpenBSD-Commit-ID: d18bf0945976e0f3467d710d4bc8bdbe181c0567 commit 487cf4c18c123b66c1f3f733398cd37e6b2ab6ab Author: deraadt@openbsd.org Date: Fri Feb 21 18:22:41 2025 +0000 upstream: Also prohibit , (comma) in hostnames, proposed by David Leadbeater ok djm millert OpenBSD-Commit-ID: 2837fa31dc6e81976f510f0a259edaa559b20b07 commit 3bc6de98c830bd5207f6c371ba69c5874f06305b Author: Damien Miller Date: Mon Feb 24 17:27:50 2025 +1100 Try to fix github tcmalloc target failure tcmalloc may, depending on the stacktrace generator it uses, create pipe(2) fds during shared library initialisation. These will later get clobbered by ssh/sshd calling closefrom() and chaos will ensue. Tell tcmalloc to use an unwinder that doesn't pull this stuff. commit 922e54bbfe8c8479453693ef52350338f0c19124 Author: Damien Miller Date: Fri Feb 21 13:44:35 2025 +1100 cleanup last mention of ubuntu-20.04 commit bc4b3f6dc1738d389e5c9dcca8c56d7e153fee49 Author: Damien Miller Date: Fri Feb 21 13:44:13 2025 +1100 prune gcc/clang versions to be tested Test only the oldest and latest versions of each commit 94b73755f931d592a612ef5cb998694643eab5ff Author: Damien Miller Date: Fri Feb 21 11:30:22 2025 +1100 Update AWS-LC version number Patch from Shubham Mittal bz bz3792 commit 6887099fae6d9f3482e1075d034e9343dc413200 Author: Damien Miller Date: Fri Feb 21 11:22:34 2025 +1100 adjust workflows for ubuntu version transition remove workflows for unsupported compilers, add a few for additional supported compilers, move some workflows to run on ubuntu-latest commit 33bb47e6f74f2ca8093946e6f462d655a9ae46d3 Author: Damien Miller Date: Thu Feb 20 17:10:32 2025 +1100 Add ubuntu-*-arm test runners commit a0c95fbb215b2168fa51b15906e2d6990d7fef6b Author: Damien Miller Date: Thu Feb 20 17:03:28 2025 +1100 remove ubuntu-20.04 Github action runners ubuntu-20.04 is deprecated now, so migrate all its unique runners to ubuntu-22.04. ok dtucker@ commit 0cbeedba81b57c56379e1d202b9ccd3b72af7ddc Author: Damien Miller Date: Tue Feb 18 19:03:42 2025 +1100 openssh-9.9p2 commit 0832aac79517611dd4de93ad0a83577994d9c907 Author: djm@openbsd.org Date: Tue Feb 18 08:02:48 2025 +0000 upstream: Fix cases where error codes were not correctly set Reported by the Qualys Security Advisory team. ok markus@ OpenBSD-Commit-ID: 7bcd4ffe0fa1e27ff98d451fb9c22f5fae6e610d commit 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2 Author: djm@openbsd.org Date: Tue Feb 18 08:02:12 2025 +0000 upstream: Don't reply to PING in preauth phase or during KEX Reported by the Qualys Security Advisory team. ok markus@ OpenBSD-Commit-ID: c656ac4abd1504389d1733d85152044b15830217 commit 9e5bd74a85192c00a842f63d7ab788713b4284c3 Author: jmc@openbsd.org Date: Sat Feb 15 06:48:56 2025 +0000 upstream: - use \& when contructs like "e.g." end a line, to avoid double spacing - macro is Qq not Oq OpenBSD-Commit-ID: 17e5d2d7f288cc7fc536e3af252224525f9fb43a commit f519e71fb7a46314ae16e2a75490649dc0bd01a2 Author: Damien Miller Date: Sat Feb 15 13:12:40 2025 +1100 depend commit 9131ac64b0ebe66dc1de9d44bf8d1bd64a24c350 Author: djm@openbsd.org Date: Sat Feb 15 01:52:07 2025 +0000 upstream: add "Match version" support to ssh_config. Allows matching on the local version of OpenSSH, e.g. "Match version OpenSSH_10.*" ok markus@ OpenBSD-Commit-ID: c0cb504d0b9e43ccf12e68a544a7cd625e89758d commit 192a20df00c8a56fe7d92ffa23d959c865d7fb9e Author: djm@openbsd.org Date: Sat Feb 15 01:50:47 2025 +0000 upstream: Add support for "Match sessiontype" to ssh_config. Allows matching on the type of session requested, either "shell" for interactive sessions, "exec" for command execution sessions, "subsystem" for subsystem requests, such as sftp, or "none" for transport/forwarding-only sessions. ok markus@ OpenBSD-Commit-ID: eff5c001aecb2283d36639cfb28c0935a8bfd468 commit caa3c0c77082888236b0b0c4feb3e6879731b3ba Author: djm@openbsd.org Date: Sat Feb 15 01:48:30 2025 +0000 upstream: "Match command ..." support for ssh_config to allow matching on the remote command specified on the commandline. Also relaxes matching rules for `Match tagged` to allow `Match tagged ""` to match an empty tag value. This also works for command. ok markus@ OpenBSD-Commit-ID: 00dcfea425bf58d824bf5e3464cfc2409121b60d commit 38f6000e9851a00e2e4b8e1eb4ea6a243ef7e6a3 Author: Damien Miller Date: Tue Feb 11 10:32:26 2025 +1100 depend commit aa1409e7a0a5605f0127651a3ba5a348666325bc Author: djm@openbsd.org Date: Mon Feb 10 23:19:26 2025 +0000 upstream: include arguments the command was invoked with, and operating system name, version and architecture in startup debugging output; ok dtucker OpenBSD-Commit-ID: 2a509d319aaf31a6bf9998e1842832883fbc3edd commit 857ac20f5fe19f183defba5dbf4b7d9e6400230c Author: djm@openbsd.org Date: Mon Feb 10 23:16:51 2025 +0000 upstream: include line number in Match debug messages, makes it a little easier to see what's going on OpenBSD-Commit-ID: 1fcf4aa2ee667711b9497ded0fa52d757c69b1df commit af49d474e481d2d78b2f06b06a06b0b37629358e Author: djm@openbsd.org Date: Mon Feb 10 23:00:29 2025 +0000 upstream: fix "Match invalid-user" from incorrectly being activated in initial configuration pass when no other predicates were present on the match line OpenBSD-Commit-ID: 02703b4bd207fafd03788bc4e7774bf80be6c9a8 commit 1c67bae3f5834e48ded71c406f2039dea6e536db Author: schwarze@openbsd.org Date: Sun Feb 9 18:24:08 2025 +0000 upstream: In a section 1 manual, use the plain English words "standard output" rather than the overly technical abbreviation "stdout" - we are not talking about a device file or a FILE * object here. Issue reported by on the groff mailing list. OpenBSD-Commit-ID: a0816999f970e6159523bed8484f62c42ec93109 commit 85b3d68dd931416ede657f371f1d60cdc3a66f34 Author: dtucker@openbsd.org Date: Fri Jan 17 00:09:41 2025 +0000 upstream: Fix debug logging of user specific delay. Patch from Achim Leitner (fjl5) via github PR#552. OpenBSD-Commit-ID: 834a869ed9b15058d3c1ef0cd75402ef989255d8 commit e4e5b06fdf4532705669c0ae944b364022d16b9d Author: dtucker@openbsd.org Date: Thu Jan 16 06:37:10 2025 +0000 upstream: Call log_init in sshd-auth and sshd-session immediately after parsing the config file so that any log settings set in the config file take effect immediately. Move version banners to immediately after that, and make them distinct per binary. ok djm@ OpenBSD-Commit-ID: acf3d090638edf9b6e6f78eed96b537fe671f0f5 commit 0643994b20f2cc54bca80842a984b3052ff1a6a9 Author: dtucker@openbsd.org Date: Wed Jan 15 22:23:13 2025 +0000 upstream: Use strprefix helper when processing sshd -C test args instead of counting bytes by hand. ok djm@ OpenBSD-Commit-ID: 2866d369d96fe04bf76112260ac37e489f98a9a9 commit 66efd0fbb6b8b95f8a520f2cdf8ede14e62b30b3 Author: Damien Miller Date: Thu Feb 6 09:38:09 2025 +1100 add support for AWS-LC (AWS libcrypto) Patch from Shubham Mittal via bz3784; ok dtucker commit 826483d51a9fee60703298bbf839d9ce37943474 Author: Tim Rice Date: Mon Dec 16 15:36:54 2024 -0800 fix old typo (s/SYSVINITSTOPT/SYSVINITSTOP/) commit 1a8ce460f1d0c3f7304edba0733783b57b430e21 Author: dtucker@openbsd.org Date: Thu Dec 12 09:09:09 2024 +0000 upstream: Plug leak on error path, spotted by Coverity. ok djm@ OpenBSD-Commit-ID: b1859959374b4709569760cae0866d22a16606d3 commit 924f996144fc0ae1a659fadcfc2237d1ae935fc4 Author: Xavier Hsinyuan Date: Mon Dec 9 11:21:05 2024 +0800 Add $(srcdir) for standalone sk-libfido2 make target. Fix out-of-tree build failure due to incorrect path for `sk-usbhid.c`. commit bbc9c18e84de29c83fa03e69290979fcca54a2b2 Author: djm@openbsd.org Date: Sat Dec 7 10:12:19 2024 +0000 upstream: replace bespoke logging of MaxSessions enforcement with new ratelimited logging infrastructure. Add ratelimits to logging of connections dropped by PerSourcePenalties ok dtucker OpenBSD-Commit-ID: f22fe7c39607e4361aadf95e33773ffd68c59489 commit 5a6ddf946cf105189c2c99a04f86ce95edc55fc5 Author: djm@openbsd.org Date: Sat Dec 7 10:05:36 2024 +0000 upstream: add infrastructure for ratelimited logging; feedback/ok dtucker OpenBSD-Commit-ID: 18a83e5ac09d59aaf1e834fd6b796db89dd842e7 commit 85f0c1e75e8f6c5d83b8070918ee2f6ab16d403e Author: djm@openbsd.org Date: Fri Dec 6 16:24:27 2024 +0000 upstream: allow glob(3) patterns for sshd_config AuthorizedKeysFile and AuthorizedPrincipalsFile directives; bz2755 ok dtucker OpenBSD-Commit-ID: 3e3e05a17fca39bba78b993a07b44664519adf7f commit 9a9ffee6e10bcd039f1f9385599577441ebe542a Author: djm@openbsd.org Date: Fri Dec 6 16:21:48 2024 +0000 upstream: support VersionAddendum in the client, mirroring the option of the same name in the server; bz2745 ok dtucker@ OpenBSD-Commit-ID: 6ff7905b3f9806649bde750515786553fb89cdf4 commit 41ab0ccecd68232e196efae5e224b31ca104c423 Author: djm@openbsd.org Date: Fri Dec 6 16:02:12 2024 +0000 upstream: clarify encoding of options/extensions; bz2389 OpenBSD-Commit-ID: c4e92356d44dfe6d0a4416deecb33d1d1eba016c commit 5488810359f0fd91e2f7b919c70a3798e46376cb Author: djm@openbsd.org Date: Fri Dec 6 15:17:15 2024 +0000 upstream: ignore SIGPIPE here; some downstreams have had this for years... OpenBSD-Commit-ID: 73674ee4f8ceb8fc9cb8de71d8ddea0c721eb035 commit 4389a792d9078212366eba124a3eed36e009d09e Author: djm@openbsd.org Date: Fri Dec 6 15:12:56 2024 +0000 upstream: sync -o option lists with ssh.1; requested jmc@ OpenBSD-Commit-ID: a7ac295b444da7b2ca7a33a52370594f6897f6bb commit 6b9cd095565ddc5402d5096dce248fa0521dbda3 Author: Fabio Pedretti Date: Mon Oct 16 17:12:24 2023 +0200 Remove ancient RHL 6.x config in RPM spec. It looks like build6x options were intended for RHL 6.x (the Red Hat distro predating Fedora, not RHEL), but were then applied to RHEL. Completely remove support for this ancient configuration. Successfully built, installed and run on RHEL 6. This also remove a build warning about deprecation of PreReq. commit 5cacfa798f92b707491375fed748d1d1bcb33ec9 Author: Darren Tucker Date: Fri Dec 6 23:54:45 2024 +1100 Add new hardware-backed signing key for myself. Retire old non-hardware based signing key. commit f129b6ee1d4361799e65307216e3a4d5544356b7 Author: Jonas 'Sortie' Termansen Date: Sat Nov 2 22:05:45 2024 +0100 Fix configure implicit declaration and format warnings. commit 11a5e5179077f73c2d45bcdf3f60153ae3f17815 Author: dtucker@openbsd.org Date: Fri Dec 6 07:05:54 2024 +0000 upstream: Expand $SSH to absolute path if it's not already. Prevents problem later in increase_datafile_size if ssh is not in the path. Patch from quaresmajose via GHPR#510. OpenBSD-Regress-ID: 2670a66af8b827410ca7139f0a89f4501cece77b commit dc2ef8f0944a4ff7ba19e52fd17b4654e6bd9b93 Author: dtucker@openbsd.org Date: Fri Dec 6 06:55:28 2024 +0000 upstream: Change "login again" to "log in again" in password change message. From ThinLinc-Zeijlon via github PR#532. OpenBSD-Commit-ID: fea5e9bc04caf613a118c419f16863733b340cf1 commit 8252f346eb21cd6b30816f905b7d94f10962373e Author: naddy@openbsd.org Date: Thu Dec 5 22:45:03 2024 +0000 upstream: catch up documentation: AES-GCM is preferred to AES-CTR OpenBSD-Commit-ID: 63360924b6834507fe70020edb936f5075043a9e commit 9a2f4c75081769bd45eba2bf3fab0a32b25f1879 Author: Darren Tucker Date: Fri Dec 6 17:56:17 2024 +1100 Change text from "login to" to "log in to". From ThinLinc-Zeijlon via GHPR#532. commit 24dcf368d816b06136a02845ebd0c7846bf18927 Author: Xavier Hsinyuan Date: Fri Dec 6 11:56:34 2024 +0800 Fix configure message typo in sk-libfido2 standalone. commit 1a0cac2f3411a22d69ae6918eff48456b805e73b Author: Alexander Kanavin Date: Thu Dec 5 16:26:46 2024 +0100 Skip 2038 key expiry test on 64 bit time_t systems. This allows testing Y2038 with system time set to after that (i.e. 2040), so that actual Y2038 issues can be exposed, and not masked by key expiry errors. Signed-off-by: Alexander Kanavin commit 6b4611dc1232c5d2c8e43201f580f19aab320c87 Author: Darren Tucker Date: Fri Dec 6 01:45:52 2024 +1100 Skip 64bit expiry time test on 32bit time_t. commit c9b7866a7dc5e6c30f5aa9d22dd0bbafda0d496f Author: dtucker@openbsd.org Date: Thu Dec 5 14:28:39 2024 +0000 upstream: Add key expiry test in the 64bit time_t range for additional coverage. From Alexander Kanavin via bz#3684. OpenBSD-Regress-ID: bdf6eb3c2421f2e1e11483d03b34c7931d1bccf7 commit 790c913b5fc6ee93ae14793443dc85a0f574b7eb Author: Damien Miller Date: Thu Dec 5 19:24:56 2024 +1100 typo commit d23a23aaeeabc228792e3fd7eb5f2fa6ae13c482 Author: Damien Miller Date: Thu Dec 5 08:47:02 2024 +1100 add a Makefile target for ssh-verify-attestation Not built by default, but easier than doing it by hand commit d0ac63d0f8b5f778d5fd326701ef4489bc27635e Author: dtucker@openbsd.org Date: Thu Dec 5 06:49:26 2024 +0000 upstream: De-magic the x11 base port number into a define. ok djm@ OpenBSD-Commit-ID: 23b85ca9d222cb739b9c33ee5e4d6ac9fdeecbfa commit 9998c93d57bf0f1df2bc93e0bc2d8112c6f8c720 Author: dtucker@openbsd.org Date: Thu Dec 5 06:47:00 2024 +0000 upstream: Prevent integer overflow in x11 port handling. These are theoretically possible if the admin misconfigures X11DisplayOffset or the user misconfigures their own $DISPLAY, but don't happen in normal operation. From Suhov Roman via bz#3730, ok djm@ OpenBSD-Commit-ID: e9e3860f1a19b862ccf07dc8ecbe8f1e1034f4ed commit 8c9ee046d40e4254c6c1711783ea11027b72c3e9 Author: djm@openbsd.org Date: Wed Dec 4 16:42:49 2024 +0000 upstream: add a work-in-progress tool to verify FIDO attestation blobs that ssh-keygen can write when enrolling FIDO keys. OpenBSD-Regress-ID: 6c97bf3f46e48866677ad69f54b77683eb92437f commit 50c640d874d0246dd0a0d949398c3d7f757c716a Author: dtucker@openbsd.org Date: Wed Dec 4 10:51:13 2024 +0000 upstream: Don't assume existence of SK provider in test. Patch from balu.gajjala at gmail via bz#3402. OpenBSD-Regress-ID: d571932016d07d135b54433d07520b9e1901db43 commit 73d782693144262570d3585b62f16b183170c014 Author: djm@openbsd.org Date: Wed Dec 4 14:37:55 2024 +0000 upstream: sync the list of options accepted by -o with ssh_config.5 prompted by bz3455 OpenBSD-Commit-ID: 0ecbfa70aea6c769bcc259defe07182edf461f57 commit 6993d9f0959534b0b7d52e17b95e9e79fb0b3d0a Author: djm@openbsd.org Date: Wed Dec 4 14:24:20 2024 +0000 upstream: don't screw up ssh-keygen -l output when the file contains CR characters; GHPR236 bz3385, fix from Dmitry Belyavskiy OpenBSD-Commit-ID: e458cf6b0adcea5b69ef4c7ba38e590841d02ef4 commit c0b03c2534946fc114880092177aa4a3683ced2d Author: jsg@openbsd.org Date: Tue Dec 3 22:30:03 2024 +0000 upstream: spelling; ok djm@ OpenBSD-Commit-ID: c8ff3f70020451eef214e598117b7ce1a29853ef commit 97eb247f40167f44324e88a537d5b4fe771a63b2 Author: dtucker@openbsd.org Date: Tue Dec 3 16:27:53 2024 +0000 upstream: Remove fallback to compiled-in gropup for dhgex when the moduli file exists, but does not contain moduli within the client-requested range. The fallback behaviour remains for the case where the moduli file does not exist (typically, running tests prior to installing). From bz#2793, based in part on patch from Joe Testa, ok djm@ OpenBSD-Commit-ID: b1a8c5dbbedf249b42474679ebaf14db7332b1ab commit 30c746265ebde29806dba77c92fb1fd3803cbf5c Author: tb@openbsd.org Date: Tue Dec 3 15:53:51 2024 +0000 upstream: Remove redundant field of definition check This will allow us to get rid of EC_GROUP_method_of() in the near future. ok djm OpenBSD-Commit-ID: b4a3d2e00990cf5c2ec6881c21ddca67327c2df8 commit eaa1744f34c30740328fd0a0d84b5f2f9e6918c1 Author: Damien Miller Date: Thu Dec 5 00:59:19 2024 +1100 don't ignore changes in regress Makefiles reported by Torben Hansen in bz2880 commit 66e986880b2472fefaad781f10113b138b65ff27 Author: Damien Miller Date: Thu Dec 5 00:01:33 2024 +1100 Support systemd-style socket activation in agent Adds support for systemd LISTEN_PID/LISTEN_FDS socket activation to ssh-agent. Activated when these environment variables are set and the agent is started with the -d or -D option and no socket path is set. Based on GHPR502 by Daniel Kahn Gillmor, ok dtucker commit 9b57c099f57152e6c94f633c114f544087f4bdaa Author: Darren Tucker Date: Wed Dec 4 21:36:01 2024 +1100 Update readme files to better reflect reality. Prompted by bz#3738, ok djm@. commit ffa885db1b960451d426455045d2f51288e48ee8 Author: dtucker@openbsd.org Date: Tue Dec 3 14:12:47 2024 +0000 upstream: Improve description of KbdInteractiveAuthentication. Based on bz#3658, fixes jmc@ ok markus@ djm@. OpenBSD-Commit-ID: 9fadb56b9afed554d501acbba911c685acd6ffc2 commit b460f82a67795bba37c6cc6c78f788e5b435b4cb Author: Jonas 'Sortie' Termansen Date: Sat Nov 2 17:53:23 2024 +0100 Inherit DESTDIR from the environment. autoconf packages conventionally inherit the DESTDIR variable from the environment. commit 9da7fa7c7464df241ae5d17da94e4ebed9013719 Author: Jonas 'Sortie' Termansen Date: Sat Nov 2 22:10:39 2024 +0100 Define u_short and u_long if needed. commit d3a7ff7cecbc23cc37044bdf02e7118d05bf3c35 Author: djm@openbsd.org Date: Tue Dec 3 08:31:49 2024 +0000 upstream: support FIDO tokens that return no attestation data, e.g. recent WinHello. From Michael Braun via GHPR542 OpenBSD-Commit-ID: a71b0542f2f7819ba0e33a88908e01b6fc49e4ce commit 96b64056c812620014b65371a9e3ac86bfcd08d5 Author: Thorsten Kukuk Date: Tue Nov 19 10:53:28 2024 +0100 Add wtmpdb support as Y2038 safe wtmp replacement commit 1d9563a56f2ad5b0c0aeef20e19c1a03ad54f88a Author: djm@openbsd.org Date: Mon Dec 2 14:06:42 2024 +0000 upstream: unbreak OpenBSD-Commit-ID: 05b6c31f4a6e385338f43cc0e08776cea75802a1 commit d75837b9f6d0d6cc18ed5078789ea0f3dad08f00 Author: djm@openbsd.org Date: Mon Dec 2 13:37:18 2024 +0000 upstream: prefer AES-GCM to AES-CTR; ok deraadt markus OpenBSD-Commit-ID: 8366a72e0f300ee31c5dab2c95025387ec15bbc9 commit e19cd494b567a73dc390e09b47c1e21545e6116b Author: Shiva Kaul Date: Mon Dec 2 02:04:20 2024 -0500 Fix compilation with DEBUG_SK enabled In `ssh_ecdsa_sk_verify`, the `datalen` variable was renamed to `dlen` -- but not in this debugging block. commit 67ace92be0718df7e0f52c0a76684fc2ebae4089 Author: dtucker@openbsd.org Date: Fri Nov 29 00:13:36 2024 +0000 upstream: Import regenerated moduli. OpenBSD-Commit-ID: 311d271bf0fab8a119e84f4f696d8cd40731692f commit ca0697a90e5720ba4d76cb0ae9d5572b5260a16c Author: Jeremy Stott Date: Sat Oct 19 12:10:52 2024 +1300 Add make target for standalone sk-libfido2 Add a Makefile target for sk-libfido2, the standalone fido2 security key shared library, suitable for use with the SecurityKeyProvider option. Add a new configure option `--with-security-key-standalone` that optionally sets the shared library target sk-libfido2$(SHLIBEXT), and adds it to $(TARGETS). misc.h is required when SK_STANDALONE is defined, because of the use of `monotime_tv` in `sk_select_by_touch`. Sets the shared library extension for sk-libfido2 is by setting `SHLIBEXT` depending on the platform in configure.ac. Add the shared library to the CI builds in the `sk` target config to make sure it can compile under the same conditions as `--with-security-key-builtin`. Add a libssh-pic.a static library that compiles with `-fPIC` reusing .c.lo method in sk-dummy.so for use in the shared library sk-libfido2. Note, a separate static library libssh-pic.a is needed, since defining -DSK_STANDALONE excludes some symbols needed in sshkey.lo. commit 74d70841efbf41b9fcc8e6f6f4777d2e9d7e2004 Author: Arnout Engelen Date: Fri Oct 18 13:42:38 2024 +0200 mdoc2man: balance nested square brackets I noticed the square brackets in `destination [command [argument...]` in the synopsis for the `ssh.1` manpage were not balanced, this balances them. Signed-off-by: Arnout Engelen commit 8eabd2ae2ca1d7756417a1ee5b41f09c5d997634 Author: djm@openbsd.org Date: Wed Nov 27 16:07:08 2024 +0000 upstream: fix argument of "Compression" directive in ssh -G config dump, which used to work but broke in 9.8 OpenBSD-Commit-ID: c79936242d29c70d01941b28d2d07fd0b85fe46f commit 53c03961769d8879a81398074ea3cb36253d4f2e Author: djm@openbsd.org Date: Wed Nov 27 13:27:34 2024 +0000 upstream: new name/link for agent I-D OpenBSD-Commit-ID: e3420f3925a297a1b2ab7dfe7c7d274cfc8e1193 commit 785e3c9110df8f2d30e42ce8b45969c49700f35b Author: djm@openbsd.org Date: Wed Nov 27 13:00:23 2024 +0000 upstream: mention that biometrics may be used for FIDO key user verification as well as PIN. Prompted by Zack Newman, ok jmc@ OpenBSD-Commit-ID: b774a4438c9be70012661ee278450790d21277b8 commit fd2e64c9ec9ea3e89e396be0db41aaf982ae1210 Author: djm@openbsd.org Date: Tue Nov 26 22:05:51 2024 +0000 upstream: g/c outdated XXX comments OpenBSD-Commit-ID: 74d0c0b74994d9a4343c4d7ea4948cb34f609a6c commit 0ad34a6193357d286042322ea7347262a6fb0778 Author: djm@openbsd.org Date: Tue Nov 26 22:02:28 2024 +0000 upstream: regression test for UpdateHostkeys with multiple keys backed by ssh-agent. Patch from Maxime Rey. OpenBSD-Regress-ID: 1777ab6e639e57c0e20cbcb6df60455b49fd8bb3 commit 84023656d91b78f1ef86c8321ec563f2e90f7227 Author: djm@openbsd.org Date: Tue Nov 26 22:01:37 2024 +0000 upstream: Explicitly specify the signature algorithm when signing hostkeys-prove requests. Fixes a corner-case triggered by UpdateHostKeys with one or more unknown host keys stored in ssh-agent where sshd refuses to accept the signature coming back from the agent. Report/fix from Maxime Rey OpenBSD-Commit-ID: 460c7d527a24f92b7e5f68ca1a2fa242ebf0d086 commit d1c1cfc5e4e9b43593d4642810ea8135e4c7db49 Author: djm@openbsd.org Date: Tue Nov 26 21:23:35 2024 +0000 upstream: when using RSA keys to sign messages, select the signature algorithm based on the requested hash algorithm ("-Ohashalg=xxx"). This allows using something other than rsa-sha2-512, which may not be supported on all signing backends, e.g. some smartcards only support SHA256. Patch from Morten Linderud; ok markus@ OpenBSD-Commit-ID: 246353fac24e92629263996558c6788348363ad7 commit ac7544654441280071b90a4129a47467d40f2389 Author: djm@openbsd.org Date: Sun Nov 24 23:47:50 2024 +0000 upstream: turn off CDIAGFLAGS and turn back on INSTALL_STRIP accidentally changed in last commit OpenBSD-Commit-ID: 6d07e4606997e36b860621a14dd41975f2902f8f commit 953fa5b59afb04c3c74ed82d7bace65c13cd8baa Author: Darren Tucker Date: Sat Nov 9 11:41:44 2024 +1100 Disable security key for bigendian interop. It doesn't currently work. It's not clear why, but I suspect sk-dummy.so ends up being built for the wrong architecture. commit a80eb71c428c474098087c672398f200be8fabdf Author: Darren Tucker Date: Sat Nov 9 05:14:16 2024 +1100 Reshuffle OpenWRT test configs. Move the the flags used by the OpenWRT distro to mipsel target and enable OpenSSL on all targets to improve coverage. Explicitly disable security key and openssl on mips target so that host end of the bigendian interop tests don't attempt them and fail (since they're not enabled on the target side). commit d2709c461359e4129311cdff81ee05242d6c53cd Author: Darren Tucker Date: Sat Nov 9 03:26:08 2024 +1100 Add keytype to bigendian interop test. commit 50ac0f0e0627d29fd9becf5e15e8ceca5ad18078 Author: Darren Tucker Date: Sat Nov 9 03:24:29 2024 +1100 Ignore chown failure, eg due to dangling symlinks. commit 9e528e65a03245cf28e814f09b88c701bec935d1 Author: Darren Tucker Date: Sat Nov 2 18:05:41 2024 +1100 Test bigendian interop. Where our test target is a bigendian system, do an additional build on the runner host (which is little endian) and test interop between the two. Should hopefully catch obvious endianness bugs. commit dd416f5bfa96ac1ff44b27a93f7b55ee627c6baf Author: Darren Tucker Date: Fri Nov 1 19:44:29 2024 +1100 Allow overridding TEST_SSH_SSHD. This will allow tests to specify an alternative sshd, eg on a remote machine with different endianness. commit 82662d562cf54829df8a941cdfb2fd307e1d9a90 Author: djm@openbsd.org Date: Wed Nov 6 22:51:26 2024 +0000 upstream: ssh-agent implemented an all-or-nothing allow-list of FIDO application IDs for security key-backed keys, to prevent web key handles from being used remotely as this would likely lead to unpleasant surprises. By default, only application IDs that start with "ssh:*" are allowed. This adds a -Owebsafe-allow=... argument that can override the default list with a more or less restrictive one. The default remains unchanged. ok markus@ OpenBSD-Commit-ID: 957c1ed92a8d7c87453b9341f70cb3f4e6b23e8d commit 593a0b65c55c1e06a8c22b084aefc395aedb0127 Author: jca@openbsd.org Date: Mon Nov 4 21:59:15 2024 +0000 upstream: Ignore extra groups that don't fit in the buffer passed to getgrouplist(3) Our kernel supports 16 groups (NGROUPS_MAX), but nothing prevents an admin from adding a user to more groups. With that tweak we'll keep on ignoring them instead of potentially reading past the buffer passed to getgrouplist(3). That behavior is explicitely described in initgroups(3). ok millert@ gilles@ OpenBSD-Commit-ID: a959fc45ea3431b36f52eda04faefc58bcde00db commit e7adebeff3a9d038d0eaeeb0fcefedf29acb7e90 Author: Damien Miller Date: Mon Nov 4 14:39:27 2024 +1100 Add git signing key for Tim Rice commit da4b84845e874f12af7e0686170fa391c919d1df Author: Darren Tucker Date: Fri Nov 1 18:51:22 2024 +1100 Correct path to c-cpp.yml file in workflow config. commit 28740aa2c75392a9c4191eb9523f9b20853e2932 Author: Darren Tucker Date: Fri Nov 1 18:44:42 2024 +1100 Test new OpenSSL and LibreSSL releases.` commit a74809fe06540f16231b354ffe21fcbf39e81f73 Author: Darren Tucker Date: Fri Nov 1 18:44:00 2024 +1100 Add nbsd10 default test config. commit 88b35cbdc1500efece65cd6a9a20a72cf7e46eaa Author: Damien Miller Date: Wed Oct 30 14:25:14 2024 +1100 fix uint64_t types; reported by Tom G. Christensen commit ef7c26cd2f0f9a8222f851d1e551f6dfd3113f8b Author: Damien Miller Date: Sun Oct 27 13:28:11 2024 +1100 htole64() etc for systems without endian.h commit 0c3927c45f8a57b511c874c4d51a8c89414f74ef Author: djm@openbsd.org Date: Sun Oct 27 02:06:59 2024 +0000 upstream: explicitly include endian.h OpenBSD-Commit-ID: 13511fdef7535bdbc35b644c90090013da43a318 commit cf3e48ee8ba1beeccddd2f203b558fa102be67a2 Author: djm@openbsd.org Date: Sun Oct 27 02:06:01 2024 +0000 upstream: fix ML-KEM768x25519 KEX on big-endian systems; spotted by jsg@ feedback/ok deraadt@ OpenBSD-Commit-ID: 26d81a430811672bc762687166986cad40d28cc0 commit ae566d51b64fa3dce7063e7745b9b35f8f47abde Author: naddy@openbsd.org Date: Fri Oct 25 21:53:24 2024 +0000 upstream: mlkem768x25519-sha256 has been promoted to default key exchange OpenBSD-Commit-ID: 5a3259a193fd42108a869ebf650b95b5f2d08dcf commit 3af1dba1384ca896df6e973c70398c41d36de1ea Author: Darren Tucker Date: Fri Oct 25 19:04:30 2024 +1100 Retire the minix3 test config. It got broken by the sshd-auth change, it's not obvious why, and the platform lacks the debugging tools (eg gdb, strace) to figure it out. The upstream project seems effectively dead (6 years since the last commit, 10 since the last release). It was useful while it lasted (we found a real bug because of it) but its time seems to have passed. commit 3b240cc44b8de9175280ddbe59331317d427b0e3 Author: Preetish Amballi Date: Mon Oct 21 14:07:02 2024 +0000 Updated gitignore to ignore sshd-session and sshd-auth targets commit 326495744f06a0ab18ee0d16f87b3fe91cac92fb Author: Darren Tucker Date: Fri Oct 25 19:01:02 2024 +1100 Simplify pselect shim and remove side effects. Instead of maintaing state (pipe descriptors, signal handlers) across pselect-on-select invocations, set up and restore them each call. This prevents outside factors (eg a closefrom or signal handler installation) from potentially causing problems. This does result in a drop in throughput of a couple of percent on geriatric platforms without a native pselect due to the extra overhead. Tweaks & ok djm@ commit e53b615f3934ffac1efb3c1e491d126b9b09fd24 Author: djm@openbsd.org Date: Fri Oct 25 01:34:18 2024 +0000 upstream: promote mlkem768x25519-sha256 to be the default key exchange; ok markus@ OpenBSD-Commit-ID: fc673065e6505bb06b2e2b9362f78ccb4200a828 commit de644b1831b970f6655f871c051774cc871e8e74 Author: djm@openbsd.org Date: Thu Oct 24 03:28:34 2024 +0000 upstream: test SIGUSR1 dropping all keys from ssh-agent OpenBSD-Regress-ID: 8654b9aa8eb695b1499fffc408c25319592bf0e0 commit e86d7a077ce9a2b9ee9d4138c358a17cbdb786f9 Author: djm@openbsd.org Date: Thu Oct 24 03:15:47 2024 +0000 upstream: amake ssh-agent drop all keys when it receives SIGUSR1; let's users zap keys without access to $SSH_AUTH_SOCK ok deraadt@ OpenBSD-Commit-ID: dae9db0516b1011e5ba8c655ac702fce42e6c023 commit 94cdfebec852a2429c008cc2a55f8e4183f36972 Author: djm@openbsd.org Date: Thu Oct 24 03:14:37 2024 +0000 upstream: relax valid_domain() checks to allow an underscore as the first character. ok deraadt@ OpenBSD-Commit-ID: 3f8be6d32496e5596dd8b14e19cb067ddd7969ef commit 1b05d5437bf45bee5e3104772dea06ed51764f1b Author: dtucker@openbsd.org Date: Tue Oct 22 07:13:28 2024 +0000 upstream: Remove sshd logfile in start_sshd ... and ssh and sshd log wrappers before recreating them. Prevents "can't create" errors during tests when running tests without SUDO after having run them with SUDO. OpenBSD-Regress-ID: 2f0a83532e3dccd673a9bf0291090277268c69a6 commit 307ab3c7720f8879b835614b02687358ee4df9b9 Author: dtucker@openbsd.org Date: Tue Oct 22 06:16:26 2024 +0000 upstream: Add a sshd debug wrapper ... to run all of the subprograms from the build directory while developing and debugging. Should help prevent accidentally testing against unchanged installed sshd-auth and sshd-session binaries. ok djm@ OpenBSD-Commit-ID: 61760cdc98c2bc8f1e9f83a6f97cca0f66b52e69 commit 87bd1cb3ccba5e91d2650eb7f753c898ee43858e Author: dtucker@openbsd.org Date: Tue Oct 22 06:13:00 2024 +0000 upstream: Make debug call printf("%s", NULL) safe. Prevents problems on platforms where this isn't safe (which it's not required to be). ok djm@ OpenBSD-Commit-ID: 8fa4ce3ad90915c925b81b99a79ab920b0523387 commit c44c349edd157b2c00c42bd5ef5f9dfb37de26f3 Author: Darren Tucker Date: Tue Oct 22 17:48:32 2024 +1100 Resync cvsid missed in commit 6072e4c9. commit fe4305c37ffe53540a67586854e25f05cf615849 Author: djm@openbsd.org Date: Fri Oct 18 05:53:26 2024 +0000 upstream: mention that LocalForward and RemoteForward can accept Unix domain socket paths; GHPR115 OpenBSD-Commit-ID: a8a34d0a0c51a9ddab3dfce615f9878fa76ef842 commit 9c97b6af8e052ab5ffe0f9096fadc8f9a4d0ed0f Author: djm@openbsd.org Date: Fri Oct 18 05:45:40 2024 +0000 upstream: remove duplicate check; GHPR392 from Pedro Martelletto OpenBSD-Commit-ID: 597ab7dd3f0e78939d2659fc1904d0f39ee95487 commit d9cd208e89a471a3ff8adfcec68d6210af9e9fd5 Author: djm@openbsd.org Date: Fri Oct 18 05:37:24 2024 +0000 upstream: allow "-" as output file for moduli screening based on GHPR393 OpenBSD-Commit-ID: 1517763764eb55d03a6092dd120d2909c6fef0e1 commit 5eb5c4b2820d0636b1eccee646fb32ec946c4a95 Author: djm@openbsd.org Date: Fri Oct 18 05:32:51 2024 +0000 upstream: ssh-keyscan doesn't need it's own sshfatal() definition, it can use the shared one from fatal.c based on GHPR401 from lengyijun OpenBSD-Commit-ID: 8ea75ea99f27f464c9223cbc89cb046ccf9cd5c4 commit 0a1e75499e2c6fc258ee903645c878480949f362 Author: djm@openbsd.org Date: Fri Oct 18 05:14:51 2024 +0000 upstream: in _ssh_order_hostkeyalgs() consider ECDSA curve type when arranging the hostkey algorithms. AFAIK this code is unused in OpenSSH, but I guess others are using it based on GHPR387 from Pawel Jakub Dawidek OpenBSD-Commit-ID: 4d462495ac0c40f7b7dd66178e0005b9b2128225 commit d01ee7a88c5f4b1aa8c75a7c739f8f3bc1ad8bde Author: djm@openbsd.org Date: Fri Oct 18 05:03:34 2024 +0000 upstream: require control-escape character sequences passed via the '-e ^x' commandline to be exactly two characters long. Avoids one by OOB read if ssh is invoked as "ssh -e^ ..." Spotted by Maciej Domanski in GHPR368 OpenBSD-Commit-ID: baa72bc60898fc5639e6c62de7493a202c95823d commit 74ff6382f5743e09930e6cbd195dac65cd6062c9 Author: djm@openbsd.org Date: Fri Oct 18 04:30:09 2024 +0000 upstream: remove addr.[ch] functions that are unused and visbility-restrict ones that are unused outside the implementation itself; based on GHPR#282 by tobias@ OpenBSD-Commit-ID: a0140f2418b4d46cfaa7b33febc0a0931f9b2744 commit a9d6d7d93c533fa729f08b405e786d912553f33e Author: djm@openbsd.org Date: Fri Oct 18 04:14:59 2024 +0000 upstream: unreachable POLLERR case; from ya0guang via GHPR485 OpenBSD-Commit-ID: b3c82655190532b01eb817e532742cfaa4687eff commit d76424bf279ff951383e21213eb3759ea4090674 Author: djm@openbsd.org Date: Fri Oct 18 04:11:54 2024 +0000 upstream: s/Sx/Cm/ for external references; from Domen Puncer Kugler via GHPR501 OpenBSD-Commit-ID: f864a34feb5d5ff17160cf7c42ad0f7744fe8a3f commit ca204b994e2981e7bf95627b3105408917105649 Author: naddy@openbsd.org Date: Mon Oct 14 23:53:34 2024 +0000 upstream: mention SshdAuthPath option; ok djm@ OpenBSD-Commit-ID: 9a5d3add25e4e77bd3805bc5583a842ecf34d85c commit be27770e840c4dd9d9fcad1aa879400c727d7c2f Author: Darren Tucker Date: Fri Oct 18 13:37:55 2024 +1100 Remove references to systrace and pledge sandboxes. ok djm@ commit 49e64bf63fbf2f14961062dafe8ef08cb816bb08 Author: Pavel Miadzvedzeu Date: Wed Apr 24 10:19:56 2024 +0300 Fix "undeclared 'ut'" error by replacing it with 'utx' commit 67f684733f60f66479854a2867b953de731e71b2 Author: Darren Tucker Date: Thu Oct 17 20:50:29 2024 +1100 Seed RNG when starting up sshd-auth. Makes builds configured --without-openssl work again since otherwise the first use of the RNG comes after the sandbox init and it can't open /dev/random. commit c06c681aeebbe8e84e7410095514e7ee91f7e6cb Author: Darren Tucker Date: Thu Oct 17 19:18:23 2024 +1100 MacOS 12 runners are deprecated, replace with 15. commit 39db1f23bafb48a7c0cc9c65c716a0370f4cc677 Author: Damien Miller Date: Thu Oct 17 13:28:47 2024 +1100 Fix lookup path for sshd-auth; bz3745 commit c537eeb1ae5f069450053b0027e64efe5bdb37d2 Author: Damien Miller Date: Wed Oct 16 08:28:21 2024 +1100 fix breakage; missing saved_argc symbol commit 98a0883bdef28a06c7e017f27adf21ba57898bf4 Author: Damien Miller Date: Mon Oct 14 17:17:50 2024 +1100 fix capsicum sandbox commit 164ea4380564a2a83713eacf71908e3946e5e4e4 Author: Damien Miller Date: Mon Oct 14 17:16:41 2024 +1100 put back some portable bits for sshd-auth.c commit f8edf08c258ee2918689872c4702302052729726 Author: Damien Miller Date: Mon Oct 14 14:49:25 2024 +1100 there's only one sandbox, move to a static global commit 4482f0042b41d3d63c3845d7ba9fcf47c9252a84 Author: Damien Miller Date: Mon Oct 14 14:49:20 2024 +1100 depend commit 74856204a353a187dc6e7706c6cf84b7f14d775d Author: djm@openbsd.org Date: Mon Oct 14 03:02:08 2024 +0000 upstream: regress support for split sshd-auth binary OpenBSD-Regress-ID: df7d18a87b475f70004770f0f4e404adba5f6ab7 commit 461741083d7254595fecea274e60fe3ebf3ce3f9 Author: djm@openbsd.org Date: Fri Sep 27 01:05:54 2024 +0000 upstream: test some more Match syntax, including criteria=arg and negations OpenBSD-Regress-ID: 67476baccc60bf1a255fd4e329ada950047b8b8d commit 6072e4c9385713e9c166f32cfca6a7e603d4f0b8 Author: djm@openbsd.org Date: Mon Oct 14 01:57:50 2024 +0000 upstream: Split per-connection sshd-session binary This splits the user authentication code from the sshd-session binary into a separate sshd-auth binary. This will be executed by sshd-session to complete the user authentication phase of the protocol only. Splitting this code into a separate binary ensures that the crucial pre-authentication attack surface has an entirely disjoint address space from the code used for the rest of the connection. It also yields a small runtime memory saving as the authentication code will be unloaded after thhe authentication phase completes. Joint work with markus@ feedback deraadt@ Tested in snaps since last week OpenBSD-Commit-ID: 9c3b2087ae08626ec31b4177b023db600e986d9c commit fe6c6330c1a94c7a537efe9069853ce7a275c50a Author: djm@openbsd.org Date: Sun Oct 13 22:20:06 2024 +0000 upstream: don't start the ObscureKeystrokeTiming mitigations if there has been traffic on a X11 forwarding channel recently. Should fix X11 forwarding performance problems when this setting is enabled. Patch from Antonio Larrosa via bz3655 OpenBSD-Commit-ID: 820284a92eb4592fcd3d181a62c1b86b08a4a7ab commit 538cd28598ae942c94b99855b06fdd937e2e7381 Author: jsg@openbsd.org Date: Sat Oct 12 10:50:37 2024 +0000 upstream: remove duplicate misc.h include ok dtucker@ OpenBSD-Commit-ID: fdd056e7854294834d54632b4282b877cfe4c12e commit 0051381a8c33740a77a1eca6859efa1c78887d80 Author: djm@openbsd.org Date: Sun Oct 6 23:37:17 2024 +0000 upstream: Turn off finite field (a.k.a modp) Diffie-Hellman key exchange in sshd by default. Specifically, this removes the diffie-hellman-group* and diffie-hellman-group-exchange-* methods. The client is unchanged and continues to support these methods by default. Finite field Diffie Hellman is slow and computationally expensive for the same security level as Elliptic Curve DH or PQ key agreement while offering no redeeming advantages. ECDH has been specified for the SSH protocol for 15 years and some form of ECDH has been the default key exchange in OpenSSH for the last 14 years. ok markus@ OpenBSD-Commit-ID: 4e238ad480a33312667cc10ae0eb6393abaec8da commit 67a115e7a56dbdc3f5a58c64b29231151f3670f5 Author: djm@openbsd.org Date: Thu Sep 26 23:55:08 2024 +0000 upstream: fix previous change to ssh_config Match, which broken on negated Matches; spotted by phessler@ ok deraadt@ OpenBSD-Commit-ID: b1c6acec66cd5bd1252feff1d02ad7129ced37c7 commit 220b6c1290042acd5180d783dea01efe1365c265 Author: jsg@openbsd.org Date: Wed Sep 25 23:01:39 2024 +0000 upstream: remove some unused defines; ok djm@ OpenBSD-Commit-ID: 3a63e4e11d455704f684c28715d61b17f91e0996 commit 3ef4f6e8a4d774f73852391fdccbb95f39fc71bf Author: jmc@openbsd.org Date: Wed Sep 25 06:13:01 2024 +0000 upstream: remove some unneeded Xo/Xc calls; from evan silberman the original diff had a couple of errors, which i've fixed OpenBSD-Commit-ID: f37ad5888adbc0d4e1cd6b6de237841f4b1e650d commit 3f02368e8e9121847727c46b280efc280e5eb615 Author: djm@openbsd.org Date: Wed Sep 25 01:24:04 2024 +0000 upstream: fix regression introduced when I switched the "Match" criteria tokeniser to a more shell-like one. Apparently the old tokeniser (accidentally?) allowed "Match criteria=argument" as well as the "Match criteria argument" syntax that we tested for. People were using this syntax so this adds back support for "Match criteria=argument" bz3739 ok dtucker OpenBSD-Commit-ID: d1eebedb8c902002b75b75debfe1eeea1801f58a commit 9517cc58577f85a0ba5f8bb46778dff625f0688f Author: djm@openbsd.org Date: Tue Sep 24 02:28:17 2024 +0000 upstream: some extra paranoia, reminded by jsg@ OpenBSD-Commit-ID: 22072bfa1df1391858ae7768a6c627e08593a91e commit 815a94e86a68c1000b8310cb47695cea9329516c Author: Damien Miller Date: Wed Sep 25 11:15:45 2024 +1000 gss-serv.c needs sys/param.h From Void Linux commit 76a618d2842c34c16cd21a4efc7230e2f459008d Author: Damien Miller Date: Wed Sep 25 11:13:05 2024 +1000 build construct_utmp() when USE_BTMP is set Fixes compile error on Void Linux/Musl commit d3aee17f6d395202eaa42a0c449b6da41f61527c Author: Darren Tucker Date: Tue Sep 24 18:41:44 2024 +1000 Test the flags from OpenWRT's package. commit 0f5d19e6fe4b58a89e6dc8c71a2aae30365d193e Author: Christoph Ostarek Date: Wed Jul 3 12:46:59 2024 +0200 fix utmpx ifdef 02e16ad95fb1f56ab004b01a10aab89f7103c55d did a copy-paste for utmpx, but forgot to change the ifdef appropriately commit e03239f999acf9dc3da0f2f72bde36abbe678911 Author: jsg@openbsd.org Date: Sun Sep 22 12:56:21 2024 +0000 upstream: remove some unused defines; ok djm@ OpenBSD-Commit-ID: 81869ee6356fdbff19dae6ff757095e6b24de712 commit a35f543d3a6275fef781e515c262d1c687c3bc28 Author: jsg@openbsd.org Date: Fri Sep 20 02:00:46 2024 +0000 upstream: remove unneeded semicolons; checked by millert@ OpenBSD-Commit-ID: 3fb621a58e04b759a875ad6a33f35bb57ca80231 commit 1641f2d4d6e05d2147913442864cae546e64f08b Author: Darren Tucker Date: Mon Sep 23 20:52:31 2024 +1000 Add 9.9 branch to CI status console. commit 46d1fb16b20e971b9ac15e86a3d3e350b49c9ad6 Author: Damien Miller Date: Fri Sep 20 08:20:13 2024 +1000 update version numbers commit 0bdca1f218971b38728a0a129f482476baff0968 Author: djm@openbsd.org Date: Thu Sep 19 22:17:44 2024 +0000 upstream: openssh-9.9 OpenBSD-Commit-ID: 303417285f1a73b9cb7a2ae78d3f493bbbe31f98 commit ef2d7f2d3e1b4c9ae71bacf963e76a92ab8be543 Author: Damien Miller Date: Wed Sep 18 16:03:23 2024 +1000 include openbsd-compat/base64.c license in LICENSE commit 7ef362b989c8d1f7596f557f22e5924b9c08f0ea Author: Damien Miller Date: Wed Sep 18 09:01:23 2024 +1000 conditionally include mman.h in arc4random code commit 5fb2b5ad0e748732a27fd8cc16a7ca3c21770806 Author: Damien Miller Date: Tue Sep 17 11:53:24 2024 +1000 fix bug in recently-added sntrup761 fuzzer key values need to be static to persist across invocations; spotted by the Qualys Security Advisory team. commit 0ca128c9ee894f1b0067abd473bfb33171df67f8 Author: djm@openbsd.org Date: Mon Sep 16 05:37:05 2024 +0000 upstream: use 64 bit math to avoid signed underflow. upstream code relies on using -fwrapv to provide defined over/underflow behaviour, but we use -ftrapv to catch integer errors and abort the program. ok dtucker@ OpenBSD-Commit-ID: 8933369b33c17b5f02479503d0a92d87bc3a574b commit f82e5e22cad88c81d8a117de74241328c7b101c3 Author: jmc@openbsd.org Date: Sun Sep 15 08:27:38 2024 +0000 upstream: minor grammar/sort fixes for refuseconnection; ok djm OpenBSD-Commit-ID: 1c81f37b138b8b66abba811fec836388a0f3e6da commit 0c1165fc78e8fe69b5df71f81a8f944554a68b53 Author: Damien Miller Date: Sun Sep 15 13:30:13 2024 +1000 avoid gcc warning in fuzz test commit ce171d0718104b643854b53443ff72f7283d33f2 Author: djm@openbsd.org Date: Sun Sep 15 03:09:44 2024 +0000 upstream: bad whitespace in config dump output OpenBSD-Commit-ID: d899c13b0e8061d209298eaf58fe53e3643e967c commit 671c440786a5a66216922f15d0007b60f1e6733f Author: Damien Miller Date: Sun Sep 15 12:53:59 2024 +1000 use construct_utmp to construct btmp records Simpler and removes some code with the old-style BSD license. commit 930cb02b6113df72fbc732b9feb8e4f490952a81 Author: djm@openbsd.org Date: Sun Sep 15 02:20:51 2024 +0000 upstream: update the Streamlined NTRU Prime code from the "ref" implementation in SUPERCOP 20201130 to the "compact" implementation in SUPERCOP 20240808. The new version is substantially faster. Thanks to Daniel J Bernstein for pointing out the new implementation (and of course for writing it). tested in snaps/ok deraadt@ OpenBSD-Commit-ID: bf1a77924c125ecdbf03e2f3df8ad13bd3dafdcb commit 9306d6017e0ce5dea6824c29ca5ba5673c2923ad Author: djm@openbsd.org Date: Sun Sep 15 01:19:56 2024 +0000 upstream: document Match invalid-user OpenBSD-Commit-ID: 2c84a9b517283e9711e2812c1f268081dcb02081 commit 0118a4da21147a88a56dc8b90bbc2849fefd5c1e Author: djm@openbsd.org Date: Sun Sep 15 01:18:26 2024 +0000 upstream: add a "Match invalid-user" predicate to sshd_config Match options. This allows writing Match conditions that trigger for invalid username. E.g. PerSourcePenalties refuseconnection:90s Match invalid-user RefuseConnection yes Will effectively penalise bots try to guess passwords for bogus accounts, at the cost of implicitly revealing which accounts are invalid. feedback markus@ OpenBSD-Commit-ID: 93d3a46ca04bbd9d84a94d1e1d9d3a21073fbb07 commit 7875975136f275619427604900cb0ffd7020e845 Author: djm@openbsd.org Date: Sun Sep 15 01:11:26 2024 +0000 upstream: Add a "refuseconnection" penalty class to sshd_config PerSourcePenalties This allows penalising connection sources that have had connections dropped by the RefuseConnection option. ok markus@ OpenBSD-Commit-ID: 3c8443c427470bb3eac1880aa075cb4864463cb6 commit 8d21713b669b8516ca6d43424a356fccc37212bb Author: djm@openbsd.org Date: Sun Sep 15 01:09:40 2024 +0000 upstream: Add a sshd_config "RefuseConnection" option If set, this will terminate the connection at the first authentication request (this is the earliest we can evaluate sshd_config Match blocks) ok markus@ OpenBSD-Commit-ID: 43cc2533984074c44d0d2f92eb93f661e7a0b09c commit acad117e66018fe1fa5caf41b36e6dfbd61f76a1 Author: djm@openbsd.org Date: Sun Sep 15 00:58:01 2024 +0000 upstream: switch sshd_config Match processing to the argv tokeniser too; ok markus@ OpenBSD-Commit-ID: b74b5b0385f2e0379670e2b869318a65b0bc3923 commit baec3f7f4c60cd5aa1bb9adbeb6dfa4a172502a8 Author: djm@openbsd.org Date: Sun Sep 15 00:57:36 2024 +0000 upstream: switch "Match" directive processing over to the argv string tokeniser, making it possible to use shell-like quoting in Match directives, particularly "Match exec". ok markus@ OpenBSD-Commit-ID: 0877309650b76f624b2194c35dbacaf065e769a5 commit dd424d7c382c2074ab70f1b8ad4f169a10f60ee7 Author: djm@openbsd.org Date: Sun Sep 15 00:47:01 2024 +0000 upstream: include pathname in some of the ssh-keygen passphrase prompts. Helps the user know what's going on when ssh-keygen is invoked via other tools. Requested in GHPR503 OpenBSD-Commit-ID: 613b0bb6cf845b7e787d69a5b314057ceda6a8b6 commit 62bbf8f825cc390ecb0523752ddac1435006f206 Author: djm@openbsd.org Date: Sun Sep 15 00:41:18 2024 +0000 upstream: Do not apply authorized_keys options when signature verification fails. Prevents restrictive key options being incorrectly applied to subsequent keys in authorized_keys. bz3733, ok markus@ OpenBSD-Commit-ID: ba3776d9da4642443c19dbc015a1333622eb5a4e commit 49f325fd47af4e53fcd7aafdbcc280e53f5aa5ce Author: Wu Weixin Date: Fri Aug 2 22:16:40 2024 +0800 Fix without_openssl always being set to 1 In Fedora systems, %{?rhel} is empty. In RHEL systems, %{?fedora} is empty. Therefore, the original code always sets without_openssl to 1. commit c21c3a2419bbc1c59cb1a16ea356e703e99a90d9 Author: djm@openbsd.org Date: Thu Sep 12 00:36:27 2024 +0000 upstream: Relax absolute path requirement back to what it was prior to OpenSSH 9.8, which incorrectly required that sshd was started with an absolute path in inetd mode. bz3717, patch from Colin Wilson OpenBSD-Commit-ID: 25c57f22764897242d942853f8cccc5e991ea058 commit 1bc426f51b0a5cfdcfbd205218f0b6839ffe91e9 Author: naddy@openbsd.org Date: Mon Sep 9 14:41:21 2024 +0000 upstream: document the mlkem768x25519-sha256 key exchange algorithm OpenBSD-Commit-ID: fa18dccdd9753dd287e62ecab189b3de45672521 commit 0a2db61a5ffc64d2e2961c52964f933879952fc7 Author: Darren Tucker Date: Tue Sep 10 21:11:14 2024 +1000 Spell omnios test host correctly. commit 059ed698a47c9af541a49cf754fd09f984ac5a21 Author: Darren Tucker Date: Tue Sep 10 18:52:02 2024 +1000 Add omnios test target. commit f4ff91575a448b19176ceaa8fd6843a25f39d572 Author: Darren Tucker Date: Tue Sep 10 18:45:55 2024 +1000 Wrap stdint.h in ifdef. commit ff714f001d20a9c843ee1fd9d92a16d40567d264 Author: Darren Tucker Date: Mon Sep 9 19:31:54 2024 +1000 Also test PAM on dfly64. commit 509b757c052ea969b3a41fc36818b44801caf1cf Author: Damien Miller Date: Mon Sep 9 21:50:14 2024 +1000 stubs for ML-KEM KEX functions used for C89 compilers commit 273581210c99ce7275b8efdefbb9f89e1c22e341 Author: Damien Miller Date: Mon Sep 9 17:30:38 2024 +1000 declare defeat trying to detect C89 compilers I can't find a reliable way to detect the features the ML-KEM code requires in configure. Give up for now and use VLA support (that we can detect) as a proxy for "old compiler" and turn off ML-KEM if it isn't supported. commit e8a0f19b56dfa20f98ea9876d7171ec315fb338a Author: Damien Miller Date: Mon Sep 9 16:46:40 2024 +1000 fix previous; check for C99 compound literals The previous commit was incorrect (or at least insufficient), the ML-KEM code is actually using compound literals, so test for them. commit 7c07bec1446978bebe0780ed822c8fedfb377ae8 Author: Damien Miller Date: Mon Sep 9 16:06:21 2024 +1000 test for compiler feature needed for ML-KEM The ML-KEM implementation we uses need the compiler to support C99-style named struct initialisers (e.g foo = {.bar = 1}). We still support (barely) building OpenSSH with older compilers, so add a configure test for this. commit d469d5f348772058789d35332d1ccb0b109c28ef Author: djm@openbsd.org Date: Mon Sep 9 03:13:39 2024 +0000 upstream: test mlkem768x25519-sha256 OpenBSD-Regress-ID: 7baf6bc39ae55648db1a2bfdc55a624954847611 commit 62fb2b51bb7f6863c3ab697f397b2068da1c993f Author: djm@openbsd.org Date: Mon Sep 9 02:39:57 2024 +0000 upstream: pull post-quantum ML-KEM/x25519 key exchange out from compile-time flag now than an IANA codepoint has been assigned for the algorithm. Add mlkem768x25519-sha256 in 2nd KexAlgorithms preference slot. ok markus@ OpenBSD-Commit-ID: 9f50a0fae7d7ae8b27fcca11f8dc6f979207451a commit a8ad7a2952111c6ce32949a775df94286550af6b Author: djm@openbsd.org Date: Fri Sep 6 02:30:44 2024 +0000 upstream: make parsing user@host consistently look for the last '@' in the string rather than the first. This makes it possible to use usernames that contain '@' characters. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prompted by Max Zettlmeißl; feedback/ok millert@ OpenBSD-Commit-ID: 0b16eec246cda15469ebdcf3b1e2479810e394c5 commit 13cc78d016b67a74a67f1c97c7c348084cd9212c Author: djm@openbsd.org Date: Wed Sep 4 05:33:34 2024 +0000 upstream: be more strict in parsing key type names. Only allow shortnames (e.g "rsa") in user-interface code and require full SSH protocol names (e.g. "ssh-rsa") everywhere else. Prompted by bz3725; ok markus@ OpenBSD-Commit-ID: b3d8de9dac37992eab78adbf84fab2fe0d84b187 commit ef8472309a68e319018def6f8ea47aeb40d806f5 Author: djm@openbsd.org Date: Wed Sep 4 05:11:33 2024 +0000 upstream: fix RCSID in output OpenBSD-Commit-ID: 889ae07f2d2193ddc4351711919134664951dd76 commit ba2ef20c75c5268d4d1257adfc2ac11c930d31e1 Author: jmc@openbsd.org Date: Tue Sep 3 06:17:48 2024 +0000 upstream: envrionment -> environment; OpenBSD-Commit-ID: b719f39c20e8c671ec6135c832d6cc67a595af9c commit e66c0c5673a4304a3a9fbf8305c6a19f8653740f Author: Damien Miller Date: Wed Sep 4 15:35:29 2024 +1000 add basic fuzzers for our import of sntrup761 commit d19dea6330ecd4eb403fef2423bd7e127f4c9828 Author: djm@openbsd.org Date: Tue Sep 3 05:58:56 2024 +0000 upstream: regression test for Include variable expansion OpenBSD-Regress-ID: 35477da3ba1abd9ca64bc49080c50a9c1350c6ca commit 8c4d6a628051e318bae2f283e8dc38b896400862 Author: djm@openbsd.org Date: Tue Sep 3 05:29:55 2024 +0000 upstream: allow the "Include" directive to expand the same set of %-tokens that "Match Exec" and environment variables. ok dtucker@ OpenBSD-Commit-ID: 12ef521eaa966a9241e684258564f52f1f3c5d37 commit 51b82648b6827675fc0cde21175fd1ed8e89aab2 Author: djm@openbsd.org Date: Mon Sep 2 12:18:35 2024 +0000 upstream: missing ifdef OpenBSD-Commit-ID: 85f09da957dd39fd0abe08fe5ee19393f25c2021 commit f68312eb593943127b39ba79a4d7fa438c34c153 Author: djm@openbsd.org Date: Mon Sep 2 12:13:56 2024 +0000 upstream: Add experimental support for hybrid post-quantum key exchange ML-KEM768 with ECDH/X25519 from the Internet-draft: https://datatracker.ietf.org/doc/html/draft-kampanakis-curdle-ssh-pq-ke-03 This is based on previous patches from markus@ but adapted to use the final FIPS203 standard ML-KEM using a formally-verified implementation from libcrux. Note this key exchange method is still a draft and thus subject to change. It is therefore disabled by default; set MLKEM=yes to build it. We're making it available now to make it easy for other SSH implementations to test against it. ok markus@ deraadt@ OpenBSD-Commit-ID: 02a8730a570b63fa8acd9913ec66353735dea42c commit 05f2b141cfcc60c7cdedf9450d2b9d390c19eaad Author: Antonio Larrosa Date: Fri Aug 23 12:21:06 2024 +0200 Don't skip audit before exitting cleanup_exit This fixes an issue where the SSH_CONNECTION_ABANDON event is not audited because cleanup_exit overrides the regular _exit too soon and as a result, failed auth attempts are not logged correctly. The problem was introduced in 81c1099d22b81ebfd20a334ce986c4f753b0db29 where the code from upstream was merged before the audit_event call when it should have been merged right before the _exit call in order to honor the comment that just mentions an override of the exit value. commit 16eaf9d401e70996f89f3f417738a8db421aa959 Author: djm@openbsd.org Date: Wed Aug 28 12:08:26 2024 +0000 upstream: fix test: -F is the argument to specify a non-default ssh_config, not -f (this is sadly not a new bug) OpenBSD-Regress-ID: 45a7bda4cf33f2cea218507d8b6a55cddbcfb322 commit 10ccf611ab8ecba9ce6b0548c5ccd8c1220baf92 Author: deraadt@openbsd.org Date: Fri Aug 23 04:51:00 2024 +0000 upstream: As defined in the RFC, the SSH protocol has negotiable compression support (which is requested as the name "zlib"). Compression starts very early in the session. Relative early in OpenSSH lifetime, privsep was added to sshd, and this required a shared-memory hack so the two processes could see what was going on in the dataflow. This shared-memory hack was soon recognized as a tremendous complexity risk, because it put libz (which very much trusts it's memory) in a dangerous place, and a new option ("zlib@openssh.com") was added begins compression after authentication (aka delayed-compression). That change also permitted removal of the shared-memory hack. Despite removal from the server, the old "zlib" support remained in the client, to allow negotiation with non-OpenSSH daemons which lack the delayed-compression option. This commit deletes support for the older "zlib" option in the client. It reduces our featureset in a small way, and encourages other servers to move to a better design. The SSH protocol is different enough that compressed-key-material attacks like BEAST are unlikely, but who wants to take the chance? We encourage other ssh servers who care about optional compression support to add delayed-zlib support. (Some already do "zlib@openssh.com") ok djm markus OpenBSD-Commit-ID: 6df986f38e4ab389f795a6e39e7c6857a763ba72 commit aee54878255d71bf93aa6e91bbd4eb1825c0d1b9 Author: djm@openbsd.org Date: Thu Aug 22 23:11:30 2024 +0000 upstream: sntrup761x25519-sha512 now has an IANA codepoint assigned, so we can make the algorithm available without the @openssh.com suffix too. ok markus@ deraadt@ OpenBSD-Commit-ID: eeed8fcde688143a737729d3d56d20ab4353770f commit a76a6b85108e3032c8175611ecc5746e7131f876 Author: Darren Tucker Date: Thu Aug 22 20:36:12 2024 +1000 Move rekey test into valgrind-2. Now that the rekey test has been optimized it's fast enough to not be in its own valgrind test, so move it into valgrind-2, which is currently the quickest of the others, bringing all of them to roughly the same runtime of ~1.1 hours. commit 7e75e3f57c41b9a6e6401e7674d7c2ff5c33975b Author: dtucker@openbsd.org Date: Thu Aug 22 10:21:02 2024 +0000 upstream: Use aes128-ctr for MAC tests since default has implicit MAC. Also verify that the Cipher or MAC we intended to use is actually the one selected during the test. OpenBSD-Regress-ID: ff43fed30552afe23d1364526fe8cf88cbfafe1d commit ebc890b8b4ba08c84cd1066b7b94b2b11f6c4cb4 Author: Damien Miller Date: Thu Aug 22 09:45:49 2024 +1000 fix incorrect default for PasswordAuthentication merge botch spotted by gsgleason commit 15ace435ea1c2fab2a1cc7d9c3157fe20c776b80 Author: dtucker@openbsd.org Date: Wed Aug 21 10:33:27 2024 +0000 upstream: Some awks won't match on the \r so delete it instead. Fixes regress in portable on, eg Solaris. OpenBSD-Regress-ID: 44a96d6d2f8341d89b7d5fff777502b92ac9e9ba commit 51c96b6ed627779a04493a8fe25747996a37f3c2 Author: dtucker@openbsd.org Date: Wed Aug 21 07:06:27 2024 +0000 upstream: Import regenerated moduli. OpenBSD-Commit-ID: 5db7049ad5558dee5b2079d3422e8ddab187c1cc commit 25c52f37a82c4da48ec537de37d7c168982b8d6d Author: dtucker@openbsd.org Date: Wed Aug 21 06:59:08 2024 +0000 upstream: Use curve25519-sha256 kex where possible. Except where we're explicitly testing a different kex, use curve25519-sha256 since it's faster than the default and supported even when configured without OpenSSL. Add a check to ensure that the kex we intended to test is the one we actually tested. Speeds test up by ~5%. OpenBSD-Regress-ID: 3b27fcc2ae953cb08fd82a0d3155c498b226d6e0 commit 3eb62b7ba49483c309b483eb9002a679014f3887 Author: dtucker@openbsd.org Date: Tue Aug 20 12:36:59 2024 +0000 upstream: Send only as much data as needed to trigger rekeying. Speeds up tests by about 10% in the common case, hopefully more when instrumented with something like valgrind. OpenBSD-Regress-ID: 7bf9292b4803357efcf0baf7cfbdc8521f212da1 commit cbd3f034bbf7853618fac99d7d868a2250154ea7 Author: Damien Miller Date: Wed Aug 21 09:18:29 2024 +1000 simplify sshkey_prekey_alloc(); always use mmap commit 4442bbc2fc661277a6dabfedb756a7e15ee8b8b8 Author: dtucker@openbsd.org Date: Tue Aug 20 09:15:49 2024 +0000 upstream: Merge AEAD test into main test loop. Removes 3 duplicate tests and speeds overall test up by about 1%. OpenBSD-Regress-ID: 5e5c9ff3f7588091ed369e34ac28520490ad2619 commit 829976a63fd1efae3a4c3e7c16fded59d92edb67 Author: dtucker@openbsd.org Date: Tue Aug 20 09:02:45 2024 +0000 upstream: Set a default RekeyLimit of 256k. Used unless overridden by a command-line flag, which simplifies some of the ssh command lines. OpenBSD-Regress-ID: e7cffa57027088e10336e412b34113969f88cb87 commit 57d02c9ea36aebad4e7146d46e041b6b2e582f7f Author: dtucker@openbsd.org Date: Tue Aug 20 07:52:43 2024 +0000 upstream: Add Compression=no to default ssh_config. All of the rekey tests use it (otherwise the encrypted byte counts would not match) so this lets us simplify the command lines. OpenBSD-Regress-ID: dab7ce10f4cf6c68827eb8658141272aab3ea262 commit 7254eb26f7c0772c4b47c3b32f6d1b15855cdd8c Author: dtucker@openbsd.org Date: Tue Aug 20 07:41:35 2024 +0000 upstream: Remove duplicate curve25519-sha256 kex. curve25519-sha256@libssh.org is the pre-standardization name for the same thing, so remove it as a duplicate. Speeds up test by a tiny amount. OpenBSD-Regress-ID: 5a5ee5fa1595a6e140b1cc16040bedf5996a5715 commit 749896b874928c2785256cae4d75161dc3bfcc7d Author: dtucker@openbsd.org Date: Tue Aug 20 07:27:25 2024 +0000 upstream: Unnest rekey param parsing test and use ssh not sshd. ssh uses the same parsing code, now has "-G" to dump its config and is slightly faster to start up. This speeds up the test slightly (~5%) in the common case but should help more during instrumented tests, eg under valgrind, where startup costs are magnified. OpenBSD-Regress-ID: 07c3acaf4c728e641033071f4441afc88141b0d0 commit 2b1762115481ff2b7a60fd4db2ae69b725437462 Author: djm@openbsd.org Date: Tue Aug 20 11:10:04 2024 +0000 upstream: actually use the length parameter that was passed in rather than a constant (this makes no difference in practice because the length is always the same); reported by martin AT nmkd.net OpenBSD-Commit-ID: 4aecce232c2fe9b16e9217ff6bcb3c848d853e7e commit d922762ca16a7381131b242f49d7376c41fabcb5 Author: Damien Miller Date: Tue Aug 20 13:55:30 2024 +1000 private key coredump protection for Linux/FreeBSD platforms not supporting coredump exclusion using mmap/madvise flags fall back to plain old malloc(3). commit cc048ca536d6bed6f2285b07040b0d57cd559ba5 Author: djm@openbsd.org Date: Tue Aug 20 03:48:30 2024 +0000 upstream: place shielded keys (i.e. keys at rest in RAM) into memory allocated using mmap(3) with MAP_CONCEAL set. This prevents exposure of the key material in coredumps, etc (this is in addition to other measures we take in this area). ok deraadt@ OpenBSD-Commit-ID: cbbae59f337a00c9858d6358bc65f74e62261369 commit a0b35c791cad1f85481b23ba46373060292e1c80 Author: djm@openbsd.org Date: Sat Aug 17 08:35:04 2024 +0000 upstream: mention that ed25519 is the default key type generated and clarify that rsa-sha2-512 is the default signature scheme when RSA is in use. Based on GHPR505 from SebastianRzk OpenBSD-Commit-ID: 1d90df71636a04601685d2a10a8233bcc8d4f4c5 commit 127a50f2c80572ed1a021feb11ecf941e92cbbef Author: djm@openbsd.org Date: Sat Aug 17 08:23:04 2024 +0000 upstream: fix minor memory leak in Subsystem option parsing; from Antonio Larrosa via GHPR515 OpenBSD-Commit-ID: fff3bbefd1b2c45c98cbe45c6b857b15d8a2d364 commit 171427261d2079941eb1041079dbae875da37cbc Author: djm@openbsd.org Date: Sat Aug 17 08:09:50 2024 +0000 upstream: fix swapping of source and destination addresses in some sshd log messages OpenBSD-Commit-ID: 24d4cbb86325275df1f037545aa3b91456e52d25 commit 2a50a8f1fa57857a5e124a2280bcf61cc63c77f7 Author: Darren Tucker Date: Sat Aug 17 11:10:19 2024 +1000 Add compat functions for EVP_Digest{Sign,Verify}. This should make LibreSSL 3.1.x through 3.3.x work again. Code from tb@, ok djm@. Restore the test configs covering those. commit 1c3a7145260e03037cc18715b883880836fd122d Author: Philip Hands Date: Thu Aug 8 13:03:51 2024 +0200 make sure that usage & man page match SSH-Copy-ID-Upstream: da5b1abe55b72a16e0430e7598e1573da01779c0 commit cd0d681645b9adcf2467e7838bfd9d5142de4c4e Author: Philip Hands Date: Thu Aug 8 13:01:47 2024 +0200 update copyright notices Bump the year to 2024, but also reflect the fact that hands.com Ltd. has been wound up in the UK, and its assets (including this copyright) have now reverted to its owner, Philip Hands. SSH-Copy-ID-Upstream: 0e4c4d072747a6568b11a790c29dd1b4ce663d7f commit 7fc9ccdce18841ebd0a97e31e43258512ab32a32 Author: Philip Hands Date: Sun Aug 4 20:45:00 2024 +0200 restore optionality of -i's argument SSH-Copy-ID-Upstream: f70e3abb510e4eeb040b47894e41828246c1b720 commit c37aa7012b1a3c2c322fd19e71310aadc90fc674 Author: Philip Hands Date: Fri Aug 2 15:52:07 2024 +0200 avoid exploring .ssh/id*.pub subdirectories SSH-Copy-ID-Upstream: 0b9e08b7707ad16de3c8e6a0410d9f42fbd56997 commit 777dce9e2e0d12f7e81e162f77749f30899869fe Author: Philip Hands Date: Fri Aug 2 10:07:11 2024 +0200 ensure that we're always told the source of keys SSH-Copy-ID-Upstream: 1bee96f4793e8ec3fab9f9361204ae58f5cc7cae commit fb94fd2339848e40cad6c9bb42b822244cc1a7bc Author: Philip Hands Date: Wed Jul 31 23:19:51 2024 +0200 add $HOME to ERROR if one cannot write to ~/.ssh SSH-Copy-ID-Upstream: ebef3e9c06e0447bff06e9d84b33023cf592e0ba commit eb5aafa1ffaeee75799141ec5ded406a65ec7d18 Author: Philip Hands Date: Wed Jul 31 23:19:03 2024 +0200 assert that SCRATCH_DIR is a writable directory SSH-Copy-ID-Upstream: ecb2b9d10883b9a16df56c83896c9bb47a80cde2 commit abcc460a2af46f0d812f8433d97a8eae1d80724c Author: Philip Hands Date: Wed Jul 31 23:17:54 2024 +0200 quote to avoid potential for word splitting SSH-Copy-ID-Upstream: f379adbe06ac2ef1daf0f130752234c7f8b97e3c commit b3f91411fd1473605f74c40c1a91a024c7171e27 Author: Philip Hands Date: Wed Jul 31 23:15:11 2024 +0200 ensure ERROR output goes to STDERR SSH-Copy-ID-Upstream: ac394b05eead3b91feb7c2ae4129a3e9b892f1e2 commit 674b8f30f0dbacd787eb1e4e7e1ece34b5543d8f Author: Philip Hands Date: Thu Aug 1 14:03:06 2024 +0200 avoid extra space when no arg given to -i option SSH-Copy-ID-Upstream: feca9e67e6e37c5653445d1c733569d7abb1770e commit 0efa0e1c41427c0c6ba839a18c72c1afcd7b7cc0 Author: Philip Hands Date: Wed Jul 31 23:28:36 2024 +0200 put the -i before -[pP] (matching man pages) The man pages (ssh, sftp & ssh-copy-id) all list -i before the port setting, so make the output match that order, which also seems more natural with the port being next to the server. SSH-Copy-ID-Upstream: 34d5d614172c78f9a42249466c4b81975b8883a1 commit 87831345e9745f2d13bd7a4a7972809f6788f331 Author: Shreyas Mahangade Date: Mon Jul 29 15:26:05 2024 +0000 Minor space issue fixed SSH-Copy-ID-Upstream: 335e44d7be78b03962a54c3a5c99a2ff45294a54 commit 2f3010f4736b4b3f5c10a4be97a24e90ff04c5e7 Author: Shreyas Mahangade Date: Mon Jul 29 16:55:28 2024 +0530 Show identity file in 'ssh' command - Previously no identity file is shown in "ssh" command output on the line "Now try logging into the..." - This commit makes sure whenever "ssh-copy-id" with "-i" is invoked, it also reflects in "ssh" command SSH-Copy-ID-Upstream: 58e022ec26cb2315eb3be581d01e0ba787082428 commit a13856374b894397a7682b32257ed0bf67cfede9 Author: Damien Miller Date: Fri Aug 16 08:30:20 2024 +1000 more OPENSSL_HAS_ECC commit 4da2a1a7f648979bea6eaf3b17f5f250faed4afc Author: Damien Miller Date: Thu Aug 15 23:35:54 2024 +1000 fix merge botch that broke !OPENSSL_HAS_ECC commit 2c53d2f32b8e3992b61682c909ae5bc5122b6e5d Author: Damien Miller Date: Thu Aug 15 15:09:45 2024 +1000 missed OPENSSL_HAS_ECC case commit 342dd7a219f39119b8b686b5aaa99c8e15ede368 Author: Damien Miller Date: Thu Aug 15 15:06:55 2024 +1000 retire testing aginst older LibreSSL versions libressl prior to 3.4.x lack support for the EVP_DigestSign and EVP_DigestVerify APIs that we need now that sshkey is converted to EVP_PKEY. If someone makes a good case for why we should support these versions then we could bring back support with wrappers. commit a7c6ea8eebe0f179141ec5dbf0c9e5354417930f Author: Damien Miller Date: Thu Aug 15 12:44:17 2024 +1000 sync TEST_MALLOC_OPTIONS for OpenBSD commit 60c2cf22e8f64f35d8b1175e4671257313f2e4d3 Author: Damien Miller Date: Thu Aug 15 12:43:47 2024 +1000 remove gratuitious difference from OpenBSD commit 339c4fc60a6250429d41fa8713f783d82aad4551 Author: djm@openbsd.org Date: Thu Aug 15 00:52:23 2024 +0000 upstream: adapt to EVP_PKEY conversion OpenBSD-Regress-ID: 0e2d4efb0ed0e392e23cd8fda183fe56531ac446 commit 63a94f99b9d7c8a48182a40192e45879d1ba8791 Author: djm@openbsd.org Date: Fri Jul 19 04:33:36 2024 +0000 upstream: test transfers in mux proxy mode too OpenBSD-Regress-ID: 2edfc980628cfef3550649cab8d69fa23b5cd6c4 commit 7bdfc20516e288b58c8c847958059c7b141eeff9 Author: djm@openbsd.org Date: Thu Aug 15 00:51:51 2024 +0000 upstream: Convert RSA and ECDSA key to the libcrypto EVP_PKEY API. DSA remains unconverted as it will be removed within six months. Based on patches originally from Dmitry Belyavskiy, but significantly reworked based on feedback from Bob Beck, Joel Sing and especially Theo Buehler (apologies to anyone I've missed). ok tb@ OpenBSD-Commit-ID: d098744e89f1dc7e5952a6817bef234eced648b5 commit 0af06e2c5b898992a18c74333e75a0136506acc6 Author: tobias@openbsd.org Date: Wed Aug 14 15:42:18 2024 +0000 upstream: Reorder calloc arguments The first argument should be the amount, the second argument should be the element size. Fixing this also silences some gcc compiler warnings for portable. Spotted with Benny Baumann (BenBE at geshi dot org). ok djm@ OpenBSD-Commit-ID: 711ad6f7bd7fb48bf52208f2cf9f108cddb6d41a commit 56ce0aa3c6cf28d9fcbce3207457abeac91b5050 Author: tobias@openbsd.org Date: Wed Aug 14 15:40:30 2024 +0000 upstream: Extend sshbuf validation Multiple sshbuf structs can be linked through a parent/child relationship. Make sure that a single sshbuf cannot be its own parent. If this would ever happen, it would result in reference counting issues. This is a cheap way of testing this with very little overhead. It does not detect A->B->A linkages though for performance reason and the fact that it takes a programming error for this to occur anyway. Authored with Benny Baumann (BenBE at geshi dot org). ok djm@ OpenBSD-Commit-ID: fb3fa9ee2cad3c7e842ebadfd7f5db220c4aaf16 commit fc48ddf6998188517af42dce807e2088b6a0c0be Author: tobias@openbsd.org Date: Wed Aug 14 15:37:11 2024 +0000 upstream: Use freezero for better readability It has the same meaning as the current pair of calling explicit_bzero and free. Spotted with Benny Baumann (BenBE at geshi dot org). ok djm@ OpenBSD-Commit-ID: 939fbe9ccf52d0d48c5fa53694d6f3bb9927970c commit 1ff6907ec26dac6ac59fe9fe232899a63b4c14d8 Author: tobias@openbsd.org Date: Wed Aug 14 15:35:23 2024 +0000 upstream: Fix typo in comment Spotted with Benny Baumann (BenBE at geshi dot org). ok djm@ OpenBSD-Commit-ID: 829160ac8ef3ad3409695ce3a3ade835061cae57 commit 487faaed8f3bb9ffb19e8f807a3da72895b16421 Author: dlg@openbsd.org Date: Wed Jul 31 12:00:18 2024 +0000 upstream: add a random amount of time (up to 4 seconds) to the grace login time. ok deraadt@ djm@ OpenBSD-Commit-ID: abd3c57aaa5861517529b322df79b6be35ee67f4 commit 2865f5b7520bed3e74fbbb5f8d7a44193d7a4314 Author: naddy@openbsd.org Date: Fri Jul 26 15:24:49 2024 +0000 upstream: document the reduced logingrace penalty OpenBSD-Commit-ID: 9b63e0e3599d524ddc10edc4f978081382c3548b commit 1ec0a64c5dc57b8a2053a93b5ef0d02ff8598e5c Author: Darren Tucker Date: Sun Jul 28 21:26:51 2024 +1000 Explicitly install libssl-devel cygwin. Should fix CI tests for cygwin default config. commit 0bf6e5bb750b66b25c20a1c5a471f91850de3748 Author: djm@openbsd.org Date: Thu Jul 25 23:44:01 2024 +0000 upstream: reduce logingrace penalty. A single forgotton login that times out should be below the penalty threshold. ok deraadt/claudio OpenBSD-Commit-ID: cee1f7d17597c97bff8e5092af5d136fdb08f81d commit 29fb6f6d46b67770084b4f12bcf8a01bd535041b Author: djm@openbsd.org Date: Thu Jul 25 22:40:08 2024 +0000 upstream: Fix proxy multiplexing (-O proxy) bug If a mux started with ControlPersist then later has a forwarding added using mux proxy connection and the forwarding was used, then when the mux proxy session terminates, the mux master process will send a channel close to the server with a bad channel ID and crash the connection. This was caused by my stupidly reusing c->remote_id for mux channel associations when I should have just added another member to struct channel. ok markus@ OpenBSD-Commit-ID: c9f474e0124e3fe456c5e43749b97d75e65b82b2 commit 53d1d307438517805989c7d5616d752739a97e03 Author: djm@openbsd.org Date: Thu Jul 18 01:47:27 2024 +0000 upstream: mention mux proxy mode OpenBSD-Commit-ID: fd77a77779f06d316a314e4540dc57c93fc3369a commit a9b90859d252c2f5a24142f985d38610ac74685f Author: jsg@openbsd.org Date: Sun Jul 14 10:19:23 2024 +0000 upstream: fix double word; ok dtucker@ OpenBSD-Commit-ID: e6aff005914fa350b896d2be030be3d3b56ec0e8 commit b05fda224bbcd2f641254534ed2175c42487f3c8 Author: Darren Tucker Date: Thu Jul 25 17:59:35 2024 +1000 Check for SA_RESTART before using it. ok djm@ commit c276672fc0e99f0c4389988d54a84c203ce325b6 Author: Yuichiro Naito Date: Wed Sep 1 10:19:32 2021 +0900 Class-imposed login restrictions If the following functions are available, add an additional check if users are allowed to login imposed by login class. * auth_hostok(3) * auth_timeok(3) These functions are implemented on FreeBSD. commit 7717b9e9155209916cc6b4b4b54f4e8fa578e889 Author: djm@openbsd.org Date: Wed Jul 10 21:58:34 2024 +0000 upstream: correct keyword; from Yatao Su via GHPR509 OpenBSD-Commit-ID: 81c778c76dea7ef407603caa157eb0c381c52ad2 commit f2b78bb8f149d6b4d1f62c21aa1f06995dccf4ce Author: djm@openbsd.org Date: Mon Jul 8 03:04:34 2024 +0000 upstream: don't need return at end of void function OpenBSD-Commit-ID: 42d322d37f13aa075ae7b1ad9eef591e20b89717 commit a395d37a813c0177cb5bfc4bebf5a52badb73cf0 Author: djm@openbsd.org Date: Thu Jul 4 22:53:59 2024 +0000 upstream: fix grammar: "a pattern lists" -> "one or more pattern lists" OpenBSD-Commit-ID: f3c844763398faa9800687e8ff6621225498202a commit 8b664df75966e5aed8dabea00b8838303d3488b8 Author: Darren Tucker Date: Sun Jul 7 18:46:19 2024 +1000 Cast to sockaddr * in systemd interface. Fixes build with musl libx. bz#3707. commit 30c8c81da2169e78357d08dbb0ddd823b60e93bc Author: Darren Tucker Date: Thu Jul 4 20:12:26 2024 +1000 Add 9.8 branch to ci-status page. commit ee6b9e661633fcefd29dba0c811cecbc4d027f6f Author: Samuel Thibault Date: Tue Mar 26 22:15:08 2024 +0100 Fix detection of setres*id on GNU/Hurd Like Linux, proper _SOURCE macros need to be set to get declarations of various standard functions, notably setres*id. Now that Debian is using -Werror=implicit-function-declaration this is really required. While at it, define other _SOURCE macros like on GNU/Linux, since GNU/Hurd uses the same glibc. commit fa41f6592ff1b6ead4a652ac75af31eabb05b912 Author: Damien Miller Date: Mon Jul 1 14:33:26 2024 +1000 version numbers commit bfebb8a5130a792c5356bd06e1ddef72a0a0449f Author: djm@openbsd.org Date: Mon Jul 1 04:31:59 2024 +0000 upstream: openssh-9.8 OpenBSD-Commit-ID: 5f8b89e38a4c5f7c6d52ffa19f796d49f36fab19 commit 146c420d29d055cc75c8606327a1cf8439fe3a08 Author: djm@openbsd.org Date: Mon Jul 1 04:31:17 2024 +0000 upstream: when sending ObscureKeystrokeTiming chaff packets, we can't rely on channel_did_enqueue to tell that there is data to send. This flag indicates that the channels code enqueued a packet on _this_ ppoll() iteration, not that data was enqueued in _any_ ppoll() iteration in the timeslice. ok markus@ OpenBSD-Commit-ID: 009b74fd2769b36b5284a0188ade182f00564136 commit 637e4dfea4ed81264e264b6200172ce319c64ead Author: djm@openbsd.org Date: Mon Jul 1 03:10:19 2024 +0000 upstream: use "lcd" to change directory before "lls" rather then "cd", since the directory we're trying to list is local. Spotted by Corinna Vinschen OpenBSD-Regress-ID: 821feca4a4bebe491944e624c8f7f2990b891415 commit c8cfe258cee0b8466ea84597bf15e1fcff3bc328 Author: djm@openbsd.org Date: Thu Jun 27 23:01:15 2024 +0000 upstream: delete obsolete comment OpenBSD-Commit-ID: 5fb04f298ed155053f3fbfdf0c6fe7cdf84bbfa2 commit 94b9d37100f6fa536aaa1d1a0e4926fe44fbf04d Author: djm@openbsd.org Date: Thu Jun 27 22:36:44 2024 +0000 upstream: retire unused API OpenBSD-Commit-ID: 3e30d7b0615e2707f6bbe70f61b1c2f72f78161b commit 268c3a7f5783e731ed60f4e28da66ee3743581d3 Author: jmc@openbsd.org Date: Thu Jun 27 21:02:16 2024 +0000 upstream: ssl(8) no longer contains a HISTORY section; OpenBSD-Commit-ID: 83b7ff34433d79595e9c2a5d2a561a6660251245 commit 12b6cc09ce6c430681f03af2a8069e37a664690b Author: djm@openbsd.org Date: Wed Jun 26 23:47:46 2024 +0000 upstream: move child process waitpid() loop out of SIGCHLD handler; ok deraadt OpenBSD-Commit-ID: 65815a39564e431414aed7c5ace8076f4e9ca741 commit d6bcd13297c2ab8b528df5a6898f994734849031 Author: deraadt@openbsd.org Date: Wed Jun 26 23:16:52 2024 +0000 upstream: Instead of using possibly complex ssh_signal(), write all the parts of the grace_alarm_handler() using the exact things allowed by the signal-safe rules. This is a good rule of thumb: Handlers should be written to either set a global volatile sig_atomic_t inspected from outside, and/or directly perform only safe operations listed in our sigaction(2) manual page. ok djm markus OpenBSD-Commit-ID: 14168ae8368aab76e4ed79e17a667cb46f404ecd commit b8793e2b0851f7d71b97554fa5260b23796d6277 Author: deraadt@openbsd.org Date: Wed Jun 26 23:14:14 2024 +0000 upstream: save_errno wrappers inside two small signal handlers that perform system calls, for systems with libc that do perform libc sigtramps. ok djm markus OpenBSD-Commit-ID: 7749b56419a7c9dcfe4c6c04811e429813346c62 commit f23e9332c4c8df37465c4a4f38275ea98980ed7e Author: jmc@openbsd.org Date: Mon Jun 24 06:59:39 2024 +0000 upstream: - uppercase start of sentence - correct sentence grammar ok djm OpenBSD-Commit-ID: 1ec4b0fdb633a43667f2c8fff1d600bd647dde25 commit 1839e3eb71a759aa795602c1e4196300f4ac2615 Author: djm@openbsd.org Date: Mon Jun 24 04:05:11 2024 +0000 upstream: mention SshdSessionPath option OpenBSD-Commit-ID: c29734d36c21003973b15c1c9965c35f36cef30c commit 603193e32aef5db7d60c58066d5de89806e79312 Author: Darren Tucker Date: Thu Jun 20 18:45:14 2024 +1000 Rerun upstream tests on .sh file changes too. commit dbbf9337c19381786a8e5a8a49152fe6b80c780d Author: dtucker@openbsd.org Date: Thu Jun 20 08:23:18 2024 +0000 upstream: Work around dbclient cipher/mac query bug. Unlike earlier versions, recent Dropbear (at least v2024.85) requires a host arg when querying supported ciphers and macs via "-c/-m help". Earlier versions accept but do not require it, so always provide it. If these queries fail, skip the test with a warning. OpenBSD-Regress-ID: 98eb863a3f0363416922efb273885e6b3c7f68d4 commit 8de2c8cebc46bbdb94b7a2c120fcadfb66a3cccc Author: dtucker@openbsd.org Date: Thu Jun 20 08:18:34 2024 +0000 upstream: Remove dropbear key types not supported by current OpenSSH. Allows subsequent test runs to work if OpenSSH is rebuilt w/out OpenSSL. OpenBSD-Regress-ID: e0129eb2b1d31771105903a8055216fbba20a770 commit e9b6471c59b21e5d9ef1b3832d4bf727338add85 Author: djm@openbsd.org Date: Thu Jun 20 00:18:05 2024 +0000 upstream: stricter check for overfull tables in penalty record path OpenBSD-Commit-ID: 7df01e648a0723418c554e64a9f2b6d38db060a6 commit d9336d344eb2a1e898c5e66147b3f108c7214694 Author: djm@openbsd.org Date: Wed Jun 19 23:24:47 2024 +0000 upstream: put back reaping of preauth child process when writes from the monitor fail. Not sure how this got lost in the avalanche of patches. OpenBSD-Commit-ID: eb7eb36371e1ac01050b32b70fb2b3e5d98e72f5 commit 579d9adb70ec0206a788eb5c63804c31a67e9310 Author: naddy@openbsd.org Date: Mon Jun 17 13:50:18 2024 +0000 upstream: remove one more mention of DSA OpenBSD-Commit-ID: 8515f55a15f02836ba657df341415f63c60526ca commit 7089b5f8436ef0b8d3d3ad9ce01045fb9e7aab15 Author: Darren Tucker Date: Wed Jun 19 23:09:05 2024 +1000 Move -f to the place needed to restart sshd. commit d5f83cfd852b14a25f347f082ab539a9454702ad Author: Darren Tucker Date: Wed Jun 19 21:04:01 2024 +1000 Need to supply "-f" to restart sshd. commit fad34b4ca25c0ef31e5aa841d461b6f21da5b8c1 Author: dtucker@openbsd.org Date: Wed Jun 19 10:15:51 2024 +0000 upstream: Provide defaults for ciphers and macs if querying for them fails since on some versions of Dropbear (at least v2024.85) "-m help" doesn't seem to work. Enable all supported pubkey algorithms in the server. OpenBSD-Regress-ID: 4f95556a49ee9f621789f25217c367a33d2745ca commit 5521060e35ada9f957cecdddc06d0524e75409ef Author: dtucker@openbsd.org Date: Wed Jun 19 10:10:46 2024 +0000 upstream: Use ed25519 keys for kex tests since that's supported by OpenSSH even when built without OpenSSL. Only test diffie-hellman kex if OpenSSH is compiled with support for it. OpenBSD-Regress-ID: a5d09ef9bbd171f9e4ec73ed0d9eeb49a8878e97 commit dbd3b833f6e3815e58f2dc6e14f61a51bcd4d6bd Author: dtucker@openbsd.org Date: Wed Jun 19 10:08:34 2024 +0000 upstream: Rework dropbear key setup to always generate ed25519 keys, other types only if OpenSSH has support for the corresponding key type. OpenBSD-Regress-ID: 8f91f12604cddb9f8d93aa34f3f93a3f6074395d commit d6218504e11ae9148adf410fc69b0710a052be36 Author: Darren Tucker Date: Wed Jun 19 20:20:24 2024 +1000 Restart sshd after installing it for testing. When installing an sshd built without OpenSSL the mismatch between the running sshd and newly installed sshd-session will cause the remainder of the test to fail. commit 786a4465b6bb702daf4fb17b7c3bcb42b52f0b46 Author: Darren Tucker Date: Tue Jun 18 19:59:59 2024 +1000 Remove macos-11 runner. Github is retiring them soon. commit df1c72a55edbebac14363b57de66ac6a147ecc67 Author: Damien Miller Date: Wed Jun 19 09:34:34 2024 +1000 PAMServiceName may appear in a Match block commit de1c2e70e5a5dc3c8d2fe04b24cc93d8ef6930e7 Author: dtucker@openbsd.org Date: Tue Jun 18 08:11:48 2024 +0000 upstream: Re-enable ssh-dss tests ... if ssh is compiled with DSA support OpenBSD-Regress-ID: bbfaf8c17f2b50a2d46ac35cb97af99b990c990d commit dabc2c7cf3c141e8e5d5a1a60d6c1d2d2422cf43 Author: anton@openbsd.org Date: Tue Jun 18 06:14:27 2024 +0000 upstream: Stop using DSA in dropbear interop tests. OpenBSD-Regress-ID: abfd4457d99d8cc1417fd22ca2c570270f74c1cf commit 761438012710169445acc179e3870c53c862bda0 Author: Damien Miller Date: Tue Jun 18 12:29:45 2024 +1000 missed a bit of DSA in the fuzzer commit 3f9cc47da588e8de520720e59f98438043fdaf93 Author: Damien Miller Date: Tue Jun 18 09:35:53 2024 +1000 DSA support is disabled, so remove from fuzzers commit 00eb95957dea5484b2c7c043f7d2bbc87301bef2 Author: djm@openbsd.org Date: Mon Jun 17 08:30:29 2024 +0000 upstream: disable the DSA signature algorithm by default; ok markus@ (yes, I know this expands to "the Digitial Signature Algorithm signature algorithm) OpenBSD-Commit-ID: 961ef594e46dd2dcade8dd5721fa565cee79ffed commit 5603befe11c9464ea26fe77cbacc95a7cc0b1ea7 Author: djm@openbsd.org Date: Mon Jun 17 08:28:31 2024 +0000 upstream: promote connection-closed messages from verbose to info log level; they could be the only record of the connection terminating if the client doesn't send a SSH2_MSG_DISCONNECT message. ok dtucker@ OpenBSD-Commit-ID: 0c8bfaf5e9fdff945cee09ac21e641f6c5d65d3c commit b00331402fe5c60d577f3ffcc35e49286cdc6b47 Author: Damien Miller Date: Mon Jun 17 17:02:18 2024 +1000 propagate PAM crashes to PerSourcePenalties If the PAM subprocess crashes, exit with a crash status that will be picked up by the sshd(8) listener process where it can be used by PerSourcePenalties to block the client. This is similar handling to the privsep preauth process. commit 1c207f456ace38987deda047758d13fbf857f948 Author: Damien Miller Date: Mon Jun 17 15:06:01 2024 +1000 minix doesn't have loopback, so skip penalty tests pointed out by dtucker@ commit 48443d202eaec52d4d39defdd709a4499a7140c6 Author: djm@openbsd.org Date: Sun Jun 16 11:54:49 2024 +0000 upstream: same treatment for this test OpenBSD-Regress-ID: d0cc9efca7833e673ea7b0cb3a679a3acee8d4c7 commit 45562a95ea11d328c22d97bf39401cd29684fb1f Author: djm@openbsd.org Date: Sun Jun 16 08:18:06 2024 +0000 upstream: penalty test is still a bit racy OpenBSD-Regress-ID: 90c9ac224db454637baf1ebee5857e007321e824 commit 8d0f7eb147ef72d18acb16c0b18672d44941a8ca Author: djm@openbsd.org Date: Sat Jun 15 03:59:10 2024 +0000 upstream: crank up penalty timeouts so this should work on even the slowest of test builders OpenBSD-Regress-ID: 70bda39c83e3fc9d0f3c1fad4542ed33e173d468 commit 93c75471a1202ab3e29db6938648d4e2602c0475 Author: jmc@openbsd.org Date: Fri Jun 14 05:20:34 2024 +0000 upstream: sort -q in the options list; OpenBSD-Commit-ID: 6839b38378f38f754de638a5e988c13b4164cc7c commit dd7807bbe80a93ffb4616f2bd5cf83ad5a5595fb Author: djm@openbsd.org Date: Fri Jun 14 05:01:22 2024 +0000 upstream: clarify KEXAlgorithms supported vs available. Inspired by bz3701 from Colin Watson. OpenBSD-Commit-ID: e698e69bea19bd52971d253f2b1094490c4701f7 commit d172ad56df85b68316dbadbedad16761a1265874 Author: djm@openbsd.org Date: Fri Jun 14 05:00:42 2024 +0000 upstream: ssh-keyscan -q man bits OpenBSD-Commit-ID: ba28d0e1ac609a4c99c453e57e86560c79079db1 commit 092e4ff9ccaacbe035f286feb1b56ed499604743 Author: Damien Miller Date: Fri Jun 14 14:46:35 2024 +1000 skip penalty-expire test in valgrind test env commit 2866ad08a9c50d7b67ce9424ca990532b806a21a Author: djm@openbsd.org Date: Fri Jun 14 04:43:11 2024 +0000 upstream: split the PerSourcePenalties test in two: one tests penalty enforcement but not penalty expiry, the other tests penalty expiry. This lets us disable the expiry testing in certain CI test environments. OpenBSD-Regress-ID: f56811064f3e3cb52ee73a206b8c2a06af1c8791 commit b2c64bc170d75823622a37cab3ca1804ca87ad16 Author: Damien Miller Date: Fri Jun 14 14:19:23 2024 +1000 add a sshd_config PamServiceName option Allows selecting which PAM service name to use when UsePAM is enabled. Defaults to "sshd" unless overridden at compile time by defining SSHD_PAM_SERVICE. bz2102, ok dtucker@ commit 9f032a4dd17bf0ae6066223d82aa5e784285d987 Author: djm@openbsd.org Date: Fri Jun 14 00:26:12 2024 +0000 upstream: don't redirect stderr for ssh-keyscan we expect to succeed OpenBSD-Regress-ID: 8878b8eb4e070ed2e343166d3eb86db4a08a216c commit 1e84d0cf40e94ae3a77d6a7ca8c036d8e3d55a40 Author: djm@openbsd.org Date: Fri Jun 14 00:25:25 2024 +0000 upstream: make host/banner comments go to stderr instead of stdout, so they are useful as comments without extra shell redirection and so they don't clutter actual errors on stderr. Add a -q flag to shut them up. ok dtucker@ OpenBSD-Commit-ID: bec813de56a71adb5c1a76adcf49621130d24264 commit 3e806d011855d6bd648ec95b9df630ebbd11c3bf Author: naddy@openbsd.org Date: Thu Jun 13 15:06:33 2024 +0000 upstream: separate keywords with comma OpenBSD-Commit-ID: d65a99666202a8188c4991c18d14374a229f7be5 commit abfd1f7a3cbd0a92581a0febba254b2f6649c0d9 Author: djm@openbsd.org Date: Fri Jun 14 00:23:55 2024 +0000 upstream: specify an algorithm for ssh-keyscan, otherwise it will make multiple attempts simultaneously and confuse the test OpenBSD-Regress-ID: 6e910f3315c4345053db1bf5cbf61826b194d0b9 commit a8fbe2f7d0d96d299ee8e69769e3b51067978748 Author: Damien Miller Date: Thu Jun 13 16:41:29 2024 +1000 sshd: don't use argv[0] as PAM service name sshd would implicitly use argv[0] as the PAM service name to allow people to select different PAM service names by making differently-named copies/links to the sshd binary. Splitting sshd into sshd/sshd-session broke this, as the process that starts PAM is always sshd-session and the user has no control over this. Hardcode "sshd" as the default PAM service name unless/until we figure out a better way. Should unbreak OSX integration tests. commit bf204bd05c3ae650f87e2b96527688579f59774c Author: Damien Miller Date: Thu Jun 13 15:00:28 2024 +1000 prepare for checking in autogenerated files We plan to check in automatically generated files (config.h.in, etc) on release branches. These files are normally ignored by .gitignore, but this shuffles the contents of this file to make it easy to un-ignore them. commit 425f79a837489904c343b349ef00e09aeaa4e752 Author: Damien Miller Date: Thu Jun 13 14:41:33 2024 +1000 typo in comment commit afe10313c1fa8d478af399ee7d54c8f85503013b Author: Damien Miller Date: Thu Jun 13 14:35:25 2024 +1000 fix PTY allocation on Cygwin, broken by sshd split Cygwin doesn't support FD passing and so used to disable post-auth privilege separation entirely because privsep requires PTY allocation to happen in the privileged monitor process with the PTY file descriptors being passed back to the unprivileged process. This brings back a minimal version of the previous special treatment for Cygwin (and any other platform that sets DISABLE_FD_PASSING): privilege separation remains enabled, but PTY allocation happens in the post-auth user process rather than the monitor. This either requires PTY allocation to not need privilege to begin with (this appears to be the case on Cygwin), or the post-auth privsep process retain privilege (other platforms that set the DISABLE_FD_PASSING option). Keeping privileges here is bad, but the non-Cygwin systems that set DISABLE_FD_PASSING are so deeply legacy that this is likely to be the least of their problems. commit f66d4df5749551380a8c4ae642347675a0b6a2e9 Author: Damien Miller Date: Thu Jun 13 11:33:09 2024 +1000 delay lookup of privsep user until config loaded sshd-session attempting to use options.kerberos_authentication to decide whether it needed to lookup the privsep user before the configuration was loaded. This caused it to get a placeholder value that caused it always to try to lookup the privsep user, breaking at least one test environment. commit f1c42858b94f5d9b58867b34dce3afb39c6b56a8 Author: Damien Miller Date: Thu Jun 13 11:16:57 2024 +1000 missing file for PerSourcePenalties regress test commit 4de80ff4e6fab5a6bb0028e7d57c6c23d1485adb Author: djm@openbsd.org Date: Wed Jun 12 22:36:00 2024 +0000 upstream: split PerSourcePenalties address tracking. Previously it used one shared table and overflow policy for IPv4 and IPv6 addresses, now it will use separate tables and optionally different overflow policies. This prevents misbehaviour from IPv6 addresses (which are vastly easier to obtain many of) from affecting IPv4 connections and may allow for stricter overflow policies. ok deraadt@ OpenBSD-Commit-ID: 12637ed0aa4d5f1f3e702da42ea967cbd8bfdfd9 commit 06ab4c6931b0aaa4334db2faaa7e1069e76d0df6 Author: jmc@openbsd.org Date: Tue Jun 11 05:24:39 2024 +0000 upstream: do not mark up "(default: 20ms)"; OpenBSD-Commit-ID: 54151ecdecfa1b67dcdda4fd24826ef6e2148ad4 commit cfe243cd9fde148ed060637876e27bb55ac78be9 Author: djm@openbsd.org Date: Tue Jun 11 02:54:51 2024 +0000 upstream: reap preauth net child if it hangs up during privsep message send, not just message receive OpenBSD-Commit-ID: 02a093f4ab4f8f83f0cd1ea2bb35b9ca420448f0 commit b0a711c00b9c64afd1c9d6fb538275c6604a2676 Author: djm@openbsd.org Date: Tue Jun 11 01:58:27 2024 +0000 upstream: fix PIDFILE handling, broken for SUDO=doas in last commit here OpenBSD-Regress-ID: 96fec579af228f87a036e94801eb294af9074625 commit 90fb801e2d9241be50a2a7ff79428386442a041f Author: djm@openbsd.org Date: Tue Jun 11 02:00:30 2024 +0000 upstream: reap the pre-auth [net] child if it hangs up during privsep message sending, not just receiving OpenBSD-Commit-ID: f7341605bf08c4c15830910446e6775323f2f8cb commit ef878d58798f6688c7f4d4e417dc0c29023ea831 Author: djm@openbsd.org Date: Tue Jun 11 01:23:25 2024 +0000 upstream: a little more RB_TREE paranoia OpenBSD-Commit-ID: 8dc2fd21eebd8830c4a4d25461ac4fe228e11156 commit fc4e96b2174d6a894d2033421699d091679baced Author: djm@openbsd.org Date: Tue Jun 11 01:22:25 2024 +0000 upstream: fix off-by-one comparison for PerSourcePenalty OpenBSD-Commit-ID: af4f5d01c41ef870b23e55655bfbf73474a6c02b commit 82c836df4ff41145553cd7adb11c5b985aeaa06f Author: djm@openbsd.org Date: Tue Jun 11 01:21:41 2024 +0000 upstream: move tree init before possible early return OpenBSD-Commit-ID: 72e2c5b69f151c08a7c5bf5ad929b97a92c273df commit a2300f015cc4939c4d9c564b58b74e71202dc978 Author: djm@openbsd.org Date: Tue Jun 11 01:07:35 2024 +0000 upstream: update to mention that PerSourcePenalties default to being enabled and document the default values for each parameter. OpenBSD-Commit-ID: b981288bddfb097aad269f62df4081c688ce0034 commit 41987efd356d3fc30139aeab4b09374acf8f91a0 Author: djm@openbsd.org Date: Tue Jun 11 00:44:52 2024 +0000 upstream: reap the [net] child if it hangs up while writing privsep message payloads, not just the message header OpenBSD-Commit-ID: 24dbd400aa381ac96be7ed2dd49018487dfef6ce commit 6211aa085fa91155a24922e5329576ac9a8f3175 Author: djm@openbsd.org Date: Tue Jun 11 00:40:21 2024 +0000 upstream: log waitpid() status for abnormal exits OpenBSD-Commit-ID: b317930e06b51819c1a2bc6a4359764fecfb1c2d commit a59634c7adb9ae988748d99963dfafb3070d8d41 Author: djm@openbsd.org Date: Tue Jun 11 00:36:20 2024 +0000 upstream: correct error message OpenBSD-Commit-ID: 581f60f73099083392887206860229ab104620ed commit fa7d7a667f2ee031e72873e36de2d2a36bca973b Author: deraadt@openbsd.org Date: Fri Jun 7 13:23:30 2024 +0000 upstream: avoid shadowing issues which some compilers won't accept ok djm OpenBSD-Commit-ID: 1e89572397dda83433d58c4fa6333a08f51170d4 commit 3ad4cd9eeca5c9bc6706db44b6de88e2e4513fd6 Author: jmc@openbsd.org Date: Thu Jun 6 21:14:49 2024 +0000 upstream: escape the final dot at eol in "e.g." to avoid double spacing; OpenBSD-Commit-ID: 0a9fb10bc9f7d577afe2da3f498a08bc431115b9 commit 0e0c69761a4c33ccd4a256560f522784a753d1a8 Author: djm@openbsd.org Date: Thu Jun 6 20:25:48 2024 +0000 upstream: enable PerSourcePenalties by default. ok markus NB. if you run a sshd that accepts connections from behind large NAT blocks, proxies or anything else that aggregates many possible users behind few IP addresses, then this change may cause legitimate traffic to be denied. Please read the PerSourcePenalties, PerSourcePenaltyExemptList and PerSourceNetBlockSize options in sshd_config(5) for how to tune your sshd(8) for your specific circumstances. OpenBSD-Commit-ID: 24a0e5c23d37e5a63e16d2c6da3920a51078f6ce commit bd1f74741daabeaf20939a85cd8cec08c76d0bec Author: djm@openbsd.org Date: Thu Jun 6 20:20:42 2024 +0000 upstream: mention that PerSourcePenalties don't affect concurrent in-progress connections. OpenBSD-Commit-ID: 20389da6264f2c97ac3463edfaa1182c212d420c commit 9774b938578327d88a651f4c63c504809717590a Author: djm@openbsd.org Date: Thu Jun 6 19:49:25 2024 +0000 upstream: regress test for PerSourcePenalties OpenBSD-Regress-ID: a1af13d411b25a727742644459d26480b9a1b0f1 commit b8ebd86cefe9812204a10c028dc90de29918667d Author: djm@openbsd.org Date: Thu Jun 6 19:48:40 2024 +0000 upstream: make sure logs are saved from sshd run via start_sshd OpenBSD-Regress-ID: de4ef0e32e3ab85ff3a6c36eb08d1909c0dd1b4a commit d7b2070bdaa4ebbfafb9975c1d5a62b73289d31f Author: djm@openbsd.org Date: Thu Jun 6 19:47:48 2024 +0000 upstream: simplify OpenBSD-Regress-ID: 50316e0d1ae0c0a057a45af042253e54ce23d11c commit e6ea3d224513b6bfb93818809d4c7397f5995ba2 Author: djm@openbsd.org Date: Thu Jun 6 18:48:13 2024 +0000 upstream: prepare for PerSourcePenalties being enabled by default in future OpenBSD-Regress-ID: 5236c6d1c823997aac5a35e2915da30f1903bec7 commit c0cb3b8c837761816a60a3cdb54062668df09652 Author: djm@openbsd.org Date: Thu Jun 6 19:50:01 2024 +0000 upstream: disable stderr redirection before closing fds OpenBSD-Commit-ID: d42cb895ee4542098050367fc35321c9303f003a commit 81c1099d22b81ebfd20a334ce986c4f753b0db29 Author: djm@openbsd.org Date: Thu Jun 6 17:15:25 2024 +0000 upstream: Add a facility to sshd(8) to penalise particular problematic client behaviours, controlled by two new sshd_config(5) options: PerSourcePenalties and PerSourcePenaltyExemptList. When PerSourcePenalties are enabled, sshd(8) will monitor the exit status of its child pre-auth session processes. Through the exit status, it can observe situations where the session did not authenticate as expected. These conditions include when the client repeatedly attempted authentication unsucessfully (possibly indicating an attack against one or more accounts, e.g. password guessing), or when client behaviour caused sshd to crash (possibly indicating attempts to exploit sshd). When such a condition is observed, sshd will record a penalty of some duration (e.g. 30 seconds) against the client's address. If this time is above a minimum threshold specified by the PerSourcePenalties, then connections from the client address will be refused (along with any others in the same PerSourceNetBlockSize CIDR range). Repeated offenses by the same client address will accrue greater penalties, up to a configurable maximum. A PerSourcePenaltyExemptList option allows certain address ranges to be exempt from all penalties. We hope these options will make it significantly more difficult for attackers to find accounts with weak/guessable passwords or exploit bugs in sshd(8) itself. PerSourcePenalties is off by default, but we expect to enable it automatically in the near future. much feedback markus@ and others, ok markus@ OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca commit 916b0b6174e203cf2c5ec9bcf409472eb7ffbf43 Author: Damien Miller Date: Fri Jun 7 03:31:02 2024 +1000 whitespace commit 49b55e44182b8294419aa580cbf043d5b9e3d953 Author: deraadt@openbsd.org Date: Tue Jun 4 15:14:45 2024 +0000 upstream: enable -fret-clean on amd64, for libc libcrypto ld.so kernel, and all the ssh tools. The dynamic objects are entirely ret-clean, static binaries will contain a blend of cleaning and non-cleaning callers. OpenBSD-Commit-ID: 112aacedd3b61cc5c34b1fa6d9fb759214179172 commit cc80d51d034bcb24fd0f2564a4bdf1612000a2a2 Author: Damien Miller Date: Wed Jun 5 02:21:30 2024 +1000 remove PRIVSEP macros for osx commit 8785491123d4d722b310c20f383570be758f8263 Author: djm@openbsd.org Date: Sat Jun 1 07:03:37 2024 +0000 upstream: be really strict with fds reserved for communication with the separate sshd-session process - reserve them early and fatal if we can't dup2(2) them later. The pre-split fallback to re-reading the configuration files is not possible, so sshd-session absolutely requires the fd the configuration is passed over to be in order. ok deraadt@ OpenBSD-Commit-ID: 308a98ef3c8a6665ebf92c7c9a0fc9600ccd7065 commit f1c8918cb98459910fb159373baea053ba4108c0 Author: Damien Miller Date: Fri May 31 19:12:26 2024 +1000 depend commit 94b4866cb1f4b0ed29a9f367047b30f81002316f Author: Damien Miller Date: Fri May 31 19:11:14 2024 +1000 rename need_privsep to need_chroot privsep is mandatory, chroot is optional (disabled when running sshd as non-root) commit e68a95142e5024b144f8eeccd5ffdee42c34f44c Author: Damien Miller Date: Fri May 31 19:05:34 2024 +1000 remove remaining use_privsep mention commit b21d271f651d2536dca819cc6d74032fe98634db Author: djm@openbsd.org Date: Fri May 31 09:01:08 2024 +0000 upstream: warn when -r (deprecated option to disable re-exec) is passed OpenBSD-Commit-ID: 73145ef5150edbe3ce7889f0844ed8fa6155f551 commit a4b5bc246cbca476deeeb4462aa31746a56e3021 Author: djm@openbsd.org Date: Fri May 31 08:49:35 2024 +0000 upstream: typos OpenBSD-Commit-ID: edfa72eb06bfa65da30fabf7d2fe76d2d33f77bf commit 8054b906983ceaed01fabd8188d3dac24c05ba39 Author: djm@openbsd.org Date: Mon May 27 01:52:26 2024 +0000 upstream: don't need sys/queue.h here OpenBSD-Commit-ID: dd137396828171eb19e4911581812ca58de6c578 commit 210d4239733da6180ce853538aeb9413d5c62ad5 Author: naddy@openbsd.org Date: Sun May 26 20:35:12 2024 +0000 upstream: remove references to SSH1 and DSA server keys OpenBSD-Commit-ID: 57cc1c98d4f998981473734f144b904af7d178a2 commit f0b9261d7fdd0ef86806b49fe76344bd16770cd0 Author: jsg@openbsd.org Date: Thu May 23 23:47:16 2024 +0000 upstream: remove unused struct fwd_perm_list, no decl with complete type ok djm@ OpenBSD-Commit-ID: 416fb3970b7e73c76d2963c4f00cf96f2b2ee2fb commit 2477a98c3ef78e63b11a1393656e00288f52ae97 Author: naddy@openbsd.org Date: Wed May 22 15:24:55 2024 +0000 upstream: Do not pass -Werror twice when building with clang. OpenBSD-Commit-ID: 5f378c38ad8976d507786dc4db9283a879ec8cd0 commit 435844f5675245b4271f8581f15e6d1f34fde3bc Author: miod@openbsd.org Date: Wed May 22 11:49:36 2024 +0000 upstream: Do not pass -Werror if building with gcc 3, for asn1.h and bio.h cause (admittedly bogus) warnings with gcc 3. OpenBSD-Commit-ID: fb39324748824cb0387e9d67c41d1bef945c54ea commit fc5dc092830de23767c6ef67baa18310a64ee533 Author: djm@openbsd.org Date: Wed May 22 04:20:00 2024 +0000 upstream: this test has been broken since 2014, and has been testing the same key exchange algorithm repeatedly instead of testing all of them. Spotted by nreilly AT blackberry.com in bz3692 Who broke the test? me. OpenBSD-Regress-ID: 48f4f5946276f975667141957d25441b3c9a50e2 commit fd4816791beaed2fdae7eea3e1494d1972b2a39d Author: anton@openbsd.org Date: Sun May 19 19:10:01 2024 +0000 upstream: Add missing kex-names.c source file required since the ssh split. OpenBSD-Regress-ID: ca666223f828fc4b069cb9016bff1eb50faf9fbb commit beccb7319c5449f6454889013403c336446d622e Author: naddy@openbsd.org Date: Fri May 17 14:42:00 2024 +0000 upstream: remove duplicate copy of relink kit for sshd-session OpenBSD-Commit-ID: 6d2ded4cd91d4d727c2b26e099b91ea935bed504 commit dcd79fa141311c287e0595ede684b7116122fae0 Author: jsg@openbsd.org Date: Fri May 17 06:42:04 2024 +0000 upstream: remove prototypes with no matching function; ok djm@ OpenBSD-Commit-ID: 6d9065dadea5f14a01bece0dbfe2fba1be31c693 commit 6454a05e7c6574d70adf17efe505a8581a86ca4f Author: jsg@openbsd.org Date: Fri May 17 06:38:00 2024 +0000 upstream: remove externs for removed vars; ok djm@ OpenBSD-Commit-ID: f51ea791d45c15d4927eb4ae7d877ccc1e5a2aab commit f3e4db4601ef7d2feb1d6f7447e432aaf353a616 Author: deraadt@openbsd.org Date: Fri May 17 06:11:17 2024 +0000 upstream: -Werror was turned on (probably just for development), and this is a simple way to satisfy older gcc. OpenBSD-Commit-ID: 7f698df54384b437ce33ab7405f0b86c87019e86 commit 24a1f3e5ad6f4a49377d4c74c36637e9a239efd0 Author: Damien Miller Date: Fri May 17 14:50:43 2024 +1000 attempt at updating RPM specs for sshd-session commit 17b566eeb7a0c6acc9c48b35c08885901186f861 Author: djm@openbsd.org Date: Fri May 17 04:42:13 2024 +0000 upstream: g/c unused variable OpenBSD-Commit-ID: aa6ef0778a1f1bde0d73efba72a777c48d2bd010 commit 01fb82eb2aa0a4eaf5c394ea8bb37ea4c26f8a3f Author: jsg@openbsd.org Date: Fri May 17 02:39:11 2024 +0000 upstream: spelling; ok djm@ OpenBSD-Commit-ID: bdea29bb3ed2a5a7782999c4c663b219d2270483 commit b88b690e99145a021fc1a1a116a11e0bce0594e7 Author: djm@openbsd.org Date: Fri May 17 01:45:22 2024 +0000 upstream: allow overriding the sshd-session binary path OpenBSD-Regress-ID: 5058cd1c4b6ca1a15474e33546142931d9f964da commit a68f80f2511f0e0c5cef737a8284cc2dfabad818 Author: anton@openbsd.org Date: Wed Apr 3 06:01:11 2024 +0000 upstream: Since ssh-agent(1) is only readable by root by now, use ssh(1) while generating data in tests. OpenBSD-Regress-ID: 24eb40de2e6b0ace185caaba35e2d470331ffe68 commit 92e55890314ce2b0be21a43ebcbc043b4abc232f Author: djm@openbsd.org Date: Fri May 17 01:17:40 2024 +0000 upstream: fix incorrect debug option name introduce in previous commit OpenBSD-Commit-ID: 66d69e22b1c072c694a7267c847f212284614ed3 commit 4ad72878af7b6ec28da6e230e36a91650ebe84c1 Author: deraadt@openbsd.org Date: Fri May 17 00:33:25 2024 +0000 upstream: construct and install a relink-kit for sshd-session ok djm OpenBSD-Commit-ID: 8b3820adb4da4e139c4b3cffbcc0bde9f08bf0c6 commit 02e679a2cb3f6df8e9dbb1519ed578226485157f Author: Damien Miller Date: Fri May 17 12:21:27 2024 +1000 Makefile support for sshd-session commit c0416035c5eaf70a8450d11c8833c5f7068ee7ad Author: djm@openbsd.org Date: Fri May 17 00:32:32 2024 +0000 upstream: missing files from previous OpenBSD-Commit-ID: 4b7be4434d8799f02365552b641a7a70a7ebeb2f commit 03e3de416ed7c34faeb692967737be4a7bbe2eb5 Author: djm@openbsd.org Date: Fri May 17 00:30:23 2024 +0000 upstream: Start the process of splitting sshd into separate binaries. This step splits sshd into a listener and a session binary. More splits are planned. After this changes, the listener binary will validate the configuration, load the hostkeys, listen on port 22 and manage MaxStartups only. All session handling will be performed by a new sshd-session binary that the listener fork+execs. This reduces the listener process to the minimum necessary and sets us up for future work on the sshd-session binary. feedback/ok markus@ deraadt@ NB. if you're updating via source, please restart sshd after installing, otherwise you run the risk of locking yourself out. OpenBSD-Commit-ID: 43c04a1ab96cdbdeb53d2df0125a6d42c5f19934 commit 1c0d81357921f8d3bab06841df649edac515ae5b Author: djm@openbsd.org Date: Thu May 9 09:46:47 2024 +0000 upstream: simplify exit message handling, which was more complicated than it needed to be because of unexpunged ssh1 remnants. ok markus@ OpenBSD-Commit-ID: 8b0cd2c0dee75fb053718f442aa89510b684610b commit cbbbf76aa6cd54fce32eacce1300e7abcf9461d4 Author: tobias@openbsd.org Date: Mon May 6 19:26:17 2024 +0000 upstream: remove SSH1 leftovers Authored with Space Meyer ok djm OpenBSD-Commit-ID: 81db602e4cb407baae472689db1c222ed7b2afa3 commit bc5dcb8ab9a4e8af54a724883732af378f42ea78 Author: tobias@openbsd.org Date: Tue Apr 30 15:40:43 2024 +0000 upstream: never close stdin The sanitise_stdfd call makes sure that standard file descriptors are open (if they were closed, they are connected with /dev/null). Do not close stdin in any case to prevent error messages when stdin is read multiple times and to prevent later usage of fd 0 for connections, e.g. echo localhost | ssh-keyscan -f - -f - While at it, make stdin-related error messages nicer. Authored with Max Kunzelmann ok djm OpenBSD-Commit-ID: 48e9b7938e2fa2f9bd47e6de6df66a31e0b375d3 commit 6a42b70e56bef1aacdcdf06352396e837883e84f Author: Damien Miller Date: Wed May 8 09:43:59 2024 +1000 sync getrrsetbyname.c with recent upstream changes commit 385ecb31e147dfea59c1c488a1d2011d3867e60e Author: djm@openbsd.org Date: Tue Apr 30 06:23:51 2024 +0000 upstream: fix home-directory extension implementation, it always returned the current user's home directory contrary to the spec. Patch from Jakub Jelen via GHPR477 OpenBSD-Commit-ID: 5afd775eab7f9cbe222d7fbae4c793de6c3b3d28 commit 14e2b16bc67ffcc188906f65008667e22f73d103 Author: djm@openbsd.org Date: Tue Apr 30 06:16:55 2024 +0000 upstream: flush stdout after writing "sftp>" prompt when not using editline. From Alpine Linux via GHPR480 OpenBSD-Commit-ID: 80bdc7ffe0358dc090eb9b93e6dedb2b087b24cd commit 2e69a724051488e3fb3cd11531c4b5bc1764945b Author: djm@openbsd.org Date: Tue Apr 30 05:53:03 2024 +0000 upstream: stricter validation of messaging socket fd number; disallow usage of stderr. Based on GHPR492 by RealHurrison OpenBSD-Commit-ID: 73dbbe82ea16f73ce1d044d3232bc869ae2f2ce8 commit da757b022bf18c6f7d04e685a10cd96ed00f83da Author: djm@openbsd.org Date: Tue Apr 30 05:45:56 2024 +0000 upstream: add missing reserved fields to key constraint protocol documentation. from Wiktor Kwapisiewicz via GHPR487 OpenBSD-Commit-ID: 0dfb69998cfdb3fa00cbb0e7809e7d2f6126e3df commit 16d0b82fa08038f35f1b3630c70116979f49784f Author: Damien Miller Date: Tue Apr 30 12:39:34 2024 +1000 depend commit 66aaa678dbe59aa21d0d9d89a3596ecedde0254b Author: djm@openbsd.org Date: Tue Apr 30 02:14:10 2024 +0000 upstream: correctly restore sigprocmask around ppoll() reported by Tõivo Leedjärv; ok deraadt@ OpenBSD-Commit-ID: c0c0f89de5294a166578f071eade2501929c4686 commit 80fb0eb21551aed3aebb009ab20aeffeb01e44e0 Author: djm@openbsd.org Date: Tue Apr 30 02:10:49 2024 +0000 upstream: add explict check for server hostkey type against HostkeyAlgorithms. Allows HostkeyAlgorithms to disable implicit fallback from certificate keys to plain keys. ok markus@ OpenBSD-Commit-ID: 364087e4a395ff9b2f42bf3aefdb2090bb23643a commit 5b28096d31ff7d80748fc845553a4aef5bb05d86 Author: jsg@openbsd.org Date: Tue Apr 23 13:34:50 2024 +0000 upstream: correct indentation; no functional change ok tb@ OpenBSD-Commit-ID: dd9702fd43de546bc6a3f4f025c74d6f3692a0d4 commit fd3cb8a82784e05f621dea5b56ac6f89bc53c067 Author: semarie@openbsd.org Date: Thu Apr 4 16:00:51 2024 +0000 upstream: set right mode on ssh-agent at boot-time which sthen@ ok deraadt@ OpenBSD-Commit-ID: 662b5056a2c6171563e1626f9c69f27862b5e7af commit 54343a260e3aa4bceca1852dde31cd08e2abd82b Author: deraadt@openbsd.org Date: Tue Apr 2 12:22:38 2024 +0000 upstream: Oops, incorrect hex conversion spotted by claudio. While here try to improve how it reads a bit better. Surprising the regression tests didn't spot this error, maybe it fails to roundtrip the values. OpenBSD-Commit-ID: 866cfcc1955aef8f3fc32da0b70c353a1b859f2e commit ec78c31409590ad74efc194f886273ed080a545a Author: deraadt@openbsd.org Date: Tue Apr 2 10:02:08 2024 +0000 upstream: for parse_ipqos(), use strtonum() instead of mostly idiomatic strtoul(), but wow it's so gross. ok djm OpenBSD-Commit-ID: cec14a76af2eb7b225300c80fc0e21052be67b05 commit 8176e1a6c2e6da9361a7abb6fbf6c23c299f495b Author: deraadt@openbsd.org Date: Tue Apr 2 09:56:58 2024 +0000 upstream: can shortcut by returning strtonum() value directly; ok djm OpenBSD-Commit-ID: 7bb2dd3d6d1f288dac14247d1de446e3d7ba8b8e commit 9f543d7022a781f80bb696f9d73f1d1c6f9e31d6 Author: deraadt@openbsd.org Date: Tue Apr 2 09:52:14 2024 +0000 upstream: rewrite convtime() to use a isdigit-scanner and strtonum() instead of strange strtoul can might be fooled by garage characters. passes regress/usr.bin/ssh/unittests/misc ok djm OpenBSD-Commit-ID: 4b1ef826bb16047aea3f3bdcb385b72ffd450abc commit 8673137f780d8d9e4cda3c4605cb5d88d5cea271 Author: claudio@openbsd.org Date: Tue Apr 2 09:48:24 2024 +0000 upstream: Remove unused ptr[3] char array in pkcs11_decode_hex. OK deraadt@ OpenBSD-Commit-ID: 3d14433e39fd558f662d3b0431c4c555ef920481 commit c7fec708f331f108343d69e4d74c9a5d86d6cfe7 Author: deraadt@openbsd.org Date: Tue Apr 2 09:32:28 2024 +0000 upstream: Replace non-idiomatic strtoul(, 16) to parse a region of 2-character hex sequences with a low-level replacement designed just for the task. ok djm OpenBSD-Commit-ID: 67bab8b8a4329a19a0add5085eacd6f4cc215e85 commit 019a5f483b0f588da6270ec401d0b4bb35032f3f Author: deraadt@openbsd.org Date: Tue Apr 2 09:29:31 2024 +0000 upstream: Use strtonum() instead of severely non-idomatic strtoul() In particular this will now reject trailing garbage, ie. '12garbage'. ok djm OpenBSD-Commit-ID: c82d95e3ccbfedfc91a8041c2f8bf0cf987d1501 commit 8231ca046fa39ea4eb99b79e0a6e09dec50ac952 Author: deraadt@openbsd.org Date: Mon Apr 1 15:50:17 2024 +0000 upstream: also create a relink kit for ssh-agent, since it is a long-running setgid program carrying keys with some (not very powerful) communication channels. solution for testing the binary from dtucker. agreement from djm. Will add it into /etc/rc in a few days. OpenBSD-Commit-ID: 2fe8d707ae35ba23c7916adcb818bb5b66837ba0 commit bf7bf50bd6a14e49c9c243cb8f4de31e555a5a2e Author: deraadt@openbsd.org Date: Mon Apr 1 15:48:16 2024 +0000 upstream: new-style relink kit for sshd. The old scheme created a Makefile by concatenating two Makefiles and was incredibly fragile. In the new way a narrow-purposed install.sh script is created and shipped with the objects. A recently commited /etc/rc script understands these files. OpenBSD-Commit-ID: ef9341d5a50f0d33e3a6fbe995e92964bc7ef2d3 commit 00e63688920905e326d8667cb47f17a156b6dc8f Author: renmingshuai Date: Fri Apr 12 10:20:49 2024 +0800 Shell syntax fix (leftover from a sync). Signed-off-by: renmingshuai commit 2eded551ba96e66bc3afbbcc883812c2eac02bd7 Author: Darren Tucker Date: Thu Apr 25 13:20:19 2024 +1000 Merge flags for OpenSSL 3.x versions. OpenSSL has moved to 3.4 which we don't currently accept. Based on the OpenSSL versioning policy[0] it looks like all of the 3.x versions should work with OpenSSH, so remove the distinction in configure and accept all of them. [0] https://openssl.org/policies/general/versioning-policy.html commit 8673245918081c6d1dc7fb3733c8eb2c5a902c5e Author: Darren Tucker Date: Thu Apr 25 13:19:03 2024 +1000 Remove 9.6 branch from status page. commit 70d43049747fa3c66cf876d52271859407cec2fa Author: Darren Tucker Date: Thu Apr 25 13:16:58 2024 +1000 Update LibreSSL and OpenSSL versions tested. Update LibreSSL versions to current releases (3.8.4 & 3.9.1). Add newly-released OpenSSL 3.3.0, and add tests against the 3.1 and 3.3 branches. commit 88351eca17dcc55189991ba60e50819b6d4193c1 Author: 90 Date: Fri Apr 5 19:36:06 2024 +0100 Fix missing header for systemd notification commit 08f579231cd38a1c657aaa6ddeb8ab57a1fd4f5c Author: Damien Miller Date: Wed Apr 3 14:40:32 2024 +1100 notify systemd on listen and reload Standalone implementation that does not depend on libsystemd. With assistance from Luca Boccassi, and feedback/testing from Colin Watson. bz2641 commit 43e7c1c07cf6aae7f4394ca8ae91a3efc46514e2 Author: Darren Tucker Date: Sun Mar 31 21:51:57 2024 +1100 Port changes from selfhosted to upstream tests. Should get them working again. commit 281ea25a44bff53eefb4af7bab7aa670b1f8b6b2 Author: Darren Tucker Date: Sat Mar 30 18:20:16 2024 +1100 Check if OpenSSL implementation supports DSA. If --enable/disable-dsa-keys is not specified, set based on what OpenSSL supports. If specified as enabled, but not supported by OpenSSL error out. ok djm@ commit 2d2c068de8d696fe3246f390b146197f51ea1e83 Author: djm@openbsd.org Date: Sat Mar 30 05:56:22 2024 +0000 upstream: in OpenSSH private key format, correct type for subsequent private keys in blob. From Jakub Jelen via GHPR430 OpenBSD-Commit-ID: d17dbf47554de2d752061592f95b5d772baab50b commit c2c0bdd3e96b3ef66d77fccb85ff4962dc76caf0 Author: Eero Häkkinen Date: Sat Sep 16 00:55:08 2023 +0300 Expose SSH_AUTH_INFO_0 always to PAM auth modules. This changes SSH_AUTH_INFO_0 to be exposed to PAM auth modules also when a password authentication method is in use and not only when a keyboard-interactive authentication method is in use. commit 02c5ad23124ae801cf248d99ea5068fc4331ca01 Author: Darren Tucker Date: Wed Mar 27 17:42:58 2024 +1100 Rearrange selfhosted VM scheduling. Instead of trying to infer the type of the self hosted tests in each of the driver scripts (inconsistently...), set one of the following variables to "true" in the workflow: VM: tests run in a virtual machine. EPHEMERAL: tests run on an ephemeral virtual machine. PERSISTENT: tests run on a persistent virtual machine REMOTE: tests run on a physical remote host. EPHEMERAL VMs can have multiple instances of any given VM can exist simultaneously and are run by a runner pool. The other types have a dedicated runner instance and can only run a single test at a time. Other settings: SSHFS: We need to sshfs mount over the repo so the workflow can collect build artifacts. This also implies the tests must be run over ssh. DEBUG_ACTIONS: enable "set -x" in scripts for debugging. commit cd8a72707c02615365d0851ac51063ab6bfe258f Author: Damien Miller Date: Sat Mar 30 16:05:59 2024 +1100 add new token-based signing key for dtucker@ Verified in person and via signature with old key. Will remove old key in a bit. commit 8d0e46c1ddb5b7f0992591b0dc5d8aaa77cc9dba Author: Alkaid Date: Tue Mar 12 03:59:12 2024 -0700 Fix OpenSSL ED25519 support detection Wrong function signature in configure.ac prevents openssh from enabling the recently new support for ED25519 priv keys in PEM PKCS8 format. commit 697359be9c23ee43618243cdbcc9c7981e766752 Author: djm@openbsd.org Date: Sat Mar 30 04:27:44 2024 +0000 upstream: allow WAYLAND_DISPLAY to enable SSH_ASKPASS From dkg via GHPR479; ok dtucker@ OpenBSD-Commit-ID: 1ac1f9c45da44eabbae89375393c662349239257 commit 7844705b0364574cc70b941be72036c2c2966363 Author: dtucker@openbsd.org Date: Fri Mar 29 10:40:07 2024 +0000 upstream: Use egrep instead of grep -E. Some plaforms don't have the latter so this makes things easier in -portable. OpenBSD-Regress-ID: ff82260eb0db1f11130200b25d820cf73753bbe3 commit 22b2b6c555334bffdf357a2e4aa74308b03b83c3 Author: dtucker@openbsd.org Date: Tue Mar 26 08:09:16 2024 +0000 upstream: test -h is the POSIXly way of testing for a symlink. Reduces diff vs Portable. OpenBSD-Regress-ID: 6f31cd6e231e3b8c5c2ca0307573ccb7484bff7d commit edcff77f82c2bb2b5653b36f1e47274c5ef3e8be Author: Darren Tucker Date: Tue Mar 26 18:58:58 2024 +1100 Fix name of OpenBSD upstream CI jobs. commit 861b084429940e024f1b6e9c2779eac95d7a45db Author: Darren Tucker Date: Tue Mar 26 18:55:33 2024 +1100 Resync with upstream: ${} around DATAFILE. commit 63f248c7693e7f0a3b9a13d2980ac9a7e37f2aea Author: djm@openbsd.org Date: Mon Mar 25 19:28:09 2024 +0000 upstream: optional debugging OpenBSD-Regress-ID: b4852bf97ac8fb2e3530f2d5f999edd66058d7bc commit 16e2ebe06a62f09d4877b769876d92d6008a896f Author: dtucker@openbsd.org Date: Mon Mar 25 06:05:42 2024 +0000 upstream: Verify string returned from local shell command. OpenBSD-Regress-ID: 5039bde24d33d809aebfa8d3ad7fe9053224e6f8 commit b326f7a1f39ff31324cc3fe2735178fb474c04a4 Author: dtucker@openbsd.org Date: Mon Mar 25 03:30:31 2024 +0000 upstream: Improve shell portability: grep -q is not portable so redirect stdout, and use printf instead of relying on echo to do \n substitution. Reduces diff vs Portable. Also resync somewhat with upstream. OpenBSD-Regress-ID: 9ae876a8ec4c4725f1e9820a0667360ee2398337 commit dbf2e319f0c582613fa45a735ea3c242ce56946b Author: dtucker@openbsd.org Date: Mon Mar 25 02:07:08 2024 +0000 upstream: Save error code from SSH for use inside case statement, from portable. In some shells, "case" will reset the value of $?, so save it first. OpenBSD-Regress-ID: da32e5be19299cb4f0f7de7f29c11257a62d6949 commit d2c8c4fa7def4fb057ed05b3db57b62c810a26f6 Author: dtucker@openbsd.org Date: Mon Mar 25 01:40:47 2024 +0000 upstream: Increase timeout. Resyncs with portable where some of the test VMs are slow enough for this to matter. OpenBSD-Regress-ID: 6a83a693602eb0312f06a4ad2cd6f40d99d24b26 commit 83621b63514a84791623db3efb59d38bc4bf9563 Author: dtucker@openbsd.org Date: Mon Mar 25 01:28:29 2024 +0000 upstream: In PuTTY interop test, don't assume the PuTTY major version is 0. Patch from cjwatson at debian.org via bz#3671. OpenBSD-Regress-ID: 835ed03c1b04ad46be82e674495521f11b840191 commit 8a421b927700f3834b4d985778e252b8e3299f83 Author: Darren Tucker Date: Tue Mar 26 18:38:14 2024 +1100 Really mkdir /usr/local/etc in CI tests. commit 2946ed522c47ce045314533d426b4e379f745e59 Author: Darren Tucker Date: Tue Mar 26 17:19:09 2024 +1100 Better short name for OpenBSD upstream CI jobs too. commit 18dbe8eff647aacb82d7e86b4ce63d5beee11f25 Author: Darren Tucker Date: Tue Mar 26 17:13:52 2024 +1100 Ensure /usr/local/etc exists before using in tests. commit 5fc1085128e3348bb1b5ee4d955cc767b019b3ad Author: Darren Tucker Date: Tue Mar 26 16:50:46 2024 +1100 Be more specific about when to rerun workflows. commit 5516923e8ae3da0823fea0d7d28aa813627142c0 Author: Darren Tucker Date: Tue Mar 26 16:35:27 2024 +1100 Add short names for test jobs on github CI. commit dc37d2d2470b4a9cedcee9ac926b7362214e3305 Author: Darren Tucker Date: Tue Mar 26 16:26:14 2024 +1100 If we're using xpg4's id, remember to pass args. commit fe169487937780392b23d3ff3c00e5898c10f784 Author: dtucker@openbsd.org Date: Tue Mar 26 01:23:11 2024 +0000 upstream: Import regenerated moduli. OpenBSD-Commit-ID: ad3d1486d105b008c93e952d158e5af4d9d4c531 commit 151146f03b490d19145cd421763aa7d42f5c50e2 Author: job@openbsd.org Date: Thu Mar 14 06:23:14 2024 +0000 upstream: Clarify how literal IPv6 addresses can be used in -J mode OK djm@ OpenBSD-Commit-ID: 524ddae97746b3563ad4a887dfd0a6e6ba114c50 commit 0d5bdc87a675271862b67eb6a9fb13a202fb4894 Author: Darren Tucker Date: Mon Mar 25 16:14:21 2024 +1100 Add Mac OS X 14 test targets. commit 2d7964a03e1f50a48040ec6912c0a956df909d21 Author: Darren Tucker Date: Mon Mar 25 14:05:40 2024 +1100 Move xpg4 'id' handling into test-exec.sh. Handle replacement of 'id' the same way as we do other Portable specific replacements in test-exec.sh. This brings percent.sh back into sync with upstream. commit 75d1d49ed10d978171cdafad28bdbffdbd48f41e Author: Darren Tucker Date: Mon Mar 25 10:38:03 2024 +1100 Update branches shown on ci-status to 9.7 and 9.6. commit f9193f03db0029fc9c31fbdb5c66a2737446bd8f Author: Darren Tucker Date: Mon Mar 25 09:28:02 2024 +1100 Improve detection of -fzero-call-used-regs=used. Should better detect problems with gcc 13 on m68k. bz#3673 from Colin Watson via bz#3673 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110934 Signed-off-by: Darren Tucker commit 86bdd3853f4d32c85e295e6216a2fe0953ad93f0 Author: Damien Miller Date: Mon Mar 11 16:20:49 2024 +1100 version number in README commit 282721418e6465bc39ccfd39bb0133e670ee4423 Author: Damien Miller Date: Mon Mar 11 16:20:08 2024 +1100 crank RPM spec versions commit 3876a3bbd2ca84d23ba20f8b69ba83270c04ce3a Author: djm@openbsd.org Date: Mon Mar 11 04:59:47 2024 +0000 upstream: openssh-9.7 OpenBSD-Commit-ID: 618ececf58b8cdae016b149787af06240f7b0cbc commit 8fc109cc614954a8eb2738c48c0db36a62af9a06 Author: Darren Tucker Date: Mon Mar 11 12:59:26 2024 +1100 Test against current OpenSSL and LibreSSL releases. Add LibreSSL 3.9.0, bump older branches to their respective current releases. commit 26b09b45fec7b88ba09042c09be4157e58e231e2 Author: Damien Miller Date: Sun Mar 10 16:24:57 2024 +1100 quote regexes used to test for algorithm support Fixes test failures on Solaris 8 reported by Tom G. Christensen commit a6a740a4948d10a622b505135bb485c10f21db5e Author: djm@openbsd.org Date: Sat Mar 9 05:12:13 2024 +0000 upstream: avoid logging in signal handler by converting mainloop to ppoll() bz3670, reported by Ben Hamilton; ok dtucker@ OpenBSD-Commit-ID: e58f18042b86425405ca09e6e9d7dfa1df9f5f7f commit cd82f7526e0481720567ae41db7849ab1c27e27b Author: djm@openbsd.org Date: Fri Mar 8 22:16:32 2024 +0000 upstream: skip more whitespace, fixes find-principals on allowed_signers files with blank lines; reported by Wiktor Kwapisiewicz OpenBSD-Commit-ID: b3a22a2afd753d70766f34bc7f309c03706b5298 commit 2f9d2af5cb19905d87f37d1e11c9f035ac5daf3b Author: dtucker@openbsd.org Date: Fri Mar 8 11:34:10 2024 +0000 upstream: Invoke ProxyCommand that uses stderr redirection via $TEST_SHELL. Fixes test when run by a user whose login shell is tcsh. Found by vinschen at redhat.com. OpenBSD-Regress-ID: f68d79e7f00caa8d216ebe00ee5f0adbb944062a commit 9b3f0beb4007a7e01dfedabb429097fb593deae6 Author: Darren Tucker Date: Thu Mar 7 17:18:14 2024 +1100 Prefer openssl binary from --with-ssl-dir directory. Use openssl in the directory specified by --with-ssl-dir as long as it's functional. Reported by The Doctor. commit c47e1c9c7911f38b2fc2fb01b1f6ae3a3121a838 Author: djm@openbsd.org Date: Wed Mar 6 02:59:59 2024 +0000 upstream: fix memory leak in mux proxy mode when requesting forwarding. found by RASU JSC, reported by Maks Mishin in GHPR#467 OpenBSD-Commit-ID: 97d96a166b1ad4b8d229864a553e3e56d3116860 commit 242742827fea4508e68097c128e802edc79addb5 Author: djm@openbsd.org Date: Wed Mar 6 00:31:04 2024 +0000 upstream: wrap a few PKCS#11-specific bits in ENABLE_PKCS11 OpenBSD-Commit-ID: 463e4a69eef3426a43a2b922c4e7b2011885d923 commit d52b6509210e2043f33e5a1de58dd4a0d5d48c2a Author: Damien Miller Date: Wed Mar 6 11:31:36 2024 +1100 disable RSA tests when algorithm is not supported Unbreaks "make test" when compiled --without-openssl. Similar treatment to how we do DSA and ECDSA. commit 668d270a6c77e8b5a1da26ecad2e6de9f62c8fe4 Author: Damien Miller Date: Wed Mar 6 10:33:20 2024 +1100 add a --without-retpoline configure option discussed with deraadt and dtucker a while ago commit 3deb501f86fc47e175ef6a3eaba9b9846a80d444 Author: djm@openbsd.org Date: Mon Mar 4 04:13:18 2024 +0000 upstream: fix leak of CanonicalizePermittedCNAMEs on error path; spotted by Coverity (CID 438039) OpenBSD-Commit-ID: 208839699939721f452a4418afc028a9f9d3d8af commit 65a44a8a4f7d902a64d4e60eda84384b2e2a24a2 Author: djm@openbsd.org Date: Mon Mar 4 02:16:11 2024 +0000 upstream: Separate parsing of string array options from applying them to the active configuration. This fixes the config parser from erroneously rejecting cases like: AuthenticationMethods password Match User ivy AuthenticationMethods any bz3657 ok markus@ OpenBSD-Commit-ID: 7f196cba634c2a3dba115f3fac3c4635a2199491 commit 6886e1b1f55c90942e4e6deed930f8ac32e0f938 Author: Darren Tucker Date: Thu Feb 22 17:59:35 2024 +1100 Add nbsd10 test target. commit d86bf8a3f6ea4fa7887406c2aa9959db71fa41be Author: Damien Miller Date: Thu Feb 22 12:06:10 2024 +1100 more descriptive configure test name commit 9ee335aacc9f5bdc4cc2c19fafb45e27be7d234e Author: djm@openbsd.org Date: Wed Feb 21 06:17:29 2024 +0000 upstream: explain arguments of internal-sftp GHPR#454 from Niklas Hambüchen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenBSD-Commit-ID: 0335d641ae6b5b6201b9ffd5dd06345ebbd0a3f3 commit d1164cb1001dd208fee88aaa9b43d5e6fd917274 Author: djm@openbsd.org Date: Wed Feb 21 06:06:43 2024 +0000 upstream: clarify permissions requirements for ChrootDirectory Part of GHPR#454 from Niklas Hambüchen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenBSD-Commit-ID: d37bc8786317a11649c62ff5e2936441186ef7a0 commit d410e17d186552d0717f18217d0d049486754365 Author: djm@openbsd.org Date: Wed Feb 21 06:05:06 2024 +0000 upstream: .Cm for a keyword. Part of GHPR#454 from Niklas Hambüchen OpenBSD-Commit-ID: d59c52559f926fa82859035d79749fbb4a3ce18a commit ab73f9678ebf06b32d6361b88b50b42775e0565b Author: djm@openbsd.org Date: Wed Feb 21 06:01:13 2024 +0000 upstream: fix typo in match directive predicate (s/tagged/tag) GHPR#462 from Tobias Manske OpenBSD-Commit-ID: 05b23b772677d48aa82eefd7ebebd369ae758908 commit 9844aa2521ccfb1a2d73745680327b79e0574445 Author: djm@openbsd.org Date: Wed Feb 21 05:57:34 2024 +0000 upstream: fix proxy multiplexing mode, broken when keystroke timing obfuscation was added. GHPR#463 from montag451 OpenBSD-Commit-ID: 4e412d59b3f557d431f1d81c715a3bc0491cc677 commit ee6d932acb532f80b11bb7cf161668c70ec8a117 Author: djm@openbsd.org Date: Tue Feb 20 04:10:03 2024 +0000 upstream: don't append a gratuitous space to the end of subsystem arguments; bz3667 OpenBSD-Commit-ID: e11023aeb3f30b77a674e37b8292c862926d5dc6 commit e27f032aa8fcbae9b2e7c451baaf4b8ac6fa3d45 Author: dtucker@openbsd.org Date: Mon Feb 19 09:25:52 2024 +0000 upstream: Always define puttysetup function. OpenBSD-Regress-ID: b4c0ccfa4006a1bc5dfd99ccf21c854d3ce2aee0 commit 84046f9991abef5f46b040b10cf3d494f933a17b Author: dtucker@openbsd.org Date: Fri Feb 9 08:56:59 2024 +0000 upstream: Exapnd PuTTY test coverage. Expand the set of ciphers, MACs and KEX methods in the PuTTY interop tests. OpenBSD-Regress-ID: dd28d97d48efe7329a396d0d505ee2907bf7fc57 commit bbf541ee2afe07b08a8b56fa0dc6f38fcfceef2a Author: dtucker@openbsd.org Date: Fri Feb 9 08:47:42 2024 +0000 upstream: Factor out PuTTY setup. Factor out PuTTY and call only when needed. This allows us to avoid PuTTY key setup when it's not needed, which speeds up the overall test run by a couple of percent. OpenBSD-Regress-ID: c25eaccc3c91bc874400f7c85ce40e9032358c1c commit d31c21c57fb4245271680a1e5043cf6470a96766 Author: naddy@openbsd.org Date: Sat Feb 10 11:28:52 2024 +0000 upstream: clean sshd random relinking kit; ok miod@ OpenBSD-Commit-ID: 509bb19bb9762a4b3b589af98bac2e730541b6d4 commit 4dbc5a363ff53a2fcecf6bc3bcc038badc12f118 Author: djm@openbsd.org Date: Fri Feb 2 00:13:34 2024 +0000 upstream: whitespace OpenBSD-Commit-ID: b24680bc755b621ea801ff8edf6f0f02b68edae1 commit efde85dda2130272af24cc346f6c3cd326182ff1 Author: Darren Tucker Date: Mon Feb 19 17:29:31 2024 +1100 Improve error message for OpenSSL header check. bz#3668, ok djm@ commit cbbdf868bce431a59e2fa36ca244d5739429408d Author: Darren Tucker Date: Wed Feb 7 13:45:02 2024 +1100 Interop test against PuTTY snapshot and releases. commit 91898bf786b0f149f962c4c96c08a46f29888c10 Author: Darren Tucker Date: Tue Feb 6 16:21:05 2024 +1100 Put privsep dir on OS X on /usr/local. On some runners we can't create /var/empty, so put it some place we can write. Should fix test breakage on Max OS X 11. commit be5ed8ebed8388c5056bfde4688308cc873c18b9 Author: Darren Tucker Date: Tue Feb 6 11:19:42 2024 +1100 Add --disable-fd-passing option. .. and enable for the minix3 test VM. This will cause it to more reliably skip tests that need FD passing and should fix the current test breakage. commit 0f6a8a0d0a518fd78c4cbebfdac990a57a1c4e41 Author: Darren Tucker Date: Tue Feb 6 11:18:44 2024 +1100 Use "skip" function instead doing it ourselves. commit 3ad669f81aabbd2ba9fbd472903f680f598e1e99 Author: Damien Miller Date: Thu Feb 1 14:01:18 2024 +1100 ignore some vim droppings commit c283f29d23611a06bbee06bcf458f2fffad721d9 Author: djm@openbsd.org Date: Thu Feb 1 02:37:33 2024 +0000 upstream: whitespace OpenBSD-Commit-ID: bf9e4a1049562ee4322684fbdce07142f04fdbb7 commit 0d96b1506b2f4757fefa5d1f884d49e96a6fd4c3 Author: Damien Miller Date: Tue Jan 16 14:40:18 2024 +1100 skip tests that use multiplexing on Windows Some tests here use multiplexing, skip these if DISABLE_FD_PASSING is set. Should unbreak tests on Windows. commit 50080fa42f5f744b798ee29400c0710f1b59f50e Author: djm@openbsd.org Date: Thu Jan 11 04:50:28 2024 +0000 upstream: don't disable RSA test when DSA is disabled; bug introduced in last commit OpenBSD-Regress-ID: 8780a7250bf742b33010e9336359a1c516f2d7b5 commit 415c94ce17288e0cdcb9e58cc91fba78d33c8457 Author: djm@openbsd.org Date: Thu Jan 11 01:45:58 2024 +0000 upstream: make DSA testing optional, defaulting to on ok markus OpenBSD-Regress-ID: dfc27b5574e3f19dc4043395594cea5f90b8572a commit f9311e8921d92c5efca767227a497ab63280ac39 Author: djm@openbsd.org Date: Thu Jan 11 01:51:16 2024 +0000 upstream: ensure key_fd is filled when DSA is disabled; spotted by tb@ OpenBSD-Commit-ID: 9dd417b6eec3cf67e870f147464a8d93f076dce7 commit 4e838120a759d187b036036610402cbda33f3203 Author: djm@openbsd.org Date: Thu Jan 11 01:45:36 2024 +0000 upstream: make DSA key support compile-time optional, defaulting to on ok markus@ OpenBSD-Commit-ID: 4f8e98fc1fd6de399d0921d5b31b3127a03f581d commit afcc9028bfc411bc26d20bba803b83f90cb84e26 Author: jmc@openbsd.org Date: Wed Jan 10 06:33:13 2024 +0000 upstream: fix incorrect capitalisation; OpenBSD-Commit-ID: cb07eb06e15fa2334660ac73e98f29b6a1931984 commit 9707c8170c0c1baeb1e06e5a53f604498193885f Author: djm@openbsd.org Date: Tue Jan 9 22:19:36 2024 +0000 upstream: extend ChannelTimeout regression test to exercise multiplexed connections and the new "global" timeout type. ok dtucker@ OpenBSD-Regress-ID: f10d19f697024e9941acad7c2057f73d6eacb8a2 commit b31b12d28de96e1d43581d32f34da8db27e11c03 Author: djm@openbsd.org Date: Tue Jan 9 22:19:00 2024 +0000 upstream: add a "global" ChannelTimeout type to ssh(1) and sshd(8) that watches all open channels and will close all open channels if there is no traffic on any of them for the specified interval. This is in addition to the existing per-channel timeouts added a few releases ago. This supports use-cases like having a session + x11 forwarding channel open where one may be idle for an extended period but the other is actively used. The global timeout would allow closing both channels when both have been idle for too long. ok dtucker@ OpenBSD-Commit-ID: 0054157d24d2eaa5dc1a9a9859afefc13d1d7eb3 commit 602f4beeeda5bb0eca181f8753d923a2997d0a51 Author: djm@openbsd.org Date: Tue Jan 9 21:39:14 2024 +0000 upstream: adapt ssh_api.c code for kex-strict from markus@ ok me OpenBSD-Commit-ID: 4d9f256852af2a5b882b12cae9447f8f00f933ac commit 42ba34aba8708cf96583ff52975d95a8b47d990d Author: Damien Miller Date: Mon Jan 8 16:26:37 2024 +1100 nite that recent OSX tun/tap is unsupported commit 690bc125f9a3b20e47745fa8f5b5e1fd5820247f Author: Sevan Janiyan Date: Wed Dec 27 04:57:49 2023 +0000 README.platform: update tuntap url commit 6b8be2ccd7dd091808f86af52066b0c2ec30483a Author: Rose <83477269+AtariDreams@users.noreply.github.com> Date: Tue Dec 19 11:48:20 2023 -0500 Fix compilation error in ssh-pcks11-client.c Compilation fails becaus of an undefined reference to helper_by_ec, because we forgot the preprocessor conditional that excludes that function from being called in unsupported configurations. commit 219c8134157744886ee6ac5b8c1650abcd981f4c Author: djm@openbsd.org Date: Mon Jan 8 05:11:18 2024 +0000 upstream: Remove outdated note from PROTOCOL.mux Port forward close by control master is already implemented by `mux_master_process_close_fwd` in `mux.c` GHPR442 from bigb4ng OpenBSD-Commit-ID: ad0734fe5916d2dc7dd02b588906cea4df0482fb commit 4c3cf362631ccc4ffd422e572f075d5d594feace Author: djm@openbsd.org Date: Mon Jan 8 05:05:15 2024 +0000 upstream: fix missing field in users-groups-by-id@openssh.com reply documentation GHPR441 from TJ Saunders OpenBSD-Commit-ID: ff5733ff6ef4cd24e0758ebeed557aa91184c674 commit f64cede2a3c298b50a2659a8b53eb3ab2c0b8d23 Author: djm@openbsd.org Date: Mon Jan 8 04:10:03 2024 +0000 upstream: make kex-strict section more explicit about its intent: banning all messages not strictly required in KEX OpenBSD-Commit-ID: fc33a2d7f3b7013a7fb7500bdbaa8254ebc88116 commit 698fe6fd61cbcb8e3e0e874a561d4335a49fbde5 Author: Damien Miller Date: Mon Jan 8 14:46:19 2024 +1100 update fuzzer example makefile to clang16 commit fc332cb2d602c60983a8ec9f89412754ace06425 Author: Damien Miller Date: Mon Jan 8 14:45:49 2024 +1100 unbreak fuzzers - missing pkcs11_make_cert() provide stub for use in fuzzer harness commit 9ea0a4524ae3276546248a926b6641b2fbc8421b Author: Damien Miller Date: Mon Jan 8 14:45:14 2024 +1100 unbreak fuzzers for clang16 getopt() needs a throw() attribute to compile, so supply one when compiling things with C++ commit a72833d00788ef91100c643536ac08ada46440e1 Author: djm@openbsd.org Date: Mon Jan 8 00:34:33 2024 +0000 upstream: remove ext-info-* in the kex.c code, not in callers; with/ok markus@ OpenBSD-Commit-ID: c06fe2d3a0605c517ff7d65e38ec7b2d1b0b2799 commit 86f9e96d9bcfd1f5cd4bf8fb57a9b4c242df67df Author: djm@openbsd.org Date: Mon Jan 8 00:30:39 2024 +0000 upstream: fix typo; spotted by Albert Chin OpenBSD-Commit-ID: 77140b520a43375b886e535eb8bd842a268f9368 commit f0cbd26ec91bd49719fb3eea7ca44d2380318b9a Author: dtucker@openbsd.org Date: Thu Jan 4 09:51:49 2024 +0000 upstream: Import regenerated moduli. OpenBSD-Commit-ID: 5a636f6ca7f25bfe775df4952f7aac90a7fcbbee commit 64ddf776531ca4933832beecc8b7ebe1b937e081 Author: jsg@openbsd.org Date: Wed Dec 20 00:06:25 2023 +0000 upstream: spelling; ok markus@ OpenBSD-Commit-ID: 9d01f2e9d59a999d5d42fc3b3efcf8dfb892e31b commit 503fbe9ea238a4637e8778208bde8c09bcf78475 Author: jmc@openbsd.org Date: Tue Dec 19 06:57:34 2023 +0000 upstream: sort -C, and add to usage(); ok djm OpenBSD-Commit-ID: 80141b2a5d60c8593e3c65ca3c53c431262c812f commit 5413b1c7ff5a19c6a7d44bd98c5a83eb47819ba6 Author: djm@openbsd.org Date: Tue Dec 19 06:41:14 2023 +0000 upstream: correct section numbers; from Ed Maste OpenBSD-Commit-ID: e289576ee5651528404cb2fb68945556052cf83f commit 430ef864645cff83a4022f5b050174c840e275da Author: djm@openbsd.org Date: Mon Dec 18 15:58:56 2023 +0000 upstream: match flag type (s/int/u_int) OpenBSD-Commit-ID: 9422289747c35ccb7b31d0e1888ccd5e74ad566a commit 1036d77b34a5fa15e56f516b81b9928006848cbd Author: Damien Miller Date: Fri Dec 22 17:56:26 2023 +1100 better detection of broken -fzero-call-used-regs gcc 13.2.0 on ppc64le refuses to compile some function, including cipher.c:compression_alg_list() with an error: > sorry, unimplemented: argument ‘used’ is not supportedcw > for ‘-fzero-call-used-regs’ on this target This extends the autoconf will-it-work test with a similarly- structured function that seems to catch this. Spotted/tested by Colin Watson; bz3645 commit 8241b9c0529228b4b86d88b1a6076fb9f97e4a99 Author: Damien Miller Date: Tue Dec 19 01:59:50 2023 +1100 crank versions commit 2f2c65cb5f1518a9c556d3e8efa27ea0ca305c6b Author: Damien Miller Date: Tue Dec 19 01:59:06 2023 +1100 depend commit e48cdee8e19059203b1aeeabec2350b8375fa61f Author: djm@openbsd.org Date: Mon Dec 18 14:50:08 2023 +0000 upstream: regress test for agent PKCS#11-backed certificates OpenBSD-Regress-ID: 38f681777cb944a8cc3bf9d0ad62959a16764df9 commit 2f512f862df1d5f456f82a0334c9e8cc7208a2a1 Author: djm@openbsd.org Date: Mon Dec 18 14:49:39 2023 +0000 upstream: regress test for constrained PKCS#11 keys OpenBSD-Regress-ID: b2f26ae95d609d12257b43aef7cd7714c82618ff commit cdddd66412ca5920ed4d3ebbfa6ace12dbd9b82f Author: djm@openbsd.org Date: Mon Dec 18 14:48:44 2023 +0000 upstream: openssh-9.6 OpenBSD-Commit-ID: 21759837cf0e0092d9a2079f8fb562071c11016b commit 6d51feab157cedf1e7ef5b3f8781ca8ff9c4ab1b Author: djm@openbsd.org Date: Mon Dec 18 14:48:08 2023 +0000 upstream: ssh-agent: record failed session-bind attempts Record failed attempts to session-bind a connection and refuse signing operations on that connection henceforth. Prevents a future situation where we add a new hostkey type that is not recognised by an older ssh-agent, that consequently causes session-bind to fail (this situation is only likely to arise when people mix ssh(1) and ssh-agent(1) of different versions on the same host). Previously, after such a failure the agent socket would be considered unbound and not subject to restriction. Spotted by Jann Horn OpenBSD-Commit-ID: b0fdd023e920aa4831413f640de4c5307b53552e commit 7ef3787c84b6b524501211b11a26c742f829af1a Author: djm@openbsd.org Date: Mon Dec 18 14:47:44 2023 +0000 upstream: ban user/hostnames with most shell metacharacters This makes ssh(1) refuse user or host names provided on the commandline that contain most shell metacharacters. Some programs that invoke ssh(1) using untrusted data do not filter metacharacters in arguments they supply. This could create interactions with user-specified ProxyCommand and other directives that allow shell injection attacks to occur. It's a mistake to invoke ssh(1) with arbitrary untrusted arguments, but getting this stuff right can be tricky, so this should prevent most obvious ways of creating risky situations. It however is not and cannot be perfect: ssh(1) has no practical way of interpreting what shell quoting rules are in use and how they interact with the user's specified ProxyCommand. To allow configurations that use strange user or hostnames to continue to work, this strictness is applied only to names coming from the commandline. Names specified using User or Hostname directives in ssh_config(5) are not affected. feedback/ok millert@ markus@ dtucker@ deraadt@ OpenBSD-Commit-ID: 3b487348b5964f3e77b6b4d3da4c3b439e94b2d9 commit 0cb50eefdd29f0fec31d0e71cc4b004a5f704e67 Author: djm@openbsd.org Date: Mon Dec 18 14:47:20 2023 +0000 upstream: stricter handling of channel window limits This makes ssh/sshd more strict in handling non-compliant peers that send more data than the advertised channel window allows. Previously the additional data would be silently discarded. This change will cause ssh/sshd to terminate the connection if the channel window is exceeded by more than a small grace allowance. ok markus@ OpenBSD-Commit-ID: 811e21b41831eba3dd7f67b3d409a438f20d3037 commit 4448a2938abc76e6bd33ba09b2ec17a216dfb491 Author: djm@openbsd.org Date: Mon Dec 18 14:46:56 2023 +0000 upstream: Make it possible to load certs from PKCS#11 tokens Adds a protocol extension to allow grafting certificates supplied by ssh-add to keys loaded from PKCS#11 tokens in the agent. feedback/ok markus@ OpenBSD-Commit-ID: bb5433cd28ede2bc910996eb3c0b53e20f86037f commit 881d9c6af9da4257c69c327c4e2f1508b2fa754b Author: djm@openbsd.org Date: Mon Dec 18 14:46:12 2023 +0000 upstream: apply destination constraints to all p11 keys Previously applied only to the first key returned from each token. ok markus@ OpenBSD-Commit-ID: 36df3afb8eb94eec6b2541f063d0d164ef8b488d commit a7ed931caeb68947d30af8a795f4108b6efad761 Author: djm@openbsd.org Date: Mon Dec 18 14:45:49 2023 +0000 upstream: add "ext-info-in-auth@openssh.com" extension This adds another transport protocol extension to allow a sshd to send SSH2_MSG_EXT_INFO during user authentication, after the server has learned the username that is being logged in to. This lets sshd to update the acceptable signature algoritms for public key authentication, and allows these to be varied via sshd_config(5) "Match" directives, which are evaluated after the server learns the username being authenticated. Full details in the PROTOCOL file OpenBSD-Commit-ID: 1de7da7f2b6c32a46043d75fcd49b0cbb7db7779 commit 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 Author: djm@openbsd.org Date: Mon Dec 18 14:45:17 2023 +0000 upstream: implement "strict key exchange" in ssh and sshd This adds a protocol extension to improve the integrity of the SSH transport protocol, particular in and around the initial key exchange (KEX) phase. Full details of the extension are in the PROTOCOL file. with markus@ OpenBSD-Commit-ID: 2a66ac962f0a630d7945fee54004ed9e9c439f14 commit 59d691b886c79e70b1d1c4ab744e81fd176222fd Author: Damien Miller Date: Mon Dec 18 14:49:11 2023 +1100 better detection of broken -fzero-call-used-regs Use OSSH_CHECK_CFLAG_LINK() for detection of these flags and extend test program to exercise varargs, which seems to catch more stuff. ok dtucker@ commit aa7b21708511a6d4aed3839fc9f6e82e849dd4a1 Author: djm@openbsd.org Date: Wed Dec 13 03:28:19 2023 +0000 upstream: when invoking KnownHostsCommand to determine the order of host key algorithms to request, ensure that the hostname passed to the command is decorated with the port number for ports other than 22. This matches the behaviour of KnownHostsCommand when invoked to look up the actual host key. bz3643, ok dtucker@ OpenBSD-Commit-ID: 5cfabc0b7c6c7ab473666df314f377b1f15420b1 commit 4086bd6652c0badccc020218a62190a7798fb72c Author: markus@openbsd.org Date: Fri Dec 8 09:18:39 2023 +0000 upstream: prevent leak in sshsig_match_principals; ok djm@ OpenBSD-Commit-ID: 594f61ad4819ff5c72dfe99ba666a17f0e1030ae commit 19d3ee2f3adf7d9a606ff015c1e153744702c4c9 Author: djm@openbsd.org Date: Wed Dec 6 21:06:48 2023 +0000 upstream: short circuit debug log processing early if we're not going to log anything. From Kobe Housen OpenBSD-Commit-ID: 2bcddd695872a1bef137cfff7823044dcded90ea commit 947affad4831df015c498c00c6351ea6f13895d5 Author: Darren Tucker Date: Mon Nov 27 09:37:28 2023 +1100 Add tests for OpenSSL 3.2.0 and 3.2 stable branch. commit 747dce36206675ca6b885010a835733df469351b Author: Darren Tucker Date: Sat Nov 25 09:03:38 2023 +1100 Use non-zero arg in compiler test program. Now that we're running the test program, passing zero to the test function can cause divide-by-zero exceptions which might show up in logs. commit 3d44a5c56585d1c351dbc006240a591b6da502b1 Author: dtucker@openbsd.org Date: Fri Nov 24 00:31:30 2023 +0000 upstream: Plug mem leak of msg when processing a quit message. Coverity CID#427852, ok djm@ OpenBSD-Commit-ID: bf85362addbe2134c3d8c4b80f16601fbff823b7 commit 1d7f9b6e297877bd00973e6dc5c0642dbefc3b5f Author: dtucker@openbsd.org Date: Thu Nov 23 03:37:05 2023 +0000 upstream: Include existing mux path in debug message. OpenBSD-Commit-ID: 1c3641be10c2f4fbad2a1b088a441d072e18bf16 commit f29934066bd0e561a2e516b7e584fb92d2eedee0 Author: Darren Tucker Date: Thu Nov 23 19:41:27 2023 +1100 Add an Ubuntu 22.04 test VM. This is the same version as Github's runners so most of the testing on it is over there, but having a local VM makes debugging much easier. commit a93284a780cd3972afe5f89086b75d564ba157f3 Author: Darren Tucker Date: Thu Nov 23 19:36:22 2023 +1100 Add gcc-12 -Werror test on Ubuntu 22.04. Explictly specify gcc-11 on Ubuntu 22.04 (it's the system compiler). commit 670f5a647e98b6fd95ad64f789f87ee3274b481b Author: Darren Tucker Date: Thu Nov 23 19:34:57 2023 +1100 Check return value from write to prevent warning. ... and since we're testing for flags with -Werror, this caused configure to mis-detect compiler flags. commit cea007d691cfedfa07a5b8599f97ce0511f53fc9 Author: Darren Tucker Date: Wed Nov 22 21:18:55 2023 +1100 Run compiler test program when compiling natively. ok djm@ commit ee0d305828f13536c0a416bbf9c3e81039d9ea55 Author: Darren Tucker Date: Wed Nov 22 21:18:07 2023 +1100 Factor out compiler test program into a macro. ok djm@ commit de304c76316b029df460673725a9104224b9959b Author: Darren Tucker Date: Wed Nov 22 08:55:36 2023 +1100 Add fbsd14 VM to test pool. commit 99a2df5e1994cdcb44ba2187b5f34d0e9190be91 Author: Darren Tucker Date: Tue Nov 21 16:19:29 2023 +1100 Expand -fzero-call-used-regs test to cover gcc 11. It turns out that gcc also has some problems with -fzero-call-used-regs, at least v11 on mips. Previously the test in OSSH_CHECK_CFLAG_COMPILE was sufficient to catch it with "=all", but not sufficient for "=used". Expand the testcase and include it in the other tests for good measure. See bz#3629. ok djm@. commit ff220d4010717f7bfbbc02a2400666fb9d24f250 Author: Darren Tucker Date: Tue Nov 21 14:04:34 2023 +1100 Stop using -fzero-call-used-regs=all ... since it seems to be problematic with several different versions of clang. Only use -fzero-call-used-regs=used which is less problematic, except with Apple's clang where we don't use it at all. bz#3629, ok djm@ commit 2a19e02f36b16f0f6cc915f7d1e60ead5e36303b Author: Darren Tucker Date: Tue Nov 21 14:02:18 2023 +1100 Allow for vendor prefix on clang version numbers. Correctly detects the version of OpenBSD's native clang, as well as Apple's. Spotted tb@, ok djm@. commit c52db0114826d73eff6cdbf205e9c1fa4f7ca6c6 Author: djm@openbsd.org Date: Mon Nov 20 02:50:00 2023 +0000 upstream: set errno=EAFNOSUPPORT when filtering addresses that don't match AddressFamily; yields slightly better error message if no address matches. bz#3526 OpenBSD-Commit-ID: 29cea900ddd8b04a4d1968da5c4a893be2ebd9e6 commit 26f3f3bbc69196d908cad6558c8c7dc5beb8d74a Author: djm@openbsd.org Date: Wed Nov 15 23:03:38 2023 +0000 upstream: when connecting via socket (the default case), filter addresses by AddressFamily if one was specified. Fixes the case where, if CanonicalizeHostname is enabled, ssh may ignore AddressFamily. bz5326; ok dtucker OpenBSD-Commit-ID: 6c7d7751f6cd055126b2b268a7b64dcafa447439 commit 050c335c8da43741ed0df2570ebfbd5d1dfd0a31 Author: djm@openbsd.org Date: Wed Nov 15 22:51:49 2023 +0000 upstream: when deciding whether to enable keystroke timing obfuscation, only consider enabling it when a channel with a tty is open. Avoids turning on the obfucation when X11 forwarding only is in use, which slows it right down. Reported by Roger Marsh OpenBSD-Commit-ID: c292f738db410f729190f92de100c39ec931a4f1 commit 676377ce67807a24e08a54cd60ec832946cc6cae Author: tobhe@openbsd.org Date: Mon Nov 13 09:18:19 2023 +0000 upstream: Make sure sftp_get_limits() only returns 0 if 'limits' was initialized. This fixes a potential uninitialized use of 'limits' in sftp_init() if sftp_get_limits() returned early because of an unexpected message type. ok djm@ OpenBSD-Commit-ID: 1c177d7c3becc1d71bc8763eecf61873a1d3884c commit 64e0600f23c6dec36c3875392ac95b8a9100c2d6 Author: Darren Tucker Date: Mon Nov 13 20:03:31 2023 +1100 Test current releases of LibreSSL and OpenSSL. Retire some of the older releases. commit c8ed7cc545879ac15f6ce428be4b29c35598bb2a Author: dtucker@openbsd.org Date: Wed Nov 1 02:08:38 2023 +0000 upstream: Specify ssh binary to use ... instead of relying on installed one. Fixes test failures in -portable when running tests prior to installation. OpenBSD-Regress-ID: b6d6ba71c23209c616efc805a60d9a445d53a685 commit e9fc2c48121cada1b4dcc5dadea5d447fe0093c3 Author: Darren Tucker Date: Wed Nov 1 13:11:31 2023 +1100 Put long-running test targets on hipri runners. Some of the selfhosted test targets take a long time to run for various reasons, so label them for "libvirt-hipri" runners so that they can start immediately. This should reduce the time to complete all tests. commit 7ddf27668f0e21233f08c0ab2fe9ee3fdd6ab1e2 Author: djm@openbsd.org Date: Wed Nov 1 00:29:46 2023 +0000 upstream: add some tests of forced commands overriding Subsystem directives OpenBSD-Regress-ID: eb48610282f6371672bdf2a8b5d2aa33cfbd322b commit fb06f9b5a065dfbbef5916fc4accc03c0bf026dd Author: dtucker@openbsd.org Date: Tue Oct 31 04:15:40 2023 +0000 upstream: Don't try to use sudo inside sshd log wrapper. We still need to check if we're using sudo since we don't want to chown unecessarily, as on some platforms this causes an error which pollutes stderr. We also don't want to unnecessarily invoke sudo, since it's running in the context of the proxycommand, on *other* platforms it may not be able to authenticate, and if we're using SUDO then it should already be privileged. OpenBSD-Regress-ID: 70d58df7503db699de579a9479300e5f3735f4ee commit fc3cc33e88c242c704781c6c48087838f1dcfa2a Author: dtucker@openbsd.org Date: Tue Oct 31 02:58:45 2023 +0000 upstream: Only try to chmod logfile if we have sudo. If we don't have sudo then we won't need to chmod. OpenBSD-Regress-ID: dbad2f5ece839658ef8af3376cb1fb1cabe2e324 commit 3a506598fddd3f18f9095af3fe917f24cbdd32e0 Author: djm@openbsd.org Date: Mon Oct 30 23:00:25 2023 +0000 upstream: move PKCS#11 setup code to test-exec.sh so it can be reused elsewhere OpenBSD-Regress-ID: 1d29e6be40f994419795d9e660a8d07f538f0acb commit f82fa227a52661c37404a6d33bbabf14fed05db0 Author: djm@openbsd.org Date: Mon Oct 30 17:32:00 2023 +0000 upstream: tidy and refactor PKCS#11 setup code Replace the use of a perl script to delete the controlling TTY with a SSH_ASKPASS script to directly load the PIN. Move PKCS#11 setup code to functions in anticipation of it being used elsewhere in additional tests. Reduce stdout spam OpenBSD-Regress-ID: 07705c31de30bab9601a95daf1ee6bef821dd262 commit 3cf698c6d4ffa9be1da55672a3519e2135a6366a Author: Darren Tucker Date: Mon Oct 30 21:35:03 2023 +1100 Add obsd74 test VM and retire obsd69 and obsd70. commit 3e21d58a09894acb38dc69ed615d101131f473d0 Author: Darren Tucker Date: Mon Oct 30 18:34:12 2023 +1100 Add OpenSSL 3.3.0 as a known dev version. commit 917ba181c2cbdb250a443589ec732aa36fd51ffa Author: Darren Tucker Date: Mon Oct 30 13:32:03 2023 +1100 Restore nopasswd sudo rule on Mac OS X. This seems to be missing from some (but not all) github runners, so restore it if it seems to be missing. commit c5698abad6d4ec98ca20bcaaabaeacd5e1ec3f4f Author: Darren Tucker Date: Mon Oct 30 13:26:52 2023 +1100 Don't exit early when setting up on Mac OS X. We probably need some of the other bits in there (specifically, setting the perms on the home directory) so make it less of a special snowflake. commit 1d6a878ceba60b9dc14037dddc8f036070c0065f Author: dtucker@openbsd.org Date: Sun Oct 29 06:22:07 2023 +0000 upstream: Only try to chown logfiles that exist to prevent spurious errors. OpenBSD-Regress-ID: f1b20a476734e885078c481f1324c9ea03af991e commit e612376427a66f835e284f6b426d16d7c85301bc Author: anton@openbsd.org Date: Thu Oct 26 18:52:45 2023 +0000 upstream: make use of bsd.regress.mk in extra and interop targets; ok dtucker@ OpenBSD-Regress-ID: 7ea21b5f6fc4506165093b2123d88d20ff13a4f0 commit ea0039173957d0edcd6469b9614dcedb44dcb4f9 Author: dtucker@openbsd.org Date: Thu Oct 26 12:44:07 2023 +0000 upstream: Skip conch interop tests when not enabled instead of fatal. OpenBSD-Regress-ID: b0abf81c24ac6c21f367233663228ba16fa96a46 commit d220b9ed5494252b26b95f05be118472bc3ab5c0 Author: dtucker@openbsd.org Date: Wed Oct 25 05:38:08 2023 +0000 upstream: Import regenerated moduli. OpenBSD-Commit-ID: 95f5dd6107e8902b87dc5b005ef2b53f1ff378b8 commit a611e4db4009447a0151f31a44e235ca32ed4429 Author: anton@openbsd.org Date: Wed Oct 25 08:01:59 2023 +0000 upstream: ssh conch interop tests requires a controlling terminal; ok dtucker@ OpenBSD-Regress-ID: cbf2701bc347c2f19d907f113779c666f1ecae4a commit da951b5e08c167acb5d6e2eec6f146502f5d6ed8 Author: anton@openbsd.org Date: Mon Oct 23 11:30:49 2023 +0000 upstream: Use private key that is allowed by sshd defaults in conch interop tests. ok dtucker@ OpenBSD-Regress-ID: 3b7f65c8f409c328bcd4b704f60cb3d31746f045 commit 1ca166dbb3c0ce632b98869cd955f69320aa6fe8 Author: Darren Tucker Date: Fri Oct 20 20:43:00 2023 +1100 Install Dropbear for interop testing. commit f993bb58351c5cb71e61aede63805a34a6d4daea Author: Darren Tucker Date: Fri Oct 20 20:39:03 2023 +1100 Resync PuTTY and Conch path handling with upstream. Now that configure finds these for us we can remove these -portable specific changes. commit ff85becd5f5f06a76efa45d30fb204a3c5e5215c Author: Darren Tucker Date: Fri Oct 20 20:35:46 2023 +1100 Have configure find PuTTY and Conch binaries. This will let us remove some -portable specific changes from test-exec.sh. commit c54a50359b9cecddbf3ffcdc26efcb3cd6071ec1 Author: dtucker@openbsd.org Date: Fri Oct 20 07:37:07 2023 +0000 upstream: Allow overriding the locations of the Dropbear binaries similar to what we do for the PuTTY ones. OpenBSD-Regress-ID: 7de0e00518fb0c8fdc5f243b7f82f523c936049c commit fbaa707d455a61d0aef8ae65e02a25bac5351e5c Author: dtucker@openbsd.org Date: Fri Oct 20 06:56:45 2023 +0000 upstream: Add interop test with Dropbear. Right now this is only dbclient not the Dropbear server since it won't currently run as a ProxyCommand. OpenBSD-Regress-ID: 8cb898c414fcdb252ca6328896b0687acdaee496 commit c2003d0dbdcdb61ca336c3f90c5c2b4a09c8e73f Author: Fabio Pedretti Date: Mon Oct 16 11:59:53 2023 +0200 Update openssl-devel dependency in RPM spec. Since openssh 9.4p1, openssl >= 1.1.1 is required, so build with --without-openssl elsewhere. According to https://repology.org/project/openssl/versions openssl 1.1.1 is available on fedora >= 29 and rhel >= 8. Successfully build tested, installed and run on rhel 6 commit 064e09cd632721c7e6889904e07767443ee23821 Author: Fabio Pedretti Date: Mon Oct 16 10:13:06 2023 +0200 Remove reference of dropped sshd.pam.old file The file was removed in openssh 8.8 commit 62db354b696b378a164b6e478cb6b0171dcb0c3d Author: dtucker@openbsd.org Date: Mon Oct 16 08:40:00 2023 +0000 upstream: Move declaration of "len" into the block where it's used. This lets us compile Portable with -Werror with when OpenSSL doesn't have Ed25519 support. OpenBSD-Commit-ID: e02e4b4af351946562a7caee905da60eff16ba29 commit 6eee8c972d5901d10e80634a006b4e346b2c8c19 Author: Damien Miller Date: Fri Oct 13 15:15:05 2023 +1100 run t-extra regress tests This exposes the t-extra regress tests (including agent-pkcs11.sh) as a new extra-tests target in the top level Makefile and runs them by default. ok dtucker@ commit 637624dbbac13f2bc3c8ec5b15c9d627d07f2935 Author: Darren Tucker Date: Thu Oct 12 22:01:23 2023 +1100 Don't use make -j2. While we have 2 cores available on github runners, not using it means that the most recent log message is the actual failure, rather than having to search back through the log for it. commit 971e0cfcfd52ef1d73cf5244074c306a60006e89 Author: Darren Tucker Date: Thu Oct 12 16:23:05 2023 +1100 Correct arg order for ED255519 AC_LINK_IFELSE test. commit c616e64688b2a0c1b4daad69b056099be998d121 Author: djm@openbsd.org Date: Thu Oct 12 03:51:08 2023 +0000 upstream: typos and extra debug trace calls OpenBSD-Regress-ID: 98a2a6b9333743274359e3c0f0e65cf919a591d1 commit c49a3fbf10162128c67c59562348de2041188974 Author: djm@openbsd.org Date: Thu Oct 12 03:48:53 2023 +0000 upstream: ensure logs are owned by correct user; feedback/ok dtucker@ OpenBSD-Regress-ID: c3297af8f07717f1d400a5d34529962f1a76b5a3 commit 5ec0ed79ac074c3437b25f6cba8b8cf21c8d4587 Author: djm@openbsd.org Date: Thu Oct 12 03:36:32 2023 +0000 upstream: 64 %-expansion keys ought to be enough for anybody; ok dtucker (we just hit the previous limit in some cases) OpenBSD-Commit-ID: 84070f8001ec22ff5d669f836b62f206e08c5787 commit f59a94e22e46db2c23eddeb871aa9e8d93ab0016 Author: djm@openbsd.org Date: Thu Oct 12 02:48:43 2023 +0000 upstream: don't dereference NULL pointer when hashing jumphost OpenBSD-Commit-ID: 251c0263e1759a921341c7efe7f1d4c73e1c70f4 commit 281c79168edcc303abfd5bca983616eaa24c5f32 Author: Damien Miller Date: Thu Oct 12 13:20:01 2023 +1100 Solaris: prefer PRIV_XPOLICY to PRIV_LIMIT If the system support PRIV_XPOLICY and one is set, then don't modify PRIV_LIMIT. bz2833, patch from Ron Jordan, ok dtucker@ commit 98fc34df837f3a3b79d2a111b96fe8a39adcab55 Author: djm@openbsd.org Date: Thu Oct 12 02:18:18 2023 +0000 upstream: add %j token that expands to the configured ProxyJump hostname (or the empty string if this option is not being used). bz3610, ok dtucker OpenBSD-Commit-ID: ce9983f7efe6a178db90dc5c1698df025df5e339 commit 7f3180be8a85320b5d3221714b40c16e66881249 Author: djm@openbsd.org Date: Thu Oct 12 02:15:53 2023 +0000 upstream: release GSS OIDs only at end of authentication; bz2982, ok dtucker@ OpenBSD-Commit-ID: 0daa41e0525ae63cae4483519ecaa37ac485d94c commit a612b93de5d86e955bfb6e24278f621118eea500 Author: djm@openbsd.org Date: Thu Oct 12 02:12:53 2023 +0000 upstream: mask SIGINT/TERM/QUIT/HUP before checking quit_pending and use ppoll() to unmask them in the mainloop. Avoids race condition between signaling ssh to exit and polling. bz3531; ok dtucker OpenBSD-Commit-ID: 5c14e1aabcddedb95cdf972283d9c0d5083229e7 commit 531b27a006116fe7aff325510aaa576f24844452 Author: djm@openbsd.org Date: Wed Oct 11 23:23:58 2023 +0000 upstream: sync usage() with ssh.1; spotted by kn@ OpenBSD-Commit-ID: 191a85639477dcb5fa1616d270d93b7c8d5c1dfd commit 64f7ca881b19be754425dca60d1590d306c9d1d0 Author: djm@openbsd.org Date: Wed Oct 11 23:14:33 2023 +0000 upstream: ssh -Q does not make sense with other command-line options, so give it its own line in the manpage OpenBSD-Commit-ID: 00a747f0655c12122bbb77c2796be0013c105361 commit a752a6c0e1001f93696d7025f0c867f0376e2ecf Author: djm@openbsd.org Date: Wed Oct 11 22:42:26 2023 +0000 upstream: add ChannelTimeout support to the client, mirroring the same option in the server. ok markus@ OpenBSD-Commit-ID: 55630b26f390ac063980cfe7ad8c54b03284ef02 commit 76e91e7238cdc5662bc818e2a48d466283840d23 Author: djm@openbsd.org Date: Wed Oct 11 22:41:05 2023 +0000 upstream: add support for reading ED25519 private keys in PEM PKCS8 format; ok markus@ tb@ OpenBSD-Commit-ID: 01b85c91757e6b057e9b23b8a23f96415c3c7174 commit fc77c8e352c0f44125425c05265e3a00c183d78a Author: djm@openbsd.org Date: Wed Oct 11 06:40:54 2023 +0000 upstream: mention "none" is a valid argument to IdentityFile; bz3080 OpenBSD-Commit-ID: 1b4fb590ef731099349a7d468b77f02b240ac926 commit c97520d23d1fe53d30725a2af25d2dddd6f2faff Author: djm@openbsd.org Date: Wed Oct 11 05:42:08 2023 +0000 upstream: in olde rcp/scp protocol mode, when rejecting a path from the server as not matching the glob that the client sent, log (at debug level) the received pathname as well as the list of possible expected paths expanded from the glob. bz2966 OpenBSD-Commit-ID: 0bd8db8a595334ca86bca8f36e23fc0395315765 commit 208c2b719879805983398160791d6a1ef9c2c3fc Author: djm@openbsd.org Date: Wed Oct 11 04:46:29 2023 +0000 upstream: s/%.100s/%s/ in SSH- banner construction as there's no reason to limit its size: the version string bring included is a compile time constant going into an allocated banner string. OpenBSD-Commit-ID: 0ef73304b9bf3e534c60900cd84ab699f859ebcd commit 0354790826b97c41bbd171a965574e159b58d83e Author: tb@openbsd.org Date: Tue Oct 10 06:49:54 2023 +0000 upstream: Garbage collect cipher_get_keyiv_len() This is a compat20 leftover, unused since 2017. ok djm OpenBSD-Commit-ID: 91fa5497c9dc6883064624ac27813a567883fdce commit 8d29ee4115001a02641386ae394992c65ed279e0 Author: djm@openbsd.org Date: Tue Oct 10 03:57:45 2023 +0000 upstream: Reserve a range of "local extension" message numbers that OpenSSH promises not to use (comment change only) OpenBSD-Commit-ID: e61795b453d4892d2c99ce1039112c4a00250e03 commit 90b0d73d63a706e85f6431f05a62d2ce1b476472 Author: djm@openbsd.org Date: Fri Oct 6 03:32:15 2023 +0000 upstream: typo in error message OpenBSD-Regress-ID: 6a8edf0dc39941298e3780b147b10c0a600b4fee commit e84517f51532ec913d8fb01a8aab7307134774bb Author: djm@openbsd.org Date: Fri Oct 6 03:25:14 2023 +0000 upstream: Perform the softhsm2 setup as discrete steps rather than as a long shell pipeline. Makes it easier to figure out what has happened when it breaks. OpenBSD-Regress-ID: b3f1292115fed65765d0a95414df16e27772d81c commit cb54becff4d776238e0e9072943ba0872260535d Author: claudio@openbsd.org Date: Sun Sep 24 08:14:13 2023 +0000 upstream: REGRESS_FAIL_EARLY defaults to yes now. So no need to overload the value here anymore. OK tb@ bluhm@ OpenBSD-Regress-ID: f063330f1bebbcd373100afccebc91a965b14496 commit f01f5137ceba65baf34ceac5a298c12ac01b1fef Author: jmc@openbsd.org Date: Wed Oct 4 05:42:10 2023 +0000 upstream: spelling fix; OpenBSD-Commit-ID: 493f95121567e5ab0d9dd1150f873b5535ca0195 commit 80a2f64b8c1d27383cc83d182b73920d1e6a91f1 Author: Damien Miller Date: Wed Oct 4 15:34:10 2023 +1100 crank version numbers commit f65f187b105d9b5c12fd750a211397d08c17c6d4 Author: djm@openbsd.org Date: Wed Oct 4 04:04:09 2023 +0000 upstream: openssh-9.5 OpenBSD-Commit-ID: 5e0af680480bd3b6f5560cf840ad032d48fd6b16 commit ffe27e54a4bb18d5d3bbd3f4cc93a41b8d94dfd2 Author: djm@openbsd.org Date: Wed Oct 4 04:03:50 2023 +0000 upstream: add some cautionary text about % token expansion and shell metacharacters; based on report from vinci AT protonmail.ch OpenBSD-Commit-ID: aa1450a54fcee2f153ef70368d90edb1e7019113 commit 60ec3d54fd1ebfe2dda75893fa1e870b8dffbb0d Author: djm@openbsd.org Date: Tue Oct 3 23:56:10 2023 +0000 upstream: fix link to agent draft; spotted by Jann Horn OpenBSD-Commit-ID: ff5bda21a83ec013db683e282256a85201d2dc4b commit 12e2d4b13f6f63ce2de13cbfcc9e4d0d4b4ab231 Author: Damien Miller Date: Wed Oct 4 10:54:04 2023 +1100 use portable provider allowlist path in manpage spotted by Jann Horn commit 6c2c6ffde75df95fd838039850d3dd3d84956d87 Author: deraadt@openbsd.org Date: Tue Sep 19 20:37:07 2023 +0000 upstream: typo; from Jim Spath OpenBSD-Commit-ID: 2f5fba917b5d4fcf93d9e0b0756c7f63189e228e commit b6b49130a0089b297245ee39e769231d7c763014 Author: djm@openbsd.org Date: Sun Sep 10 23:12:32 2023 +0000 upstream: rename remote_glob() -> sftp_glob() to match other API OpenBSD-Commit-ID: d9dfb3708d824ec02970a84d96cf5937e0887229 commit 21b79af6c8d2357c822c84cef3fbdb8001ed263b Author: djm@openbsd.org Date: Sun Sep 10 03:51:55 2023 +0000 upstream: typo in comment OpenBSD-Commit-ID: 69285e0ce962a7c6b0ab5f17a293c60a0a360a18 commit 41232d25532b4d2ef6c5db62efc0cf50a79d26ca Author: Darren Tucker Date: Sun Sep 10 15:45:38 2023 +1000 Use zero-call-used-regs=used with Apple compilers. Apple's versions of clang have version numbers that do not match the corresponding upstream clang versions. Unfortunately, they do still have the clang-15 zero-call-used-regs=all bug, so for now use the value that doesn't result in segfaults. We could allowlist future versions that are known to work. bz#3584 (and probably also our github CI failures). commit 90ccc5918ea505bf156c31148b6b59a1bf5d6dc6 Author: djm@openbsd.org Date: Sun Sep 10 03:25:53 2023 +0000 upstream: randomise keystroke obfuscation intervals and average interval rate. ok dtucker@ OpenBSD-Commit-ID: 05f61d051ab418fcfc4857ff306e420037502382 commit bd1b9e52f5fa94d87223c90905c5fdc1a7c32aa6 Author: djm@openbsd.org Date: Fri Sep 8 06:34:24 2023 +0000 upstream: fix sizeof(*ptr) instead sizeof(ptr) in realloc (pointer here is char**, so harmless); spotted in CID 416964 OpenBSD-Commit-ID: c61caa4a5a667ee20bb1042098861e6c72c69002 commit c4f966482983e18601eec70a1563115de836616f Author: djm@openbsd.org Date: Fri Sep 8 06:10:57 2023 +0000 upstream: regress test recursive remote-remote directories copies where the directory contains a symlink to another directory. also remove errant `set -x` that snuck in at some point OpenBSD-Regress-ID: 1c94a48bdbd633ef2285954ee257725cd7bc456f commit 5e1dfe5014ebc194641678303e22ab3bba15f4e5 Author: djm@openbsd.org Date: Fri Sep 8 06:10:02 2023 +0000 upstream: fix recursive remote-remote copies of directories that contain symlinks to other directories (similar to bz3611) OpenBSD-Commit-ID: 7e19d2ae09b4f941bf8eecc3955c9120171da37f commit 7c0ce2bf98b303b6ad91493ee3247d96c18ba1f6 Author: djm@openbsd.org Date: Fri Sep 8 05:50:57 2023 +0000 upstream: regress test for recursive copies of directories containing symlinks to other directories. bz3611, ok dtucker@ OpenBSD-Regress-ID: eaa4c29cc5cddff4e72a16bcce14aeb1ecfc94b9 commit 2de990142a83bf60ef694378b8598706bc654b08 Author: djm@openbsd.org Date: Fri Sep 8 05:56:13 2023 +0000 upstream: the sftp code was one of my first contributions to OpenSSH and it shows - the function names are terrible. Rename do_blah() to sftp_blah() to make them less so. Completely mechanical except for sftp_stat() and sftp_lstat() which change from returning a pointer to a static variable (error-prone) to taking a pointer to a caller-provided receiver. OpenBSD-Commit-ID: eb54d6a72d0bbba4d623e2175cf5cc4c75dc2ba4 commit 249d8bd0472b53e3a2a0e138b4c030a31e83346a Author: djm@openbsd.org Date: Fri Sep 8 05:50:12 2023 +0000 upstream: fix scp in SFTP mode recursive upload and download of directories that contain symlinks to other directories. In scp mode, the links would be followed, but in SFTP mode they were not. bz3611, ok dtucker@ OpenBSD-Commit-ID: 9760fda668eaa94a992250d7670dfbc62a45197c commit 0e1f4401c466fa4fdaea81b6dadc8dd1fc4cf0af Author: djm@openbsd.org Date: Wed Sep 6 23:36:09 2023 +0000 upstream: regression test for override of subsystem in match blocks OpenBSD-Regress-ID: 5f8135da3bfda71067084c048d717b0e8793e87c commit 8a1450c62035e834d8a79a5d0d1c904236f9dcfe Author: djm@openbsd.org Date: Wed Sep 6 23:35:35 2023 +0000 upstream: allow override of Sybsystem directives in sshd Match blocks OpenBSD-Commit-ID: 3911d18a826a2d2fe7e4519075cf3e57af439722 commit 6e52826e2a74d077147a82ead8d4fbd5b54f4e3b Author: djm@openbsd.org Date: Wed Sep 6 23:26:37 2023 +0000 upstream: allocate the subsystems array as necessary and remove the fixed limit of subsystems. Saves a few kb of memory in the server and makes it more like the other options. OpenBSD-Commit-ID: e683dfca6bdcbc3cc339bb6c6517c0c4736a547f commit e19069c9fac4c111d6496b19c7f7db43b4f07b4f Author: djm@openbsd.org Date: Wed Sep 6 23:23:53 2023 +0000 upstream: preserve quoting of Subsystem commands and arguments. This may change behaviour of exotic configurations, but the most common subsystem configuration (sftp-server) is unlikely to be affected. OpenBSD-Commit-ID: 8ffa296aeca981de5b0945242ce75aa6dee479bf commit 52dfe3c72d98503d8b7c6f64fc7e19d685636c0b Author: djm@openbsd.org Date: Wed Sep 6 23:21:36 2023 +0000 upstream: downgrade duplicate Subsystem directives from being a fatal error to being a debug message to match behaviour with just about all other directives. OpenBSD-Commit-ID: fc90ed2cc0c18d4eb8e33d2c5e98d25f282588ce commit 1ee0a16e07b6f0847ff463d7b5221c4bf1876e25 Author: djm@openbsd.org Date: Wed Sep 6 23:18:15 2023 +0000 upstream: handle cr+lf (instead of just cr) in sshsig signature files OpenBSD-Commit-ID: 647460a212b916540016d066568816507375fd7f commit e1c284d60a928bcdd60bc575c6f9604663502770 Author: job@openbsd.org Date: Mon Sep 4 10:29:58 2023 +0000 upstream: Generate Ed25519 keys when invoked without arguments Ed25519 public keys are very convenient due to their small size. OpenSSH has supported Ed25519 since version 6.5 (January 2014). OK djm@ markus@ sthen@ deraadt@ OpenBSD-Commit-ID: f498beaad19c8cdcc357381a60df4a9c69858b3f commit 694150ad92765574ff82a18f4e86322bd3231e68 Author: djm@openbsd.org Date: Mon Sep 4 00:08:14 2023 +0000 upstream: trigger keystroke timing obfucation only if the channels layer enqueud some data in the last poll() cycle; this avoids triggering the obfuscatior for non-channels data like ClientAlive probes and also fixes a related problem were the obfucations would be triggered on fully quiescent connections. Based on / tested by naddy@ OpenBSD-Commit-ID: d98f32dc62d7663ff4660e4556e184032a0db123 commit b5fd97896b59a3a46245cf438cc8b16c795d9f74 Author: djm@openbsd.org Date: Mon Sep 4 00:04:02 2023 +0000 upstream: avoid bogus "obfuscate_keystroke_timing: stopping ..." debug messages when keystroke timing obfuscation was never started; spotted by naddy@ OpenBSD-Commit-ID: 5c270d35f7d2974db5c1646e9c64188f9393be31 commit ccf7d913db34e49b7a6db1b8331bd402004c840d Author: djm@openbsd.org Date: Mon Sep 4 00:01:46 2023 +0000 upstream: make channel_output_poll() return a flag indicating whether channel data was enqueued. Will be used to improve keystroke timing obfuscation. Problem spotted by / tested by naddy@ OpenBSD-Commit-ID: f9776c7b0065ba7c3bbe50431fd3b629f44314d0 commit 43254b326ac6e2131dbd750f9464dc62c14bd5a7 Author: djm@openbsd.org Date: Sun Sep 3 23:59:32 2023 +0000 upstream: set interactive mode for ControlPersist sessions if they originally requested a tty; enables keystroke timing obfuscation for most ControlPersist sessions. Spotted by naddy@ OpenBSD-Commit-ID: 72783a26254202e2f3f41a2818a19956fe49a772 commit ff3eda68ceb2e2bb8f48e3faceb96076c3e85c20 Author: Darren Tucker Date: Thu Aug 31 23:02:35 2023 +1000 Set LLONG_MAX for C89 test. If we don't have LLONG_MAX, configure will figure out that it can get it by setting -std=gnu99, at which point we won't be testing C89 any more. To avoid this, feed it in via CFLAGS. commit f98031773db361424d59e3301aa92aacf423d920 Author: djm@openbsd.org Date: Tue Aug 29 02:50:10 2023 +0000 upstream: make PerSourceMaxStartups first-match-wins; ok dtucker@ OpenBSD-Commit-ID: dac0c24cb709e3c595b8b4f422a0355dc5a3b4e7 commit cfa66857db90cd908de131e0041a50ffc17c7df8 Author: djm@openbsd.org Date: Mon Aug 28 09:52:09 2023 +0000 upstream: descriptive text shouldn't be under .Cm OpenBSD-Commit-ID: b1afaeb456a52bc8a58f4f9f8b2f9fa8f6bf651b commit 01dbf3d46651b7d6ddf5e45d233839bbfffaeaec Author: djm@openbsd.org Date: Mon Aug 28 09:48:11 2023 +0000 upstream: limit artificial login delay to a reasonable maximum (5s) and don't delay at all for the "none" authentication mechanism. Patch by Dmitry Belyavskiy in bz3602 with polish/ok dtucker@ OpenBSD-Commit-ID: 85b364676dd84cf1de0e98fc2fbdcb1a844ce515 commit 528da5b9d7c5da01ed7a73ff21c722e1b5326006 Author: jmc@openbsd.org Date: Mon Aug 28 05:32:28 2023 +0000 upstream: add spacing for punctuation when macro args; OpenBSD-Commit-ID: e80343c16ce0420b2aec98701527cf90371bd0db commit 3867361ca691d0956ef7d5fb8181cf554a91d84a Author: djm@openbsd.org Date: Mon Aug 28 04:06:52 2023 +0000 upstream: explicit long long type in timing calculations (doesn't matter, since the range is pre-clamped) OpenBSD-Commit-ID: f786ed902d04a5b8ecc581d068fea1a79aa772de commit 7603ba71264e7fa938325c37eca993e2fa61272f Author: djm@openbsd.org Date: Mon Aug 28 03:31:16 2023 +0000 upstream: Add keystroke timing obfuscation to the client. This attempts to hide inter-keystroke timings by sending interactive traffic at fixed intervals (default: every 20ms) when there is only a small amount of data being sent. It also sends fake "chaff" keystrokes for a random interval after the last real keystroke. These are controlled by a new ssh_config ObscureKeystrokeTiming keyword/ feedback/ok markus@ OpenBSD-Commit-ID: 02231ddd4f442212820976068c34a36e3c1b15be commit dce6d80d2ed3cad2c516082682d5f6ca877ef714 Author: djm@openbsd.org Date: Mon Aug 28 03:28:43 2023 +0000 upstream: Introduce a transport-level ping facility This adds a pair of SSH transport protocol messages SSH2_MSG_PING/PONG to implement a ping capability. These messages use numbers in the "local extensions" number space and are advertised using a "ping@openssh.com" ext-info message with a string version number of "0". ok markus@ OpenBSD-Commit-ID: b6b3c4cb2084c62f85a8dc67cf74954015eb547f commit d2d247938b38b928f8a6e1a47a330c5584d3a358 Author: tobhe@openbsd.org Date: Mon Aug 21 21:16:18 2023 +0000 upstream: Log errors in kex_exchange_identification() with level verbose instead of error to reduce preauth log spam. All of those get logged with a more generic error message by sshpkt_fatal(). feedback from sthen@ ok djm@ OpenBSD-Commit-ID: bd47dab4695b134a44c379f0e9a39eed33047809 commit 9d7193a8359639801193ad661a59d1ae4dc3d302 Author: djm@openbsd.org Date: Mon Aug 21 04:59:54 2023 +0000 upstream: correct math for ClientAliveInterval that caused the probes to be sent less frequently than configured; from Dawid Majchrzak OpenBSD-Commit-ID: 641153e7c05117436ddfc58267aa267ca8b80038 commit 3c6ab63b383b0b7630da175941e01de9db32a256 Author: Darren Tucker Date: Fri Aug 25 14:48:02 2023 +1000 Include Portable version in sshd version string. bz#3608, ok djm@ commit 17fa6cd10a26e193bb6f65d21264d2fe553bcd87 Author: Darren Tucker Date: Mon Aug 21 19:47:58 2023 +1000 obsd-arm64 host is real hardware... so put in the correct config location. commit 598ca75c85acaaacee5ef954251e489cc20d7be9 Author: Darren Tucker Date: Mon Aug 21 18:38:36 2023 +1000 Add OpenBSD ARM64 test host. commit 1acac79bfbe207e8db639e8043524962037c8feb Author: Darren Tucker Date: Mon Aug 21 18:05:26 2023 +1000 Add test for zlib development branch. commit 84efebf352fc700e9040c8065707c63caedd36a3 Author: djm@openbsd.org Date: Mon Aug 21 04:36:46 2023 +0000 upstream: want stdlib.h for free(3) OpenBSD-Commit-ID: 743af3c6e3ce5e6cecd051668f0327a01f44af29 commit cb4ed12ffc332d1f72d054ed92655b5f1c38f621 Author: Darren Tucker Date: Sat Aug 19 07:39:08 2023 +1000 Fix zlib version check for 1.3 and future version. bz#3604. commit 25b75e21f16bccdaa472ea1889b293c9bd51a87b Author: Darren Tucker Date: Mon Aug 14 11:10:08 2023 +1000 Add 9.4 branch to CI status page. commit 803e22eabd3ba75485eedd8b7b44d6ace79f2052 Author: djm@openbsd.org Date: Fri Aug 18 01:37:41 2023 +0000 upstream: fix regression in OpenSSH 9.4 (mux.c r1.99) that caused multiplexed sessions to ignore SIGINT under some circumstances. Reported by / feedback naddy@, ok dtucker@ OpenBSD-Commit-ID: 4d5c6c894664f50149153fd4764f21f43e7d7e5a commit e706bca324a70f68dadfd0ec69edfdd486eed23a Author: djm@openbsd.org Date: Wed Aug 16 16:14:11 2023 +0000 upstream: defence-in-depth MaxAuthTries check in monitor; ok markus OpenBSD-Commit-ID: 65a4225dc708e2dae71315adf93677edace46c21 commit d1ab7eb90474df656d5e9935bae6df0bd000d343 Author: djm@openbsd.org Date: Mon Aug 14 03:37:00 2023 +0000 upstream: add message number of SSH2_MSG_NEWCOMPRESS defined in RFC8308 OpenBSD-Commit-ID: 6c984171c96ed67effd7b5092f3d3975d55d6028 commit fa8da52934cb7dff6f660a143276bdb28bb9bbe1 Author: Darren Tucker Date: Sun Aug 13 15:01:27 2023 +1000 Add obsd72 and obsd73 test targets. commit f9f18006678d2eac8b0c5a5dddf17ab7c50d1e9f Author: djm@openbsd.org Date: Thu Aug 10 23:05:48 2023 +0000 upstream: better debug logging of sessions' exit status OpenBSD-Commit-ID: 82237567fcd4098797cbdd17efa6ade08e1a36b0 commit a8c57bcb077f0cfdffcf9f23866bf73bb93e185c Author: naddy@openbsd.org Date: Thu Aug 10 14:37:32 2023 +0000 upstream: drop a wayward comma, ok jmc@ OpenBSD-Commit-ID: 5c11fbb9592a29b37bbf36f66df50db9d38182c6 commit e962f9b318a238db1becc53c2bf79dd3a49095b4 Author: Damien Miller Date: Thu Aug 10 11:10:22 2023 +1000 depend commit 0fcb60bf83130dfa428bc4422b3a3ac20fb528af Author: Damien Miller Date: Thu Aug 10 11:05:42 2023 +1000 update versions in RPM specs commit d0cee4298491314f09afa1c4383a66d913150b26 Author: Damien Miller Date: Thu Aug 10 11:05:14 2023 +1000 update version in README commit 78b4dc6684f4d35943b46b24ee645edfdb9974f5 Author: djm@openbsd.org Date: Thu Aug 10 01:01:07 2023 +0000 upstream: openssh-9.4 OpenBSD-Commit-ID: 71fc1e01a4c4ea061b252bd399cda7be757e6e35 commit 58ca4f0aa8c4306ac0a629c9a85fb1efaf4ff092 Author: Darren Tucker Date: Thu Aug 10 11:30:24 2023 +1000 Only include unistd.h once. commit 3961ed02dc578517a9d2535128cff5c3a5460d28 Author: Damien Miller Date: Thu Aug 10 09:08:49 2023 +1000 wrap poll.h include in HAVE_POLL_H commit e535fbe2af893046c28adfcd787c1fdbae36a24a Author: dtucker@openbsd.org Date: Fri Aug 4 06:32:40 2023 +0000 upstream: Apply ConnectTimeout to multiplexing local socket connections. If the multiplex socket exists but the connection times out, ssh will fall back to a direct connection the same way it would if the socket did not exist at all. ok djm@ OpenBSD-Commit-ID: 2fbe1a36d4a24b98531b2d298a6557c8285dc1b4 commit 9d92e7b24848fcc605945f7c2e3460c7c31832ce Author: Darren Tucker Date: Thu Aug 3 19:35:33 2023 +1000 Fix RNG seeding for OpenSSL w/out self seeding. When sshd is built with an OpenSSL that does not self-seed, it would fail in the preauth privsep process while handling a new connection. Sanity checked by djm@ commit f70010d9b0b3e7e95de8aa0b961e1d74362cfb5d Author: djm@openbsd.org Date: Wed Aug 2 23:04:38 2023 +0000 upstream: CheckHostIP has defaulted to 'no' for a while; make the commented- out config option match. From Ed Maste OpenBSD-Commit-ID: e66e934c45a9077cb1d51fc4f8d3df4505db58d9 commit c88a8788f9865d02b986d00405b9f0be65ad0b5a Author: dtucker@openbsd.org Date: Tue Aug 1 08:15:04 2023 +0000 upstream: remove unnecessary if statement. github PR#422 from eyalasulin999, ok djm@ OpenBSD-Commit-ID: 2b6b0dde4407e039f58f86c8d2ff584a8205ea55 commit 77b8b865cd5a8c79a47605c0c5b2bacf4692c4d5 Author: jmc@openbsd.org Date: Fri Jul 28 05:42:36 2023 +0000 upstream: %C is a callable macro in mdoc(7) so, as we do for %D, escape it; OpenBSD-Commit-ID: 538cfcddbbb59dc3a8739604319491dcb8e0c0c9 commit e0f91aa9c2fbfc951e9ced7e1305455fc614d3f2 Author: djm@openbsd.org Date: Fri Jul 28 05:33:15 2023 +0000 upstream: don't need to start a command here; use ssh -N instead. Fixes failure on cygwin spotted by Darren OpenBSD-Regress-ID: ff678a8cc69160a3b862733d935ec4a383f93cfb commit f446a44f30bc680e0d026a4204844b02646c1c2d Author: djm@openbsd.org Date: Wed May 17 05:52:01 2023 +0000 upstream: add LTESTS_FROM variable to allow skipping of tests up to a specific point. e.g. "make LTESTS_FROM=t-sftp" will only run the sftp.sh test and subsequent ones. ok dtucker@ OpenBSD-Regress-ID: 07f653de731def074b29293db946042706fcead3 commit 8eb8899d612440a9b608bee7f916081d3d0b7812 Author: djm@openbsd.org Date: Fri May 12 06:37:42 2023 +0000 upstream: test ChrootDirectory in Match block OpenBSD-Regress-ID: a6150262f39065939f025e546af2a346ffe674c1 commit e43f43d3f19516222e9a143468ea0dc1b3ab67b6 Author: djm@openbsd.org Date: Fri May 12 06:36:27 2023 +0000 upstream: better error messages OpenBSD-Regress-ID: 55e4186604e80259496d841e690ea2090981bc7a commit 6958f00acf3b9e0b3730f7287e69996bcf3ceda4 Author: djm@openbsd.org Date: Thu Jul 27 22:26:49 2023 +0000 upstream: don't incorrectly truncate logged strings retrieved from PKCS#11 modules; based on GHPR406 by Jakub Jelen; ok markus OpenBSD-Commit-ID: 7ed1082f23a13b38c373008f856fd301d50012f9 commit d1ffde6b55170cd4b9a72bfd9a3f17508e6cf714 Author: djm@openbsd.org Date: Thu Jul 27 22:25:17 2023 +0000 upstream: make sshd_config AuthorizedPrincipalsCommand and AuthorizedKeysCommand accept the %D (routing domain) and a new %C (connection address/port 4-tuple) as expansion sequences; ok markus OpenBSD-Commit-ID: ee9a48bf1a74c4ace71b69de69cfdaa2a7388565 commit 999a2886ca1844a7a74b905e5f2c8c701f9838cd Author: djm@openbsd.org Date: Thu Jul 27 22:23:05 2023 +0000 upstream: increase default KDF work-factor for OpenSSH format private keys from 16 to 24; { feedback ok } x { deraadt markus } OpenBSD-Commit-ID: a3afb1383f8ff0a49613d449f02395d9e8d4a9ec commit 0fa803a1dd1c7b546c166000e23a869cf6c4ec10 Author: Darren Tucker Date: Thu Jul 27 02:25:09 2023 +1000 Prefer OpenSSL's SHA256 in sk-dummy.so Previously sk-dummy.so used libc's (or compat's) SHA256 since it may be built without OpenSSL. In many cases, however, including both libc's and OpenSSL's headers together caused conflicting definitions. We tried working around this (on OpenSSL <1.1 you could define OPENSSL_NO_SHA, NetBSD had USE_LIBC_SHA2, various #define hacks) with varying levels of success. Since OpenSSL >=1.1 removed OPENSSL_NO_SHA and including most OpenSSL headers would bring sha.h in, even if it wasn't used directly this was a constant hassle. Admit defeat and use OpenSSL's SHA256 unless we aren't using OpenSSL at all. ok djm@ commit 36cdb5dbf55c99c0faad06066f56a7c341258c1f Author: Darren Tucker Date: Thu Jul 27 10:29:44 2023 +1000 Retire dfly58 test VM. Add dfly64. commit 2d34205dab08ede9b0676efa57647fc49e6decbe Author: djm@openbsd.org Date: Wed Jul 26 23:06:00 2023 +0000 upstream: make ssh -f (fork after authentication) work properly in multiplexed cases (inc. ControlPersist). bz3589 bz3589 Based on patches by Peter Chubb; ok dtucker@ OpenBSD-Commit-ID: a7a2976a54b93e6767dc846b85647e6ec26969ac commit 076aeda86a7ee9be8fd2f0181ec7b9729a6ceb37 Author: naddy@openbsd.org Date: Sun Jul 23 20:04:45 2023 +0000 upstream: man page typos; ok jmc@ OpenBSD-Commit-ID: e6ddfef94b0eb867ad88abe07cedc8ed581c07f0 commit 135e7d5fe31f700e6dfc61ce914970c5ee7175ba Author: jmc@openbsd.org Date: Thu Jul 20 05:43:39 2023 +0000 upstream: tweak the allow-remote-pkcs11 text; OpenBSD-Commit-ID: bc965460a89edf76865b7279b45cf9cbdebd558a commit 5f83342b61d1f76c141de608ed2bd293990416bd Author: Darren Tucker Date: Tue Jul 25 13:00:22 2023 +1000 Handle a couple more OpenSSL no-ecc cases. ok djm@ commit edc2ef4e418e514c99701451fae4428ec04ce538 Author: Damien Miller Date: Thu Jul 20 12:53:44 2023 +1000 depend commit 51fda734e0d3c2df256fc03e8b060c4305be6e59 Author: Damien Miller Date: Thu Jul 20 12:53:21 2023 +1000 Bring back OPENSSL_HAS_ECC to ssh-pkcs11-client commit 099cdf59ce1e72f55d421c8445bf6321b3004755 Author: djm@openbsd.org Date: Wed Jul 19 14:03:45 2023 +0000 upstream: Separate ssh-pkcs11-helpers for each p11 module Make ssh-pkcs11-client start an independent helper for each provider, providing better isolation between modules and reliability if a single module misbehaves. This also implements reference counting of PKCS#11-hosted keys, allowing ssh-pkcs11-helper subprocesses to be automatically reaped when no remaining keys reference them. This fixes some bugs we have that make PKCS11 keys unusable after they have been deleted, e.g. https://bugzilla.mindrot.org/show_bug.cgi?id=3125 ok markus@ OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e commit 29ef8a04866ca14688d5b7fed7b8b9deab851f77 Author: djm@openbsd.org Date: Wed Jul 19 14:02:27 2023 +0000 upstream: Ensure FIDO/PKCS11 libraries contain expected symbols This checks via nlist(3) that candidate provider libraries contain one of the symbols that we will require prior to dlopen(), which can cause a number of side effects, including execution of constructors. Feedback deraadt; ok markus OpenBSD-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe commit 1f2731f5d7a8f8a8385c6031667ed29072c0d92a Author: djm@openbsd.org Date: Wed Jul 19 13:56:33 2023 +0000 upstream: Disallow remote addition of FIDO/PKCS11 provider libraries to ssh-agent by default. The old behaviour of allowing remote clients from loading providers can be restored using `ssh-agent -O allow-remote-pkcs11`. Detection of local/remote clients requires a ssh(1) that supports the `session-bind@openssh.com` extension. Forwarding access to a ssh-agent socket using non-OpenSSH tools may circumvent this control. ok markus@ OpenBSD-Commit-ID: 4c2bdf79b214ae7e60cc8c39a45501344fa7bd7c commit 892506b13654301f69f9545f48213fc210e5c5cc Author: djm@openbsd.org Date: Wed Jul 19 13:55:53 2023 +0000 upstream: terminate process if requested to load a PKCS#11 provider that isn't a PKCS#11 provider; from / ok markus@ OpenBSD-Commit-ID: 39532cf18b115881bb4cfaee32084497aadfa05c commit f3f56df8ec476b2de6cbdbdfdb77a2a61087829d Author: Damien Miller Date: Wed Jul 19 12:07:18 2023 +1000 agent_fuzz doesn't want stdint.h conditionalised commit 750911fd31d307a767cc86e3bfa90bbbb77b1a25 Author: Damien Miller Date: Tue Jul 18 15:41:12 2023 +1000 conditionalise stdint.h inclusion on HAVE_STDINT_H fixes build on AIX5 at least commit ff047504fa6e008c4092f8929881816b8993bea0 Author: Damien Miller Date: Tue Jul 18 15:30:45 2023 +1000 conditionalise match localnetwork on ifaddrs.h Fixes build breakage on platforms that lack getifaddrs() commit b87b03282e466ca2927954ce93f5dbf0bfdc68f6 Author: djm@openbsd.org Date: Mon Jul 17 06:16:33 2023 +0000 upstream: missing match localnetwork negation check OpenBSD-Commit-ID: 9a08ed8dae27d3f38cf280f1b28d4e0ff41a737a commit 6d6e185ba29ef4274164b77eab4dc763907f8821 Author: jmc@openbsd.org Date: Mon Jul 17 05:41:53 2023 +0000 upstream: - add -P to usage() - sync the arg name to -J in usage() with that in ssh.1 - reformat usage() to match what "man ssh" does on 80width OpenBSD-Commit-ID: 5235dd7aa42e5bf90ae54579d519f92fc107036e commit f1a9898283a0638667b587ee4a950afd61ab51b0 Author: jmc@openbsd.org Date: Mon Jul 17 05:38:10 2023 +0000 upstream: -P before -p in SYNOPSIS; OpenBSD-Commit-ID: 535f5257c779e26c6a662a038d241b017f8cab7c commit eef4d7e873568e1c84c36bb4034e2c3378250a61 Author: jsg@openbsd.org Date: Mon Jul 17 05:36:14 2023 +0000 upstream: configuation -> configuration OpenBSD-Commit-ID: 4776ced33b780f1db0b2902faec99312f26a726b commit dc1dbe94cf6532bd546a3373ad436404f8850e5f Author: djm@openbsd.org Date: Mon Jul 17 05:26:38 2023 +0000 upstream: move other RCSIDs to before their respective license blocks too no code change OpenBSD-Commit-ID: ef5bf46b57726e4260a63b032b0b5ac3b4fe9cd4 commit ebe11044681caff78834ca6b78311ad19c1860b8 Author: djm@openbsd.org Date: Mon Jul 17 05:22:30 2023 +0000 upstream: Move RCSID to before license block and away from #includes, where it caused merge conflict in -portable for each commit :( OpenBSD-Commit-ID: 756ebac963df3245258b962e88150ebab9d5fc20 commit 05c08e5f628de3ecf6f7ea20947735bcfa3201e0 Author: djm@openbsd.org Date: Mon Jul 17 05:20:15 2023 +0000 upstream: return SSH_ERR_KRL_BAD_MAGIC when a KRL doesn't contain a valid magic number and not SSH_ERR_MESSAGE_INCOMPLETE; the former is needed to fall back to text revocation lists in some cases; fixes t-cert-hostkey. OpenBSD-Commit-ID: 5c670a6c0f027e99b7774ef29f18ba088549c7e1 commit c6fad2c3d19b74f0bd0af1ef040fc74f3a1d9ebb Author: Damien Miller Date: Mon Jul 17 14:56:14 2023 +1000 avoid AF_LINK on platforms that don't define it commit 919bc3d3b712c920de1ae6be5ac6561c98886d7e Author: djm@openbsd.org Date: Mon Jul 17 04:08:31 2023 +0000 upstream: Add support for configuration tags to ssh(1). This adds a ssh_config(5) "Tag" directive and corresponding "Match tag" predicate that may be used to select blocks of configuration similar to the pf.conf(5) keywords of the same name. ok markus OpenBSD-Commit-ID: dc08358e70e702b59ac3e591827e5a96141b06a3 commit 3071d85a47061c1bdaf11a0ac233b501ecba862c Author: djm@openbsd.org Date: Mon Jul 17 04:04:36 2023 +0000 upstream: add a "match localnetwork" predicate. This allows matching on the addresses of available network interfaces and may be used to vary the effective client configuration based on network location (e.g. to use a ProxyJump when not on a particular network). ok markus@ OpenBSD-Commit-ID: cffb6ff9a3803abfc52b5cad0aa190c5e424c139 commit beec17bb311365b75a0a5941418d4b96df7d7888 Author: djm@openbsd.org Date: Mon Jul 17 04:01:10 2023 +0000 upstream: remove vestigal support for KRL signatures When the KRL format was originally defined, it included support for signing of KRL objects. However, the code to sign KRLs and verify KRL signatues was never completed in OpenSSH. Now, some years later, we have SSHSIG support in ssh-keygen that is more general, well tested and actually works. So this removes the semi-finished KRL signing/verification support from OpenSSH and refactors the remaining code to realise the benefit - primarily, we no longer need to perform multiple parsing passes over KRL objects. ok markus@ OpenBSD-Commit-ID: 517437bab3d8180f695c775410c052340e038804 commit 449566f64c21b4578d5c0c431badd0328adc53ed Author: djm@openbsd.org Date: Mon Jul 17 03:57:21 2023 +0000 upstream: Support for KRL extensions. This defines wire formats for optional KRL extensions and implements parsing of the new submessages. No actual extensions are supported at this point. ok markus OpenBSD-Commit-ID: ae2fcde9a22a9ba7f765bd4f36b3f5901d8c3fa7 commit 18ea857770e84825a3a6238bb37f54864487b59f Author: dtucker@openbsd.org Date: Fri Jul 14 07:44:21 2023 +0000 upstream: Include stdint.h for SIZE_MAX. Fixes OPENSSL=no build. OpenBSD-Commit-ID: e7c31034a5434f2ead3579b13a7892960651e6b0 commit 20b768fcd13effe0f2d3619661b6c8592c773553 Author: Darren Tucker Date: Fri Jul 14 17:07:32 2023 +1000 Fix typo in declaration of nmesg. commit 4b94d09542e36ebde2eb9ad89bc68431609932de Author: Damien Miller Date: Fri Jul 14 15:34:47 2023 +1000 portable-specific int overflow defence-in-depth These too are unreachable, but we want the code to be safe regardless of context. Reported by Yair Mizrahi @ JFrog commit 2ee48adb9fc8692e8d6ac679dcc9f35e89ad68f0 Author: djm@openbsd.org Date: Fri Jul 14 05:31:44 2023 +0000 upstream: add defence-in-depth checks for some unreachable integer overflows reported by Yair Mizrahi @ JFrog; feedback/ok millert@ OpenBSD-Commit-ID: 52af085f4e7ef9f9d8423d8c1840a6a88bda90bd commit 4b43bc358ae6f6b19a973679246dc5172f6ac41b Author: djm@openbsd.org Date: Mon Jul 10 04:51:26 2023 +0000 upstream: misplaced debug message OpenBSD-Commit-ID: d0f12af0a5067a756aa707bc39a83fa6f58bf7e5 commit 8c7203bcee4c4f98a22487b4631fe068b992099b Author: Damien Miller Date: Wed Jul 12 11:41:19 2023 +1000 replace deprecate selinux matchpathcon function This function is apparently deprecated. Documentation on what is the supposed replacement is is non-existent, so this follows the approach glibc used https://sourceware.org/git/?p=glibc.git;a=patch;h=f278835f59 ok dtucker@ commit 7e8800f5d701efffa39ccb63ca1e095ea777c31a Author: dtucker@openbsd.org Date: Thu Jul 6 22:17:59 2023 +0000 upstream: minleft and maxsign are u_int so cast appropriately. Prompted by github PR#410, ok deraadt. OpenBSD-Commit-ID: 0514cd51db3ec60239966622a0d3495b15406ddd commit 94842bfe9b09fc93189c6ed0dc9bbebc1d44a426 Author: dlg@openbsd.org Date: Tue Jul 4 03:59:21 2023 +0000 upstream: add support for unix domain sockets to ssh -W ok djm@ dtucker@ OpenBSD-Commit-ID: 3e6d47567b895c7c28855c7bd614e106c987a6d8 commit a95fc5eed09a0238fb127b6c50e8498432b79dae Author: David Seifert Date: Fri May 12 14:06:01 2023 +0200 gss-serv.c: `MAXHOSTNAMELEN` -> `HOST_NAME_MAX` `MAXHOSTNAMELEN` is not defined in POSIX, which breaks on musl: https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html Bug: https://bugs.gentoo.org/834044 commit 8a6cd08850f576e7527c52a1b086cae82fab290e Author: Darren Tucker Date: Fri Jun 23 09:49:02 2023 +1000 Update runner OS version for hardenedmalloc test. Hardenedmalloc dropped support for "legacy glibc" versions in their 64dad0a69 so use a newer Ubuntu version for the runner for that test. commit cfca6f17e64baed6822bb927ed9f372ce64d9c5b Author: Damien Miller Date: Thu Jun 22 15:04:03 2023 +1000 handle sysconf(SC_OPEN_MAX) returning > INT_MAX; bz3581; ok dtucker commit c1c2ca1365b3f7b626683690bd2c68265f6d8ffd Author: djm@openbsd.org Date: Wed Jun 21 05:10:26 2023 +0000 upstream: better validate CASignatureAlgorithms in ssh_config and sshd_config. Previously this directive would accept certificate algorithm names, but these were unusable in practice as OpenSSH does not support CA chains. part of bz3577; ok dtucker@ OpenBSD-Commit-ID: a992d410c8a78ec982701bc3f91043dbdb359912 commit 4e73cd0f4ab3e5b576c56cac9732da62c8fc0565 Author: djm@openbsd.org Date: Wed Jun 21 05:08:32 2023 +0000 upstream: make `ssh -Q CASignatureAlgorithms` only list signature algorithms that are valid for CA signing. Previous behaviour was to list all signing algorithms, including certificate algorithms (OpenSSH certificates do not support CA chains). part of bz3577; ok dtucker@ OpenBSD-Commit-ID: 99c2b072dbac0f44fd1f2269e3ff6c1b5d7d3e59 commit a69062f1695ac9c3c3dea29d3044c72aaa6af0ea Author: djm@openbsd.org Date: Wed Jun 21 05:06:04 2023 +0000 upstream: handle rlimits > INT_MAX (rlim_t is u64); ok dtucker bz3581 OpenBSD-Commit-ID: 31cf59c041becc0e5ccb0a77106f812c4cd1cd74 commit 8d33f2aa6bb895a7f85a47189913639086347b75 Author: djm@openbsd.org Date: Tue Jun 20 23:59:33 2023 +0000 upstream: prepare for support for connecting to unix domain sockets using ssh -W by explicitly decoding PORT_STREAMLOCAL (a negative number) from the u32 that's passed over the multiplexing socket; previously code would just cast, which is UB. OpenBSD-Commit-ID: e5ac5f40d354096c51e8c118a5c1b2d2b7a31384 commit b4ac435b4e67f8eb5932d8f59eb5b3cf7dc38df0 Author: djm@openbsd.org Date: Tue Jun 20 00:05:09 2023 +0000 upstream: reset comment=NULL for each key in do_fingerprint(); fixes "no comment" not showing on when running `ssh-keygen -l` on multiple keys where one has a comment and other following keys do not. Patch from Markus Kuhn via GHPR407, bz3580 OpenBSD-Commit-ID: 3cce84456fdcd67dc6b84e369f92c6686d111d9b commit b53a809a549dcd4fbde554c6aa283e597b15ea33 Author: millert@openbsd.org Date: Mon Jun 5 13:24:36 2023 +0000 upstream: Store timeouts as int, not u_int as they are limited to INT_MAX. Fixes sign compare warnings systems with 32-bit time_t due to type promotion. OK djm@ OpenBSD-Commit-ID: 48081e9ad35705c5f1705711704a4c2ff94e87b7 commit 2709809fd616a0991dc18e3a58dea10fb383c3f0 Author: Philip Hands Date: Wed May 24 19:41:14 2023 +0200 fixup! if -s & -p specified, mention 'sftp -P' on success SSH-Copy-ID-Upstream: 32686e7c65b4fa2846e474d3315102dfa0f043b0 commit 204e0bf05161b7641500d7ab266c21217412379f Author: Darren Tucker Date: Tue Aug 3 21:25:48 2021 +1000 Make ssh-copy-id(1) consistent with OpenSSH. This makes the ssh-copy-id man page more consistent with the rest of the OpenSSH man pages: - new sentence, new line - no sentences >80 - N.B. -> NB - zap unused .Pp - zap trailing whitespace Report from Debian via mindrot bz#3331, diff from jmc at openbsd.org. SSH-Copy-ID-Upstream: d8974cfb6242316460ed22a1ccc662800a50c5d3 commit 9de79df66d1430d290fab670bb4b18612875e518 Author: Philip Hands Date: Wed May 24 11:45:43 2023 +0200 if -s & -p specified, mention 'sftp -P' on success This was inspired by this: https://github.com/openssh/openssh-portable/pull/321 but I thought that it was better to not do the sed patching. BTW the reason one can get away with using $SSH_OPTS throughout, despite the lowercase -p in there, even if sftp is in use, is that the sftp call is using the already-established ssh master connection, so the port was passed to the earlier ssh. SSH-Copy-ID-Upstream: 1c124d9bfafdbe28a00b683367ebf5750ce12eb2 commit 801cda54c00e0f4e7d89345a90874c8d05dc233a Author: Philip Hands Date: Tue May 23 23:07:11 2023 +0200 drop whitespace SSH-Copy-ID-Upstream: e604fae1cdee35c18055d35dcec530cf12ef00ad commit 288482f53613f3e74544eb92deeb24f7c7f1f371 Author: Philip Hands Date: Tue May 23 20:52:13 2023 +0200 make -x also apply to the target script SSH-Copy-ID-Upstream: 3c4214704f427bd0654adf9b0fc079253db21cf4 commit b79e7b88ed44f0e4339f0ff35c96c78a92175a8d Author: Philip Hands Date: Tue May 23 16:46:42 2023 +0200 add -t option to specify the target path Allow the default target path (.ssh/authorized_files) to be over-riden This was inspired by this MR from Panagiotis Cheilaris https://gitlab.com/phil_hands/ssh-copy-id/-/merge_requests/8 SSH-Copy-ID-Upstream: a942a0e076874adb6d8b2f0fb76d6c7918190fcd commit 914f4ad138714c471ba72fb6d5496b6235320edd Author: Carlos Rodríguez Gili Date: Tue Apr 20 19:23:57 2021 +0200 Fix test error for /bin/sh on Solaris 10 and older On Solaris 10 and older targets /bin/sh is not POSIX-compliant. Test -z `...` fails with error 'sh: test: argument expected'. Using quotes around backticks fixes this and doesn't break POSIX compatibility. SSH-Copy-ID-Upstream: 98394072a3f985b2650c1e8eab2fef84e38cc065 commit bd382dca316c721aed1e45edcf4c4e0f6374afb0 Author: Jakub Jelen Date: Tue Mar 2 21:34:05 2021 +0000 Remove outdated comment The commit b068122 removed the code dropping the trailing colon, but the comment stayed leaving the code confusing for future readers SSH-Copy-ID-Upstream: 930d39f238117cd53810240ec989d0356aa1c1f6 commit bdcaf7939029433635d63aade8f9ac762aca2bbe Author: Darren Tucker Date: Wed May 10 18:50:46 2023 +1000 Special case OpenWrt instead of Dropbear. OpenWrt overrides the location of authorized_keys for root. Currently we assume that all Dropbear installations behave this way, which is not the case. Check for OpenWrt and root user before using that location instead of assuming that for all Dropbear servers. Prompted by Github PR#250. SSH-Copy-ID-Upstream: 0e1f5d443a9967483c33945793107ae3f3e4af2d commit cf84498f67abe93f813a296167b406a0db7b288e Author: Philip Hands Date: Thu May 18 18:20:55 2023 +0200 ssh-copy-id: add -x option (for debugging) This option causes the ssh-copy-id to run with set -x SSH-Copy-ID-Upstream: a0ee367ea8c0a29c8b4515245e408d2d349e7844 commit b4a1efdcb88f03394c08e7f68ed4e11676830002 Author: Philip Hands Date: Thu May 18 17:14:41 2023 +0200 update copyright notices SSH-Copy-ID-Upstream: c284ed33b361814ea48ff68cbd01ca525b2bf117 commit fcd78e31cdd45a7e69ccfe6d8a3b1037dc1de290 Author: djm@openbsd.org Date: Wed May 24 23:01:06 2023 +0000 upstream: fix AuthorizedPrincipalsCommand when AuthorizedKeysCommand appears previously in configuration. Reported by John Meyers in bz3574 ok dtucker@ OpenBSD-Commit-ID: 1c92e4517284386703936e1d3abaa36cfacf1951 commit 5ec5504f1d328d5bfa64280cd617c3efec4f78f3 Author: dtucker@openbsd.org Date: Wed May 10 10:04:20 2023 +0000 upstream: Remove unused prototypes for ssh1 RSA functions. From lengyijun via github PR#396. OpenBSD-Commit-ID: 379a5afa8b7a0f3cba0c8a9bcceb4e5e33a5c1ef commit fbf362b3891ae4b36052d1b39f37fc618b41c476 Author: Darren Tucker Date: Tue May 9 19:26:56 2023 +1000 main(void) to prevent unused variable warning. commit baf854c8bb0a6d0af5c696c801e631a48dabbaba Author: Darren Tucker Date: Tue May 9 19:25:45 2023 +1000 Remove warning pragma since clang doesn't like it. commit 5fbb7a1349fbbb48ccb1b8cafff2c1854370d87d Author: Darren Tucker Date: Tue May 9 17:13:33 2023 +1000 Suppress warning for snprintf truncation test. commit 47742c513e4e045ecc985c6483fc5c8b050acda2 Author: Darren Tucker Date: Tue May 9 17:12:50 2023 +1000 Update OpenSSL compat test for 3.x. commit 86ad25d455a2313126125540e61e0f9314283f88 Author: Darren Tucker Date: Mon May 8 20:23:08 2023 +1000 Add macos13 PAM test target. commit 77cca2c4b13bc6e5f389565583b6202b0d1bccc2 Author: Darren Tucker Date: Mon May 8 20:14:46 2023 +1000 Skip agent-peereid test on macos13. sudo -S nobody doesn't work on the github runners (probably a permission issue) so skip that test. commit b356b8e91678ea295bcf44df5248c3fbf499fdcf Author: Darren Tucker Date: Mon May 8 20:14:28 2023 +1000 Include config.guess in debug output. commit b7afd8a4ecaca8afd3179b55e9db79c0ff210237 Author: Darren Tucker Date: Mon May 8 20:12:59 2023 +1000 Handle OpenSSL >=3 ABI compatibility. Beyond OpenSSL 3.0, the ABI compatibility guarantees are wider (only major must match instead of major and minor in earlier versions). bz#3548, ok djm@ commit 0e9e2663eb2c6e9c3e10d15d70418312ae67e542 Author: dtucker@openbsd.org Date: Mon May 1 08:57:29 2023 +0000 upstream: Import regenerated moduli. OpenBSD-Commit-ID: 3d5f811cfcaed8cc4a97e1db49ac61bdf118113c commit d9687f49682e1e93383fc15ab2018850b2ef38c3 Author: Darren Tucker Date: Mon May 1 11:45:14 2023 +1000 Add macos-13 test target. Also flatten OS list for clarity. commit aacfd6767497b8fa6d41ecdd3f8e265d1e9ef1f6 Author: djm@openbsd.org Date: Sun Apr 30 22:54:22 2023 +0000 upstream: adjust ftruncate() logic to handle servers that reorder requests. sftp/scp will ftruncate the destination file after a transfer completes, to deal with the case where a longer destination file already existed. We tracked the highest contiguous block transferred to deal with this case, but our naive tracking doesn't deal with servers that reorder requests - a misfeature strictly permitted by the protocol but seldom implemented. Adjust the logic to ftruncate() at the highest absolute block received when the transfer is successful. feedback deraadt@ ok markus@ prompted by https://github.com/openssh/openssh-portable/commit/9b733#commitcomment-110679778 OpenBSD-Commit-ID: 4af7fac75958ad8507b4fea58706f3ff0cfddb1b commit c8eb3941758615c8284a48fff47872db926da63c Author: djm@openbsd.org Date: Wed Apr 26 01:36:03 2023 +0000 upstream: Check for ProxyJump=none in CanonicalizeHostname logic. Previously ssh would incorrectly refuse to canonicalise the hostname if ProxyJump was explicitly set to "none" when CanonicalizeHostname=yes bz3567; ok dtucker OpenBSD-Commit-ID: 80a58e43c3a32f97361282f756ec8d3f37989efd commit ac383f3a5c6f529a2e8a5bc44af79a08c7da294e Author: jsg@openbsd.org Date: Wed Apr 12 14:22:04 2023 +0000 upstream: remove duplicate signal.h include OpenBSD-Commit-ID: 30c0a34d74d91ddd0e6992525da70d3293392f70 commit 740dafa20f3f3d325f6f5d44e990b8c8a6d3d816 Author: jsg@openbsd.org Date: Wed Apr 12 08:53:54 2023 +0000 upstream: fix double words ok dtucker@ OpenBSD-Commit-ID: 44d3223902fbce5276422bdc8063ab72a4078489 commit 6452f89577ec4f22440c31b8e19b061d1a7c4b2a Author: Darren Tucker Date: Tue Apr 11 16:49:19 2023 +1000 Test against LibreSSL 3.7.2. openssh-10.0p1/PaxHeaders.10889/INSTALL100644 001750 001750 0000000003514775415623 0014204xustar0029 atime=1744182234.46076586 openssh-10.0p1/INSTALL010064400017500001750000000234341477541562300125760ustar00djmdjm1. Prerequisites ---------------- A C compiler. Any C89 or better compiler that supports variadic macros 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) 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): https://zlib.net/ 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/) 3.1.0 or greater - OpenSSL (https://www.openssl.org) 1.1.1 or greater LibreSSL/OpenSSL should be compiled as a position-independent library (i.e. -fPIC, eg by configuring OpenSSL as "./config [options] -fPIC" or LibreSSL as "CFLAGS=-fPIC ./configure") otherwise OpenSSH will not be able to link with it. If you must use a non-position-independent libcrypto, then you may need to configure OpenSSH --without-pie. If you build either from source, running the OpenSSL self-test ("make tests") or the LibreSSL equivalent ("make check") and ensuring that all tests pass is strongly recommended. NB. If you operating system supports /dev/random, you should configure libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's direct support of /dev/random, or failing that, either prngd or egd. PRNGD: If your system lacks kernel-based random collection, the use of Lutz Jaenicke's PRNGd is recommended. If you are using libcrypto it requires that the libcrypto is configured to support it. If you are building --without-openssl then the --with-prngd-socket option must match the socket provided by prngd. http://prngd.sourceforge.net/ EGD: The Entropy Gathering Daemon (EGD) supports the same interface as prngd. The same caveats about configuration for prngd also apply. http://egd.sourceforge.net/ 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, NetBSD and Mac OS X. Information about the various PAM implementations are available: Solaris PAM: http://www.sun.com/software/solaris/pam/ Linux PAM: http://www.kernel.org/pub/linux/libs/pam/ OpenPAM: http://www.openpam.org/ If you wish to build the GNOME passphrase requester, you will need the GNOME libraries and headers. GNOME: http://www.gnome.org/ Alternatively, Jim Knoble has written an excellent X11 passphrase requester. This is maintained separately at: http://www.jmknoble.net/software/x11-ssh-askpass/ LibEdit: sftp supports command-line editing via NetBSD's libedit. If your platform has it available natively you can use that, alternatively you might try these multi-platform ports: http://www.thrysoee.dk/editline/ http://sourceforge.net/projects/libedit/ LDNS: LDNS is a DNS BSD-licensed resolver library which supports DNSSEC. http://nlnetlabs.nl/projects/ldns/ Autoconf: If you modify configure.ac or configure doesn't exist (eg if you checked the main git branch) then you will need autoconf-2.69 and automake-1.16.1 or newer to rebuild the automatically generated files by running "autoreconf". Earlier versions may also work but this is not guaranteed. http://www.gnu.org/software/autoconf/ http://www.gnu.org/software/automake/ Basic Security Module (BSM): 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. libfido2 >= 1.5.0 is strongly recommended. Limited functionality is possible with earlier libfido2 versions. https://github.com/Yubico/libfido2 https://github.com/pjk/libcbor 2. Building / Installation -------------------------- To install OpenSSH with default options: ./configure make make install This will install the OpenSSH binaries in /usr/local/bin, configuration files in /usr/local/etc, the server in /usr/local/sbin, etc. To specify a different installation prefix, use the --prefix option to configure: ./configure --prefix=/opt make make install Will install OpenSSH in /opt/{bin,etc,lib,sbin}. You can also override specific paths, for example: ./configure --prefix=/opt --sysconfdir=/etc/ssh make 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 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, which is the basename of the path of your sshd (e.g., the service name for /usr/sbin/osshd will be osshd). If you have renamed your sshd executable, your PAM configuration may need to be modified. A generic PAM configuration is included as "contrib/sshd.pam.generic", you may need to edit it before using it on your system. If you are using a recent version of Red Hat Linux, the config file in contrib/redhat/sshd.pam should be more useful. Failure to install a valid PAM file may result in an inability to use password authentication. On HP-UX 11 and Solaris, the standard /etc/pam.conf configuration will work with sshd (sshd will match the other service name). There are a few other options to the configure script: --with-audit=[module] enable additional auditing via the specified module. Currently, drivers for "debug" (additional info via syslog) and "bsm" (Sun's Basic Security Module) are supported. --with-pam enables PAM support. If PAM support is compiled in, it must 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. --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. --with-lastlog=FILE will specify the location of the lastlog file. ./configure searches a few locations for lastlog, but may not find it if lastlog is installed in a different place. --without-lastlog will disable lastlog support entirely. --with-osfsia, --without-osfsia will enable or disable OSF1's Security Integration Architecture. The default for OSF1 machines is enable. --with-utmpx enables utmpx support. utmpx support is automatic for some platforms. --without-shadow disables shadow password support. --with-ipaddr-display forces the use of a numeric IP address in the $DISPLAY environment variable. Some broken systems need this. --with-default-path=PATH allows you to specify a default $PATH for sessions started by sshd. This replaces the standard path entirely. --with-pid-dir=PATH specifies the directory in which the sshd.pid file is 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. --with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support --without-openssl builds without using OpenSSL. Only a subset of ciphers and algorithms are supported in this configuration. --without-zlib builds without zlib. This disables the Compression option. --with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to real (AF_INET) IPv4 addresses. Works around some quirks on Linux. If you need to pass special options to the compiler or linker, you can specify these as environment variables before running ./configure. For example: CC="/usr/foo/cc" CFLAGS="-O" LDFLAGS="-s" LIBS="-lrubbish" ./configure 3. Configuration ---------------- The runtime configuration files are installed by in ${prefix}/etc or whatever you specified as your --sysconfdir (/usr/local/etc by default). The default configuration should be instantly usable, though you should 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 [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). If you have configured OpenSSH with EGD/prngd support, ensure that EGD or prngd is running and has collected some entropy first. For more information on configuration, please refer to the manual pages for sshd, ssh and ssh-agent. 4. (Optional) Send survey ------------------------- $ make survey [check the contents of the file "survey" to ensure there's no information that you consider sensitive] $ make send-survey This will send configuration information for the currently configured host to a survey address. This will help determine which configurations are actually in use, and what valid combinations of configure options exist. The raw data is available only to the OpenSSH developers, however 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 https://www.openssh.com/ openssh-10.0p1/PaxHeaders.10889/LICENCE100644 001750 001750 0000000003614775415623 0014141xustar0030 atime=1744182234.461742687 openssh-10.0p1/LICENCE010064400017500001750000000512241477541562300125300ustar00djmdjmThis file is part of the OpenSSH software. The licences which components of this software fall under are as follows. First, we will summarize and say that all components are under a BSD licence, or a licence more free than that. OpenSSH contains no GPL code. 1) * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". [Tatu continues] * However, I am not implying to give any licenses to any patents or * copyrights held by third parties, and the software includes parts that * are not under my direct control. As far as I know, all included * source code is used in accordance with the relevant license agreements * and can be used freely for any purpose (the GNU license being the most * restrictive); see below for details. [However, none of that term is relevant at this point in time. All of these restrictively licenced software components which he talks about have been removed from OpenSSH, i.e., - RSA is no longer included, found in the OpenSSL library - IDEA is no longer included, its use is deprecated - DES is now external, in the OpenSSL library - GMP is no longer used, and instead we call BN code from OpenSSL - Zlib is now external, in a library - The make-ssh-known-hosts script is no longer included - TSS has been removed - MD5 is now external, in the OpenSSL library - RC4 support has been replaced with ARC4 support from OpenSSL - Blowfish is now external, in the OpenSSL library [The licence continues] Note that any information and cryptographic algorithms used in this software are publicly available on the Internet and at any major bookstore, scientific library, and patent office worldwide. More information can be found e.g. at "http://www.cs.hut.fi/crypto". The legal status of this program is some combination of all these permissions and restrictions. Use only at your own responsibility. You will be responsible for any legal consequences yourself; I am not making any claims whether possessing or using this is legal or not in your country, and I am not taking any responsibility on your behalf. NO WARRANTY BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 3) ssh-keyscan was contributed by David Mazieres under a BSD-style license. * Copyright 1995, 1996 by David Mazieres . * * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the * OpenBSD project by leaving this copyright notice intact. 4) The Rijndael implementation by Vincent Rijmen, Antoon Bosselaers and Paulo Barreto is in the public domain and distributed with the following license: * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. 5) One component of the ssh source code is under a 3-clause BSD license, held by the University of California, since we pulled these parts from original Berkeley code. * Copyright (c) 1983, 1990, 1992, 1993, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. 6) Remaining components of the software are provided under a standard 2-term BSD licence with the following names as copyright holders: Markus Friedl Theo de Raadt Niels Provos Dug Song Aaron Campbell Damien Miller Kevin Steves Daniel Kouril Wesley Griffin Per Allansson Nils Nordman Simon Wilkinson Portable OpenSSH additionally includes code from the following copyright holders, also under the 2-term BSD license: Ben Lindstrom Tim Rice Andre Lucas Chris Adams Corinna Vinschen Cray Inc. Denis Parker Gert Doering Jakob Schlyter Jason Downs Juha Yrjölä Michael Stone Networks Associates Technology, Inc. Solar Designer Todd C. Miller Wayne Schroeder William Jones Darren Tucker Sun Microsystems The SCO Group Daniel Walsh Red Hat, Inc Simon Vallet / Genoscope * 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. 8) Portable OpenSSH contains the following additional licenses: a) snprintf replacement * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell * (papowell@astart.com) It may be used for any purpose as long as this * notice remains intact on all source code distributions b) Compatibility code (openbsd-compat) Apart from the previously mentioned licenses, various pieces of code in the openbsd-compat/ subdirectory are licensed as follows: Some code is licensed under a 3-term BSD license, to the following copyright holders: Todd C. Miller Theo de Raadt Damien Miller Eric P. Allman The Regents of the University of California Constantin S. Svintsoff Kungliga Tekniska Högskolan * 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. Some code is licensed under an ISC-style license, to the following copyright holders: Internet Software Consortium. Todd C. Miller Reyk Floeter Chad Mynhier * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER 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. Some code is licensed under a MIT-style license to the following copyright holders: Free Software Foundation, Inc. * 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, distribute with modifications, 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 ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * * * Except as contained in this notice, the name(s) of the above copyright * * holders shall not be used in advertising or otherwise to promote the * * sale, use or other dealings in this Software without prior written * * authorization. * ****************************************************************************/ The Blowfish cipher implementation is licensed by Niels Provos under a 3-clause BSD license: * Blowfish - a fast block cipher designed by Bruce Schneier * * Copyright 1997 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Some replacement code is licensed by the NetBSD foundation under a 2-clause BSD license: * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Todd Vierling. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. The replacement base64 implementation has the following MIT-style licenses: * Copyright (c) 1996 by 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. * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. ------ $OpenBSD: LICENCE,v 1.20 2017/04/30 23:26:16 djm Exp $ openssh-10.0p1/PaxHeaders.10889/Makefile.in100644 001750 001750 0000000003614775415623 0015221xustar0030 atime=1744182234.461742687 openssh-10.0p1/Makefile.in010064400017500001750000000776741477541562300136310ustar00djmdjmSHELL=@SH@ AUTORECONF=autoreconf prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ sbindir=@sbindir@ libexecdir=@libexecdir@ datadir=@datadir@ datarootdir=@datarootdir@ mandir=@mandir@ mansubdir=@mansubdir@ sysconfdir=@sysconfdir@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ abs_top_srcdir=@abs_top_srcdir@ abs_top_builddir=@abs_top_builddir@ VPATH=@srcdir@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign SSHD_SESSION=$(libexecdir)/sshd-session SSHD_AUTH=$(libexecdir)/sshd-auth SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ STRIP_OPT=@STRIP_OPT@ TEST_SHELL=@TEST_SHELL@ BUILDDIR=@abs_top_builddir@ SK_STANDALONE=@SK_STANDALONE@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \ -D_PATH_SSHD_SESSION=\"$(SSHD_SESSION)\" \ -D_PATH_SSHD_AUTH=\"$(SSHD_AUTH)\" \ -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \ -D_PATH_SSH_SK_HELPER=\"$(SSH_SK_HELPER)\" \ -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ CFLAGS_NOPIE=@CFLAGS_NOPIE@ CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ PICFLAG=@PICFLAG@ LIBS=@LIBS@ CHANNELLIBS=@CHANNELLIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHDLIBS=@SSHDLIBS@ LIBEDIT=@LIBEDIT@ LIBFIDO2=@LIBFIDO2@ LIBWTMPDB=@LIBWTMPDB@ AR=@AR@ AWK=@AWK@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ SED=@SED@ XAUTH_PATH=@XAUTH_PATH@ LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@ EXEEXT=@EXEEXT@ MANFMT=@MANFMT@ MKDIR_P=@MKDIR_P@ .SUFFIXES: .lo TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) $(SK_STANDALONE) XMSS_OBJS=\ ssh-xmss.o \ sshkey-xmss.o \ xmss_commons.o \ xmss_fast.o \ xmss_hash.o \ xmss_hash_address.o \ xmss_wots.o LIBOPENSSH_OBJS=\ ssh_api.o \ ssherr.o \ sshbuf.o \ sshkey.o \ sshbuf-getput-basic.o \ sshbuf-misc.o \ sshbuf-getput-crypto.o \ krl.o \ bitmap.o \ ${XMSS_OBJS} LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ authfd.o authfile.o \ canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \ cleanup.o \ compat.o fatal.o hostfile.o \ log.o match.o moduli.o nchan.o packet.o \ readpass.o ttymodes.o xmalloc.o addr.o addrmatch.o \ atomicio.o dispatch.o mac.o misc.o utf8.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ ssh-ed25519-sk.o ssh-rsa.o dh.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ ssh-pkcs11.o smult_curve25519_ref.o \ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ ssh-ed25519.o digest-openssl.o digest-libc.o \ hmac.o ed25519.o hash.o \ kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ kexsntrup761x25519.o kexmlkem768x25519.o sntrup761.o kexgen.o \ sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ sshbuf-io.o SKOBJS= ssh-sk-client.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect2.o mux.o $(SKOBJS) SSHDOBJS=sshd.o \ platform-listen.o \ servconf.o sshpty.o srclimit.o groupaccess.o auth2-methods.o \ dns.o fatal.o compat.o utf8.o authfd.o canohost.o \ $(SKOBJS) SSHD_SESSION_OBJS=sshd-session.o auth-rhosts.o auth-passwd.o \ audit.o audit-bsm.o audit-linux.o platform.o \ sshpty.o sshlogin.o servconf.o serverloop.o \ auth.o auth2.o auth2-methods.o auth-options.o session.o \ auth2-chall.o groupaccess.o \ auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ monitor.o monitor_wrap.o auth-krb5.o \ auth2-gss.o gss-serv.o gss-serv-krb5.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ sftp-server.o sftp-common.o \ uidswap.o platform-listen.o $(SKOBJS) SSHD_AUTH_OBJS=sshd-auth.o \ auth2-methods.o \ auth-rhosts.o auth-passwd.o sshpty.o sshlogin.o servconf.o \ serverloop.o auth.o auth2.o auth-options.o session.o auth2-chall.o \ groupaccess.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ auth2-gss.o gss-serv.o gss-serv-krb5.o \ monitor_wrap.o auth-krb5.o \ audit.o audit-bsm.o audit-linux.o platform.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ sandbox-null.o sandbox-rlimit.o sandbox-darwin.o \ sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-solaris.o \ sftp-server.o sftp-common.o \ uidswap.o $(SKOBJS) SFTP_CLIENT_OBJS=sftp-common.o sftp-client.o sftp-glob.o SCP_OBJS= scp.o progressmeter.o $(SFTP_CLIENT_OBJS) SSHADD_OBJS= ssh-add.o $(SKOBJS) SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o $(SKOBJS) SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(SKOBJS) SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(SKOBJS) P11HELPER_OBJS= ssh-pkcs11-helper.o ssh-pkcs11.o $(SKOBJS) SKHELPER_OBJS= ssh-sk-helper.o ssh-sk.o sk-usbhid.o SSHKEYSCAN_OBJS=ssh-keyscan.o $(SKOBJS) SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o SFTP_OBJS= sftp.o sftp-usergroup.o progressmeter.o $(SFTP_CLIENT_OBJS) MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5 MANTYPE = @MANTYPE@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out CONFIGFILES_IN=sshd_config ssh_config moduli PATHSUBS = \ -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \ -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \ -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \ -e 's|/usr/libexec|$(libexecdir)|g' \ -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \ -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \ -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \ -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \ -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \ -e 's|/etc/ssh/ssh_host_ed25519_key|$(sysconfdir)/ssh_host_ed25519_key|g' \ -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \ -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \ -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \ -e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \ -e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \ -e 's|/var/empty|$(PRIVSEP_PATH)|g' \ -e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g' FIXPATHSCMD = $(SED) $(PATHSUBS) FIXALGORITHMSCMD= $(SHELL) $(srcdir)/fixalgorithms $(SED) \ @UNSUPPORTED_ALGORITHMS@ all: $(CONFIGFILES) $(MANPAGES) $(TARGETS) $(LIBSSH_OBJS): Makefile.in config.h $(SSHOBJS): Makefile.in config.h $(SSHDOBJS): Makefile.in config.h .c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ LIBCOMPAT=openbsd-compat/libopenbsd-compat.a $(LIBCOMPAT): always (cd openbsd-compat && $(MAKE)) always: libssh.a: $(LIBSSH_OBJS) $(AR) rv $@ $(LIBSSH_OBJS) $(RANLIB) $@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(GSSLIBS) $(CHANNELLIBS) sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(CHANNELLIBS) sshd-session$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHD_SESSION_OBJS) $(LD) -o $@ $(SSHD_SESSION_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) $(LIBWTMPDB) sshd-auth$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHD_AUTH_OBJS) $(LD) -o $@ $(SSHD_AUTH_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) $(LIBWTMPDB) scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS) $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHADD_OBJS) $(LD) -o $@ $(SSHADD_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHAGENT_OBJS) $(LD) -o $@ $(SSHAGENT_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYGEN_OBJS) $(LD) -o $@ $(SSHKEYGEN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSIGN_OBJS) $(LD) -o $@ $(SSHKEYSIGN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS) $(LD) -o $@ $(P11HELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS) $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS) $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) # test driver for the loginrec code - not built by default logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) # compile libssh objects with -fPIC for use in the sk_libfido2 shared library LIBSSH_PIC_OBJS=$(LIBSSH_OBJS:.o=.lo) libssh-pic.a: $(LIBSSH_PIC_OBJS) $(AR) rv $@ $(LIBSSH_PIC_OBJS) $(RANLIB) $@ $(SK_STANDALONE): $(srcdir)/sk-usbhid.c $(LIBCOMPAT) libssh-pic.a $(CC) -o $@ -shared $(CFLAGS_NOPIE) $(CPPFLAGS) -DSK_STANDALONE $(PICFLAG) $(srcdir)/sk-usbhid.c \ libssh-pic.a $(LDFLAGS_NOPIE) -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) $(MANPAGES): $(MANPAGES_IN) if test "$(MANTYPE)" = "cat"; then \ manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \ else \ manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \ fi; \ if test "$(MANTYPE)" = "man"; then \ $(FIXPATHSCMD) $${manpage} | $(FIXALGORITHMSCMD) | \ $(AWK) -f $(srcdir)/mdoc2man.awk > $@; \ else \ $(FIXPATHSCMD) $${manpage} | $(FIXALGORITHMSCMD) > $@; \ fi $(CONFIGFILES): $(CONFIGFILES_IN) Makefile conffile=`echo $@ | sed 's/.out$$//'`; \ $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@ # fake rule to stop make trying to compile moduli.o into a binary "moduli.o" moduli: echo clean: regressclean rm -f *.o *.lo *.a $(TARGETS) logintest config.cache config.log rm -f *.out core survey rm -f regress/check-perm$(EXEEXT) rm -f regress/mkdtemp$(EXEEXT) rm -f regress/unittests/test_helper/*.a rm -f regress/unittests/test_helper/*.o rm -f regress/unittests/authopt/*.o rm -f regress/unittests/authopt/test_authopt$(EXEEXT) rm -f regress/unittests/bitmap/*.o rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT) rm -f regress/unittests/conversion/*.o rm -f regress/unittests/conversion/test_conversion$(EXEEXT) rm -f regress/unittests/hostkeys/*.o rm -f regress/unittests/hostkeys/test_hostkeys$(EXEEXT) rm -f regress/unittests/kex/*.o rm -f regress/unittests/kex/test_kex$(EXEEXT) rm -f regress/unittests/match/*.o rm -f regress/unittests/match/test_match$(EXEEXT) rm -f regress/unittests/misc/*.o rm -f regress/unittests/misc/test_misc$(EXEEXT) rm -f regress/unittests/sshbuf/*.o rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT) rm -f regress/unittests/sshkey/*.o rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT) rm -f regress/unittests/sshsig/*.o rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(EXEEXT) rm -f regress/misc/sk-dummy/*.o rm -f regress/misc/sk-dummy/*.lo rm -f regress/misc/ssh-verify-attestation/ssh-verify-attestation$(EXEEXT) rm -f regress/misc/ssh-verify-attestation/*.o (cd openbsd-compat && $(MAKE) clean) distclean: regressclean rm -f *.o *.a $(TARGETS) logintest config.cache config.log rm -f *.out core opensshd.init openssh.xml rm -f Makefile buildpkg.sh config.h config.status rm -f survey.sh openbsd-compat/regress/Makefile *~ rm -rf autom4te.cache rm -f regress/check-perm rm -f regress/mkdtemp rm -f regress/unittests/test_helper/*.a rm -f regress/unittests/test_helper/*.o rm -f regress/unittests/authopt/*.o rm -f regress/unittests/authopt/test_authopt rm -f regress/unittests/bitmap/*.o rm -f regress/unittests/bitmap/test_bitmap rm -f regress/unittests/conversion/*.o rm -f regress/unittests/conversion/test_conversion rm -f regress/unittests/hostkeys/*.o rm -f regress/unittests/hostkeys/test_hostkeys rm -f regress/unittests/kex/*.o rm -f regress/unittests/kex/test_kex rm -f regress/unittests/match/*.o rm -f regress/unittests/match/test_match rm -f regress/unittests/misc/*.o rm -f regress/unittests/misc/test_misc rm -f regress/unittests/sshbuf/*.o rm -f regress/unittests/sshbuf/test_sshbuf rm -f regress/unittests/sshkey/*.o rm -f regress/unittests/sshkey/test_sshkey rm -f regress/unittests/sshsig/*.o rm -f regress/unittests/sshsig/test_sshsig rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8 rm -f regress/misc/sk-dummy/*.o rm -f regress/misc/sk-dummy/*.lo rm -f regress/misc/sk-dummy/sk-dummy.so rm -f regress/misc/ssh-verify-attestation/ssh-verify-attestation$(EXEEXT) rm -f regress/misc/ssh-verify-attestation/*.o (cd openbsd-compat && $(MAKE) distclean) if test -d pkg ; then \ rm -fr pkg ; \ fi veryclean: distclean rm -f configure config.h.in *.0 cleandir: veryclean mrproper: veryclean realclean: veryclean catman-do: @for f in $(MANPAGES_IN) ; do \ base=`echo $$f | sed 's/\..*$$//'` ; \ echo "$$f -> $$base.0" ; \ $(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \ >$$base.0 ; \ done depend: depend-rebuild rm -f .depend.bak depend-rebuild: mv .depend .depend.old rm -f config.h .depend touch config.h .depend makedepend -w1000 -Y. -f .depend *.c 2>/dev/null (echo '# Automatically generated by makedepend.'; \ echo '# Run "make depend" to rebuild.'; sort .depend ) >.depend.tmp mv .depend.tmp .depend rm -f .depend.bak mv .depend.old .depend.bak rm -f config.h depend-check: depend-rebuild cmp .depend .depend.bak || (echo .depend stale && exit 1) distprep: catman-do depend-check $(AUTORECONF) -rm -rf autom4te.cache .depend.bak install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files check-config: -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config install-files: $(MKDIR_P) $(DESTDIR)$(bindir) $(MKDIR_P) $(DESTDIR)$(sbindir) $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)1 $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)5 $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)8 $(MKDIR_P) $(DESTDIR)$(libexecdir) $(MKDIR_P) -m 0755 $(DESTDIR)$(PRIVSEP_PATH) $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sshd-session$(EXEEXT) $(DESTDIR)$(SSHD_SESSION)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sshd-auth$(EXEEXT) $(DESTDIR)$(SSHD_AUTH)$(EXEEXT) $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 $(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 $(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 install-sysconf: $(MKDIR_P) $(DESTDIR)$(sysconfdir) @if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \ $(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \ else \ echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \ fi @if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \ $(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \ else \ echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \ fi @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \ if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \ echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \ mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \ else \ $(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \ fi ; \ else \ echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \ fi host-key: ssh-keygen$(EXEEXT) @if [ -z "$(DESTDIR)" ] ; then \ ./ssh-keygen -A; \ fi host-key-force: ssh-keygen$(EXEEXT) ssh$(EXEEXT) ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ./ssh-keygen -t ed25519 -f $(DESTDIR)$(sysconfdir)/ssh_host_ed25519_key -N "" if ./ssh -Q key | grep ecdsa >/dev/null ; then \ ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""; \ fi uninstallall: uninstall -rm -f $(DESTDIR)$(sysconfdir)/ssh_config -rm -f $(DESTDIR)$(sysconfdir)/sshd_config -rmdir $(DESTDIR)$(sysconfdir) -rmdir $(DESTDIR)$(bindir) -rmdir $(DESTDIR)$(sbindir) -rmdir $(DESTDIR)$(mandir)/$(mansubdir)1 -rmdir $(DESTDIR)$(mandir)/$(mansubdir)8 -rmdir $(DESTDIR)$(mandir) -rmdir $(DESTDIR)$(libexecdir) uninstall: -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT) -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT) -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 regress-prep: $(MKDIR_P) `pwd`/regress/unittests/test_helper $(MKDIR_P) `pwd`/regress/unittests/authopt $(MKDIR_P) `pwd`/regress/unittests/bitmap $(MKDIR_P) `pwd`/regress/unittests/conversion $(MKDIR_P) `pwd`/regress/unittests/hostkeys $(MKDIR_P) `pwd`/regress/unittests/kex $(MKDIR_P) `pwd`/regress/unittests/match $(MKDIR_P) `pwd`/regress/unittests/misc $(MKDIR_P) `pwd`/regress/unittests/sshbuf $(MKDIR_P) `pwd`/regress/unittests/sshkey $(MKDIR_P) `pwd`/regress/unittests/sshsig $(MKDIR_P) `pwd`/regress/unittests/utf8 $(MKDIR_P) `pwd`/regress/misc/sk-dummy $(MKDIR_P) `pwd`/regress/misc/ssh-verify-attestation [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile REGRESSLIBS=libssh.a $(LIBCOMPAT) TESTLIBS=$(LIBS) $(CHANNELLIBS) regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/timestamp$(EXEEXT): $(srcdir)/regress/timestamp.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/timestamp.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/setuid-allowed.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/mkdtemp$(EXEEXT): $(srcdir)/regress/mkdtemp.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/mkdtemp.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_HELPER_OBJS=\ regress/unittests/test_helper/test_helper.o \ regress/unittests/test_helper/fuzz.o regress/unittests/test_helper/libtest_helper.a: ${UNITTESTS_TEST_HELPER_OBJS} $(AR) rv $@ $(UNITTESTS_TEST_HELPER_OBJS) $(RANLIB) $@ UNITTESTS_TEST_SSHBUF_OBJS=\ regress/unittests/sshbuf/tests.o \ regress/unittests/sshbuf/test_sshbuf.o \ regress/unittests/sshbuf/test_sshbuf_getput_basic.o \ regress/unittests/sshbuf/test_sshbuf_getput_crypto.o \ regress/unittests/sshbuf/test_sshbuf_misc.o \ regress/unittests/sshbuf/test_sshbuf_fuzz.o \ regress/unittests/sshbuf/test_sshbuf_getput_fuzz.o \ regress/unittests/sshbuf/test_sshbuf_fixed.o regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHBUF_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_SSHKEY_OBJS=\ regress/unittests/sshkey/test_fuzz.o \ regress/unittests/sshkey/tests.o \ regress/unittests/sshkey/common.o \ regress/unittests/sshkey/test_file.o \ regress/unittests/sshkey/test_sshkey.o \ $(SKOBJS) regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHKEY_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_SSHSIG_OBJS=\ sshsig.o \ regress/unittests/sshsig/tests.o \ $(SKOBJS) regress/unittests/sshsig/test_sshsig$(EXEEXT): ${UNITTESTS_TEST_SSHSIG_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHSIG_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_BITMAP_OBJS=\ regress/unittests/bitmap/tests.o regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_BITMAP_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_AUTHOPT_OBJS=\ regress/unittests/authopt/tests.o \ auth-options.o \ $(SKOBJS) regress/unittests/authopt/test_authopt$(EXEEXT): \ ${UNITTESTS_TEST_AUTHOPT_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_AUTHOPT_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_CONVERSION_OBJS=\ regress/unittests/conversion/tests.o regress/unittests/conversion/test_conversion$(EXEEXT): \ ${UNITTESTS_TEST_CONVERSION_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_CONVERSION_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_KEX_OBJS=\ regress/unittests/kex/tests.o \ regress/unittests/kex/test_kex.o \ regress/unittests/kex/test_proposal.o \ $(SKOBJS) regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_KEX_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_HOSTKEYS_OBJS=\ regress/unittests/hostkeys/tests.o \ regress/unittests/hostkeys/test_iterate.o \ $(SKOBJS) regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \ ${UNITTESTS_TEST_HOSTKEYS_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_HOSTKEYS_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_MATCH_OBJS=\ regress/unittests/match/tests.o regress/unittests/match/test_match$(EXEEXT): \ ${UNITTESTS_TEST_MATCH_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MATCH_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_MISC_OBJS=\ regress/unittests/misc/tests.o \ regress/unittests/misc/test_parse.o \ regress/unittests/misc/test_expand.o \ regress/unittests/misc/test_convtime.o \ regress/unittests/misc/test_argv.o \ regress/unittests/misc/test_strdelim.o \ regress/unittests/misc/test_hpdelim.o \ regress/unittests/misc/test_ptimeout.o regress/unittests/misc/test_misc$(EXEEXT): \ ${UNITTESTS_TEST_MISC_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MISC_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_UTF8_OBJS=\ regress/unittests/utf8/tests.o regress/unittests/utf8/test_utf8$(EXEEXT): \ ${UNITTESTS_TEST_UTF8_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_UTF8_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) # These all need to be compiled -fPIC, so they are treated differently. SK_DUMMY_OBJS=\ regress/misc/sk-dummy/sk-dummy.lo \ regress/misc/sk-dummy/fatal.lo \ ed25519.lo hash.lo SK_DUMMY_LIBRARY=@SK_DUMMY_LIBRARY@ .c.lo: Makefile.in config.h $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< -o $@ regress/misc/sk-dummy/sk-dummy.so: $(SK_DUMMY_OBJS) $(CC) $(CFLAGS) $(CPPFLAGS) $(PICFLAG) -shared -o $@ $(SK_DUMMY_OBJS) \ -L. -Lopenbsd-compat -lopenbsd-compat $(LDFLAGS_NOPIE) $(TESTLIBS) SSH_VERIFY_ATTESTATION_OBJS=\ regress/misc/ssh-verify-attestation/ssh-verify-attestation.o \ $(SKOBJS) ssh-verify-attestation: regress/misc/ssh-verify-attestation/ssh-verify-attestation$(EXEEXT) regress/misc/ssh-verify-attestation/ssh-verify-attestation$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSH_VERIFY_ATTESTATION_OBJS) $(LD) -o $@ $(SSH_VERIFY_ATTESTATION_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) $(LIBFIDO2) regress-binaries: regress-prep $(LIBCOMPAT) \ regress/modpipe$(EXEEXT) \ regress/timestamp$(EXEEXT) \ regress/setuid-allowed$(EXEEXT) \ regress/netcat$(EXEEXT) \ regress/check-perm$(EXEEXT) \ regress/mkdtemp$(EXEEXT) \ $(SK_DUMMY_LIBRARY) regress-unit-binaries: regress-prep $(REGRESSLIBS) \ regress/unittests/authopt/test_authopt$(EXEEXT) \ regress/unittests/bitmap/test_bitmap$(EXEEXT) \ regress/unittests/conversion/test_conversion$(EXEEXT) \ regress/unittests/hostkeys/test_hostkeys$(EXEEXT) \ regress/unittests/kex/test_kex$(EXEEXT) \ regress/unittests/match/test_match$(EXEEXT) \ regress/unittests/misc/test_misc$(EXEEXT) \ regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ regress/unittests/sshkey/test_sshkey$(EXEEXT) \ regress/unittests/sshsig/test_sshsig$(EXEEXT) \ regress/unittests/utf8/test_utf8$(EXEEXT) tests: file-tests t-exec interop-tests extra-tests unit echo all tests passed unit: regress-unit-binaries cd $(srcdir)/regress || exit $$?; \ $(MAKE) \ .CURDIR="$(abs_top_srcdir)/regress" \ .OBJDIR="$(BUILDDIR)/regress" \ OBJ="$(BUILDDIR)/regress" \ $@ && echo $@ tests passed TEST_SSH_SSHD="$(BUILDDIR)/sshd" interop-tests t-exec file-tests extra-tests: regress-prep regress-binaries $(TARGETS) cd $(srcdir)/regress || exit $$?; \ EGREP='@EGREP@' \ OPENSSL_BIN='@OPENSSL_BIN@' \ $(MAKE) \ .CURDIR="$(abs_top_srcdir)/regress" \ .OBJDIR="$(BUILDDIR)/regress" \ BUILDDIR="$(BUILDDIR)" \ OBJ="$(BUILDDIR)/regress" \ PATH="$(BUILDDIR):$${PATH}" \ TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ TEST_MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ TEST_SSH_SCP="$(BUILDDIR)/scp" \ TEST_SSH_SSH="$(BUILDDIR)/ssh" \ TEST_SSH_SSHD="$(TEST_SSH_SSHD)" \ TEST_SSH_SSHD_SESSION="$(BUILDDIR)/sshd-session" \ TEST_SSH_SSHD_AUTH="$(BUILDDIR)/sshd-auth" \ TEST_SSH_SSHAGENT="$(BUILDDIR)/ssh-agent" \ TEST_SSH_SSHADD="$(BUILDDIR)/ssh-add" \ TEST_SSH_SSHKEYGEN="$(BUILDDIR)/ssh-keygen" \ TEST_SSH_SSHPKCS11HELPER="$(BUILDDIR)/ssh-pkcs11-helper" \ TEST_SSH_SSHKEYSCAN="$(BUILDDIR)/ssh-keyscan" \ TEST_SSH_SFTP="$(BUILDDIR)/sftp" \ TEST_SSH_PKCS11_HELPER="$(BUILDDIR)/ssh-pkcs11-helper" \ TEST_SSH_SK_HELPER="$(BUILDDIR)/ssh-sk-helper" \ TEST_SSH_SFTPSERVER="$(BUILDDIR)/sftp-server" \ TEST_SSH_MODULI_FILE="$(abs_top_srcdir)/moduli" \ TEST_SSH_PLINK="@PLINK@" \ TEST_SSH_PUTTYGEN="@PUTTYGEN@" \ TEST_SSH_CONCH="@CONCH@" \ TEST_SSH_DROPBEAR="@DROPBEAR@" \ TEST_SSH_DROPBEARKEY="@DROPBEARKEY@" \ TEST_SSH_DROPBEARCONVERT="@DROPBEARCONVERT@" \ TEST_SSH_DBCLIENT="@DBCLIENT@" \ TEST_SSH_IPV6="@TEST_SSH_IPV6@" \ TEST_SSH_UTF8="@TEST_SSH_UTF8@" \ TEST_SHELL="$(TEST_SHELL)" \ EXEEXT="$(EXEEXT)" \ $@ && echo all $@ passed compat-tests: $(LIBCOMPAT) (cd openbsd-compat/regress && $(MAKE)) regressclean: if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \ (cd regress && $(MAKE) clean) \ fi survey: survey.sh ssh @$(SHELL) ./survey.sh > survey @echo 'The survey results have been placed in the file "survey" in the' @echo 'current directory. Please review the file then send with' @echo '"make send-survey".' send-survey: survey mail portable-survey@mindrot.org Updated 17 Nov 1995. Updated 19 Oct 1999 for OpenSSH-1.2 Updated 20 May 2001 note obsolete for > OpenSSH-1.2 The software consists of ssh (client), sshd (server), scp, sdist, and the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and make-ssh-known-hosts. The main program for each of these is in a .c file with the same name. There are some subsystems/abstractions that are used by a number of these programs. Buffer manipulation routines - 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 buffer manipulation functions are in sshbuf*.c (header sshbuf.h). Compression Library - Ssh uses the GNU GZIP compression library (ZLIB). Encryption/Decryption - 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 either in libc or LibreSSL. Multiple Precision Integer Library - Uses the LibreSSL BIGNUM sublibrary. Random Numbers - Uses arc4random() and such. RSA key generation, encryption, decryption - Ssh uses the RSA routines in libssl. RSA key files - RSA keys are stored in files with a special format. The code to read/write these files is in authfile.c. The files are normally encrypted with a passphrase. The functions to read passphrases are in readpass.c (the same code is used to read passwords). Binary packet protocol - The ssh binary packet protocol is implemented in packet.c. The 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. - The code in packet.c calls the buffer manipulation routines (buffer.c, bufaux.c), compression routines (zlib), and the encryption routines. X11, TCP/IP, and Agent forwarding - Code for various types of channel forwarding is in channels.c. The file defines a generic framework for arbitrary communication channels inside the secure channel, and uses this framework to implement X11 forwarding, TCP/IP forwarding, and authentication agent forwarding. The new, Protocol 1.5, channel close implementation is in nchan.c Authentication agent - Code to communicate with the authentication agent is in authfd.c. Authentication methods - Code for various authentication methods resides in auth-*.c (auth-passwd.c, auth-rh-rsa.c, auth-rhosts.c, auth-rsa.c). This code is linked into the server. The routines also manipulate known hosts files using code in hostfile.c. Code in canohost.c is used to retrieve the canonical host name of the remote host. Code in match.c is used to match host names. - In the client end, authentication code is in sshconnect.c. It reads Passwords/passphrases using code in readpass.c. It reads RSA key files with authfile.c. It communicates the authentication agent using authfd.c. The ssh client - The client main program is in ssh.c. It first parses arguments and reads configuration (readconf.c), then calls ssh_connect (in sshconnect.c) to open a connection to the server (possibly via a proxy), and performs authentication (ssh_login in sshconnect.c). It then makes any pty, forwarding, etc. requests. It may call code in ttymodes.c to encode current tty modes. Finally it calls client_loop in clientloop.c. This does the real work for the session. Pseudo-tty manipulation and tty modes - Code to allocate and use a pseudo tty is in pty.c. Code to encode and set terminal modes is in ttymodes.c. Logging in (updating utmp, lastlog, etc.) - The code to do things that are done when a user logs in are in login.c. This includes things such as updating the utmp, wtmp, and lastlog files. Some of the code is in sshd.c. Writing to the system log and terminal - The programs use the functions fatal(), log(), debug(), error() in many places to write messages to system log or user's terminal. The implementation that logs to system log is in log-server.c; it is used in the server program. The other programs use an implementation that sends output to stderr; it is in log-client.c. The definitions are in ssh.h. The sshd server (daemon) - The sshd daemon starts by processing arguments and reading the configuration file (servconf.c). It then reads the host key, starts listening for connections, and generates the server key. The server key will be regenerated every hour by an alarm. - When the server receives a connection, it forks, disables the regeneration alarm, and starts communicating with the client. They first perform identification string exchange, then negotiate encryption, then perform authentication, preparatory operations, and finally the server enters the normal session mode by calling server_loop in serverloop.c. This does the real work, calling functions in other modules. - The code for the server is in sshd.c. It contains a lot of stuff, including: - server main program - waiting for connections - processing new connection - authentication - preparatory operations - building up the execution environment for the user program - starting the user program. Auxiliary files - There are several other files in the distribution that contain various auxiliary routines: ssh.h the main header file for ssh (various definitions) uidswap.c uid-swapping xmalloc.c "safe" malloc routines $OpenBSD: OVERVIEW,v 1.15 2018/10/23 05:56:35 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL100644 001750 001750 0000000003614775415623 0014340xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL010064400017500001750000000675261477541562300127430ustar00djmdjmThis documents OpenSSH's deviations and extensions to the published SSH protocol. Note that OpenSSH's sftp and sftp-server implement revision 3 of the SSH filexfer protocol described in: 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. The protocol used by OpenSSH's ssh-agent is described in the file PROTOCOL.agent 1. Transport protocol changes 1.1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com" This is a new transport-layer MAC method using the UMAC algorithm (rfc4418). This method is identical to the "umac-64" method documented in: https://www.openssh.com/txt/draft-miller-secsh-umac-01.txt 1.2. transport: Protocol 2 compression algorithm "zlib@openssh.com" This transport-layer compression method uses the zlib compression algorithm (identical to the "zlib" method in rfc4253), but delays the start of compression until after authentication has completed. This avoids exposing compression code to attacks from unauthenticated users. The method is documented in: https://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt 1.3. transport: New public key algorithms "ssh-rsa-cert-v01@openssh.com", "ssh-dsa-cert-v01@openssh.com", "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ecdsa-sha2-nistp384-cert-v01@openssh.com" and "ecdsa-sha2-nistp521-cert-v01@openssh.com" OpenSSH introduces new public key algorithms to support certificate authentication for users and host keys. These methods are documented in the file PROTOCOL.certkeys 1.4. transport: Elliptic Curve cryptography OpenSSH supports ECC key exchange and public key authentication as specified in RFC5656. Only the ecdsa-sha2-nistp256, ecdsa-sha2-nistp384 and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic curve points encoded using point compression are NOT accepted or generated. 1.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms OpenSSH supports MAC algorithms, whose names contain "-etm", that perform the calculations in a different order to that defined in RFC 4253. These variants use the so-called "encrypt then MAC" ordering, calculating the MAC over the packet ciphertext rather than the plaintext. This ordering closes a security flaw in the SSH transport protocol, where decryption of unauthenticated ciphertext provided a "decryption oracle" that could, in conjunction with cipher flaws, reveal session plaintext. Specifically, the "-etm" MAC algorithms modify the transport protocol to calculate the MAC over the packet ciphertext and to send the packet length unencrypted. This is necessary for the transport to obtain the length of the packet and location of the MAC tag so that it may be verified without decrypting unauthenticated data. As such, the MAC covers: mac = MAC(key, sequence_number || packet_length || encrypted_packet) where "packet_length" is encoded as a uint32 and "encrypted_packet" contains: byte padding_length byte[n1] payload; n1 = packet_length - padding_length - 1 byte[n2] random padding; n2 = padding_length 1.6 transport: AES-GCM OpenSSH supports the AES-GCM algorithm as specified in RFC 5647. Because of problems with the specification of the key exchange the behaviour of OpenSSH differs from the RFC as follows: AES-GCM is only negotiated as the cipher algorithms "aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as an MAC algorithm. Additionally, if AES-GCM is selected as the cipher the exchanged MAC algorithms are ignored and there doesn't have to be a matching MAC. 1.7 transport: chacha20-poly1305@openssh.com authenticated encryption OpenSSH supports authenticated encryption using ChaCha20 and Poly1305 as described in PROTOCOL.chacha20poly1305. 1.8 transport: curve25519-sha256@libssh.org key exchange algorithm OpenSSH supports the use of ECDH in Curve25519 for key exchange as described at: http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519 This is identical to curve25519-sha256 as later published in RFC8731. 1.9 transport: ping facility OpenSSH implements a transport level ping message SSH2_MSG_PING and a corresponding SSH2_MSG_PONG reply. #define SSH2_MSG_PING 192 #define SSH2_MSG_PONG 193 The ping message is simply: byte SSH_MSG_PING string data The reply copies the data (which may be the empty string) from the ping: byte SSH_MSG_PONG string data Replies are sent in order. They are sent immediately except when rekeying is in progress, in which case they are queued until rekeying completes. The server advertises support for these messages using the SSH2_MSG_EXT_INFO mechanism (RFC8308), with the following message: string "ping@openssh.com" string "0" (version) The ping/reply message is implemented at the transport layer rather than as a named global or channel request to allow pings with very short packet lengths, which would not be possible with other approaches. 1.10 transport: strict key exchange extension OpenSSH supports a number of transport-layer hardening measures under a "strict KEX" feature. This feature is signalled similarly to the RFC8308 ext-info feature: by including a additional algorithm in the initial SSH2_MSG_KEXINIT kex_algorithms field. The client may append "kex-strict-c-v00@openssh.com" to its kex_algorithms and the server may append "kex-strict-s-v00@openssh.com". These pseudo-algorithms are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored if they are present in subsequent SSH2_MSG_KEXINIT packets. When an endpoint that supports this extension observes this algorithm name in a peer's KEXINIT packet, it MUST make the following changes to the protocol: a) During initial KEX, terminate the connection if out-of-sequence packet or any message that is not strictly required by KEX is received. This includes terminating the connection if the first packet received is not SSH2_MSG_KEXINIT. Unexpected packets for the purpose of strict KEX include messages that are otherwise valid at any time during the connection such as SSH2_MSG_DEBUG, SSH2_MSG_IGNORE or SSH2_MSG_UNIMPLEMENTED. b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the packet sequence number to zero. This behaviour persists for the duration of the connection (i.e. not just the first SSH2_MSG_NEWKEYS). 1.11 transport: SSH2_MSG_EXT_INFO during user authentication This protocol extension allows the SSH2_MSG_EXT_INFO to be sent during user authentication. RFC8308 does allow a second SSH2_MSG_EXT_INFO notification, but it may only be sent at the end of user authentication and this is too late to signal per-user server signature algorithms. Support for receiving the SSH2_MSG_EXT_INFO message during user authentication is signalled by the client including a "ext-info-in-auth@openssh.com" key via its initial SSH2_MSG_EXT_INFO set after the SSH2_MSG_NEWKEYS message. A server that supports this extension MAY send a second SSH2_MSG_EXT_INFO message any time after the client's first SSH2_MSG_USERAUTH_REQUEST, regardless of whether it succeed or fails. The client SHOULD be prepared to update the server-sig-algs that it received during an earlier SSH2_MSG_EXT_INFO with the later one. 2. Connection protocol changes 2.1. connection: Channel write close extension "eow@openssh.com" The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF message to allow an endpoint to signal its peer that it will send no more data over a channel. Unfortunately, there is no symmetric way for an endpoint to request that its peer should cease sending data to it while still keeping the channel open for the endpoint to send data to the peer. This is desirable, since it saves the transmission of data that would otherwise need to be discarded and it allows an endpoint to signal local processes of the condition, e.g. by closing the corresponding file descriptor. OpenSSH implements a channel extension message to perform this signalling: "eow@openssh.com" (End Of Write). This message is sent by an endpoint when the local output of a session channel is closed or experiences a write error. The message is formatted as follows: byte SSH_MSG_CHANNEL_REQUEST uint32 recipient channel string "eow@openssh.com" boolean FALSE On receiving this message, the peer SHOULD cease sending data of the channel and MAY signal the process from which the channel data originates (e.g. by closing its read file descriptor). As with the symmetric SSH_MSG_CHANNEL_EOF message, the channel does remain open after a "eow@openssh.com" has been sent and more data may still be sent in the other direction. This message does not consume window space and may be sent even if no window space is available. NB. due to certain broken SSH implementations aborting upon receipt of this message (in contravention of RFC4254 section 5.4), this message is only sent to OpenSSH peers (identified by banner). Other SSH implementations may be listed to receive this message upon request. 2.2. connection: disallow additional sessions extension "no-more-sessions@openssh.com" Most SSH connections will only ever request a single session, but a attacker may abuse a running ssh client to surreptitiously open additional sessions under their control. OpenSSH provides a global request "no-more-sessions@openssh.com" to mitigate this attack. When an OpenSSH client expects that it will never open another session (i.e. it has been started with connection multiplexing disabled), it will send the following global request: byte SSH_MSG_GLOBAL_REQUEST string "no-more-sessions@openssh.com" char want-reply On receipt of such a message, an OpenSSH server will refuse to open future channels of type "session" and instead immediately abort the connection. Note that this is not a general defence against compromised clients (that is impossible), but it thwarts a simple attack. NB. due to certain broken SSH implementations aborting upon receipt of this message, the no-more-sessions request is only sent to OpenSSH servers (identified by banner). Other SSH implementations may be listed to receive this message upon request. 2.3. connection: Tunnel forward extension "tun@openssh.com" 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 interfaces like the BSD tun(4) device. Tunnel forwarding channels are requested by the client with the following packet: byte SSH_MSG_CHANNEL_OPEN string "tun@openssh.com" uint32 sender channel uint32 initial window size uint32 maximum packet size uint32 tunnel mode uint32 remote unit number The "tunnel mode" parameter specifies whether the tunnel should forward layer 2 frames or layer 3 packets. It may take one of the following values: SSH_TUNMODE_POINTOPOINT 1 /* layer 3 packets */ 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 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. Once established the client and server may exchange packet or frames over the tunnel channel by encapsulating them in SSH protocol strings and sending them as channel data. This ensures that packet boundaries are kept intact. Specifically, packets are transmitted using normal SSH_MSG_CHANNEL_DATA packets: byte SSH_MSG_CHANNEL_DATA uint32 recipient channel string data The contents of the "data" field for layer 3 packets is: uint32 packet length uint32 address family byte[packet length - 4] packet data The "address family" field identifies the type of packet in the message. It may be one of: SSH_TUN_AF_INET 2 /* IPv4 */ SSH_TUN_AF_INET6 24 /* IPv6 */ The "packet data" field consists of the IPv4/IPv6 datagram itself without any link layer header. The contents of the "data" field for layer 2 packets is: uint32 packet length byte[packet length] frame The "frame" field contains an IEEE 802.3 Ethernet frame, including header. 2.4. connection: Unix domain socket forwarding OpenSSH supports local and remote Unix domain socket forwarding using the "streamlocal" extension. Forwarding is initiated as per TCP sockets but with a single path instead of a host and port. Similar to direct-tcpip, direct-streamlocal is sent by the client to request that the server make a connection to a Unix domain socket. byte SSH_MSG_CHANNEL_OPEN string "direct-streamlocal@openssh.com" uint32 sender channel uint32 initial window size uint32 maximum packet size string socket path 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 GLOBAL_REQUEST. byte SSH_MSG_CHANNEL_OPEN string "forwarded-streamlocal@openssh.com" uint32 sender channel uint32 initial window size uint32 maximum packet size string socket path string reserved for future use The reserved field is not currently defined and is ignored on the remote end. It is intended to be used in the future to pass information about the socket file, such as ownership and mode. The client currently sends the empty string for this field. Similar to tcpip-forward, streamlocal-forward is sent by the client to request remote forwarding of a Unix domain socket. byte SSH2_MSG_GLOBAL_REQUEST string "streamlocal-forward@openssh.com" boolean TRUE string socket path Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent by the client cancel the forwarding of a Unix domain socket. byte SSH2_MSG_GLOBAL_REQUEST string "cancel-streamlocal-forward@openssh.com" boolean FALSE string socket path 2.5. connection: hostkey update and rotation "hostkeys-00@openssh.com" and "hostkeys-prove-00@openssh.com" OpenSSH supports a protocol extension allowing a server to inform a client of all its protocol v.2 host keys after user-authentication has completed. byte SSH_MSG_GLOBAL_REQUEST string "hostkeys-00@openssh.com" char 0 /* want-reply */ string[] hostkeys Upon receiving this message, a client should check which of the supplied host keys are present in known_hosts. Note that the server may send key types that the client does not support. The client should disregard such keys if they are received. If the client identifies any keys that are not present for the host, it should send a "hostkeys-prove@openssh.com" message to request the server prove ownership of the private half of the key. byte SSH_MSG_GLOBAL_REQUEST string "hostkeys-prove-00@openssh.com" char 1 /* want-reply */ string[] hostkeys When a server receives this message, it should generate a signature using each requested key over the following: string "hostkeys-prove-00@openssh.com" string session identifier string hostkey These signatures should be included in the reply, in the order matching the hostkeys in the request: byte SSH_MSG_REQUEST_SUCCESS string[] signatures When the client receives this reply (and not a failure), it should validate the signatures and may update its known_hosts file, adding keys that it has not seen before and deleting keys for the server host that are no longer offered. These extensions let a client learn key types that it had not previously encountered, thereby allowing it to potentially upgrade from weaker key algorithms to better ones. It also supports graceful key rotation: a server may offer multiple keys of the same type for a period (to give clients an opportunity to learn them using this extension) before removing the deprecated key from those offered. 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. Authentication protocol changes 3.1. Host-bound public key authentication This is trivial change to the traditional "publickey" authentication method. The authentication request is identical to the original method but for the name and one additional field: byte SSH2_MSG_USERAUTH_REQUEST string username string "ssh-connection" string "publickey-hostbound-v00@openssh.com" bool has_signature string pkalg string public key string server host key Because the entire SSH2_MSG_USERAUTH_REQUEST message is included in the signed data, this ensures that a binding between the destination user, the server identity and the session identifier is visible to the signer. OpenSSH uses this binding via signed data to implement per-key restrictions in ssh-agent. A server may advertise this method using the SSH2_MSG_EXT_INFO mechanism (RFC8308), with the following message: string "publickey-hostbound@openssh.com" string "0" (version) Clients should prefer host-bound authentication when advertised by server. 4. SFTP protocol changes 4.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK When OpenSSH's sftp-server was implemented, the order of the arguments to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, the reversal was not noticed until the server was widely deployed. Since fixing this to follow the specification would cause incompatibility, the current order was retained. For correct operation, clients should send SSH_FXP_SYMLINK as follows: uint32 id string targetpath string linkpath 4.2. sftp: Server extension announcement in SSH_FXP_VERSION OpenSSH's sftp-server lists the extensions it supports using the standard extension announcement mechanism in the SSH_FXP_VERSION server hello packet: uint32 3 /* protocol version */ string ext1-name string ext1-version string ext2-name string ext2-version ... string extN-name string extN-version Each extension reports its integer version number as an ASCII encoded string, e.g. "1". The version will be incremented if the extension is ever changed in an incompatible way. The server MAY advertise the same extension with multiple versions (though this is unlikely). Clients MUST check the version number before attempting to use the extension. 4.3. sftp: Extension request "posix-rename@openssh.com" This operation provides a rename operation with POSIX semantics, which are different to those provided by the standard SSH_FXP_RENAME in draft-ietf-secsh-filexfer-02.txt. This request is implemented as a SSH_FXP_EXTENDED request with the following format: uint32 id string "posix-rename@openssh.com" string oldpath string newpath On receiving this request the server will perform the POSIX operation rename(oldpath, newpath) and will respond with a SSH_FXP_STATUS message. This extension is advertised in the SSH_FXP_VERSION hello with version "1". 4.4. sftp: Extension requests "statvfs@openssh.com" and "fstatvfs@openssh.com" These requests correspond to the statvfs and fstatvfs POSIX system interfaces. The "statvfs@openssh.com" request operates on an explicit pathname, and is formatted as follows: uint32 id string "statvfs@openssh.com" string path The "fstatvfs@openssh.com" operates on an open file handle: uint32 id string "fstatvfs@openssh.com" string handle These requests return a SSH_FXP_STATUS reply on failure. On success they return the following SSH_FXP_EXTENDED_REPLY reply: uint32 id uint64 f_bsize /* file system block size */ uint64 f_frsize /* fundamental fs block size */ uint64 f_blocks /* number of blocks (unit f_frsize) */ uint64 f_bfree /* free blocks in file system */ uint64 f_bavail /* free blocks for non-root */ uint64 f_files /* total file inodes */ uint64 f_ffree /* free file inodes */ uint64 f_favail /* free file inodes for to non-root */ uint64 f_fsid /* file system id */ uint64 f_flag /* bit mask of f_flag values */ uint64 f_namemax /* maximum filename length */ The values of the f_flag bitmask are as follows: #define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */ #define SSH_FXE_STATVFS_ST_NOSUID 0x2 /* no setuid */ Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are advertised in the SSH_FXP_VERSION hello with version "2". 4.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 following format: uint32 id string "hardlink@openssh.com" string oldpath string newpath On receiving this request the server will perform the operation 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". 4.6. sftp: Extension request "fsync@openssh.com" This request asks the server to call fsync(2) on an open file handle. uint32 id string "fsync@openssh.com" string handle On receiving this request, a server will call fsync(handle_fd) and will respond with a SSH_FXP_STATUS message. This extension is advertised in the SSH_FXP_VERSION hello with version "1". 4.7. sftp: Extension request "lsetstat@openssh.com" This request is like the "setstat" command, but sets file attributes on symlinks. It is implemented as a SSH_FXP_EXTENDED request with the following format: uint32 id string "lsetstat@openssh.com" string path ATTRS attrs See the "setstat" command for more details. This extension is advertised in the SSH_FXP_VERSION hello with version "1". 4.8. sftp: Extension request "limits@openssh.com" This request is used to determine various limits the server might impose. Clients should not attempt to exceed these limits as the server might sever the connection immediately. uint32 id string "limits@openssh.com" The server will respond with a SSH_FXP_EXTENDED_REPLY reply: uint32 id uint64 max-packet-length uint64 max-read-length uint64 max-write-length uint64 max-open-handles The 'max-packet-length' applies to the total number of bytes in a single SFTP packet. Servers SHOULD set this at least to 34000. The 'max-read-length' is the largest length in a SSH_FXP_READ packet. Even if the client requests a larger size, servers will usually respond with a shorter SSH_FXP_DATA packet. Servers SHOULD set this at least to 32768. The 'max-write-length' is the largest length in a SSH_FXP_WRITE packet the server will accept. Servers SHOULD set this at least to 32768. The 'max-open-handles' is the maximum number of active handles that the server allows (e.g. handles created by SSH_FXP_OPEN and SSH_FXP_OPENDIR packets). Servers MAY count internal file handles against this limit (e.g. system logging or stdout/stderr), so clients SHOULD NOT expect to open this many handles in practice. If the server doesn't enforce a specific limit, then the field may be set to 0. This implies the server relies on the OS to enforce limits (e.g. available memory or file handles), and such limits might be dynamic. The client SHOULD take care to not try to exceed reasonable limits. This extension is advertised in the SSH_FXP_VERSION hello with version "1". 4.9. sftp: Extension request "expand-path@openssh.com" This request supports canonicalisation of relative paths and those that need tilde-expansion, i.e. "~", "~/..." and "~user/..." These paths are expanded using shell-like rules and the resultant path is canonicalised similarly to SSH2_FXP_REALPATH. It is implemented as a SSH_FXP_EXTENDED request with the following format: uint32 id string "expand-path@openssh.com" string path Its reply is the same format as that of SSH2_FXP_REALPATH. This extension is advertised in the SSH_FXP_VERSION hello with version "1". 4.10. sftp: Extension request "copy-data" This request asks the server to copy data from one open file handle and write it to a different open file handle. This avoids needing to transfer the data across the network twice (a download followed by an upload). byte SSH_FXP_EXTENDED uint32 id string "copy-data" string read-from-handle uint64 read-from-offset uint64 read-data-length string write-to-handle uint64 write-to-offset The server will copy read-data-length bytes starting from read-from-offset from the read-from-handle and write them to write-to-handle starting from write-to-offset, and then respond with a SSH_FXP_STATUS message. It's equivalent to issuing a series of SSH_FXP_READ requests on read-from-handle and a series of requests of SSH_FXP_WRITE on write-to-handle. If read-from-handle and write-to-handle are the same, the server will fail the request and respond with a SSH_FX_INVALID_PARAMETER message. If read-data-length is 0, then the server will read data from the read-from-handle until EOF is reached. This extension is advertised in the SSH_FXP_VERSION hello with version "1". This request is identical to the "copy-data" request documented in: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-extensions-00#section-7 4.11. sftp: Extension request "home-directory" This request asks the server to expand the specified user's home directory. An empty username implies the current user. This can be used by the client to expand ~/ type paths locally. byte SSH_FXP_EXTENDED uint32 id string "home-directory" string username This extension is advertised in the SSH_FXP_VERSION hello with version "1". This provides similar information as the "expand-path@openssh.com" extension. This request is identical to the "home-directory" request documented in: https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-extensions-00#section-5 4.12. sftp: Extension request "users-groups-by-id@openssh.com" This request asks the server to return user and/or group names that correspond to one or more IDs (e.g. as returned from a SSH_FXP_STAT request). This may be used by the client to provide usernames in directory listings. byte SSH_FXP_EXTENDED uint32 id string "users-groups-by-id@openssh.com" string uids string gids Where "uids" and "gids" consists of one or more integer user or group identifiers: uint32 id-0 ... The server will reply with a SSH_FXP_EXTENDED_REPLY: byte SSH_FXP_EXTENDED_REPLY uint32 id string usernames string groupnames Where "username" and "groupnames" consists of names in identical request order to "uids" and "gids" respectively: string name-0 ... If a name cannot be identified for a given user or group ID, an empty string will be returned in its place. It is acceptable for either "uids" or "gids" to be an empty set, in which case the respective "usernames" or "groupnames" list will also be empty. This extension is advertised in the SSH_FXP_VERSION hello with version "1". 5. Miscellaneous changes 5.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. 5.2 Private key format OpenSSH private keys, as generated by ssh-keygen(1) use the format described in PROTOCOL.key by default. As a legacy option, PEM format (RFC7468) private keys are also supported for RSA, DSA and ECDSA keys and were the default format before OpenSSH 7.8. 5.3 KRL format OpenSSH supports a compact format for Key Revocation Lists (KRLs). This format is described in the PROTOCOL.krl file. 5.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. 5.5. Agent protocol extensions OpenSSH extends the usual agent protocol. These changes are documented in the PROTOCOL.agent file. $OpenBSD: PROTOCOL,v 1.55 2024/01/08 05:05:15 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.agent100644 001750 001750 0000000003614775415623 0015435xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.agent010064400017500001750000000104451477541562300140240ustar00djmdjmThe SSH agent protocol is described in https://datatracker.ietf.org/doc/draft-ietf-sshm-ssh-agent/ This file documents OpenSSH's extensions to the agent protocol. 1. session-bind@openssh.com extension This extension allows a ssh client to bind an agent connection to a particular SSH session identifier as derived from the initial key exchange (as per RFC4253 section 7.2) and the host key used for that exchange. This binding is verifiable at the agent by including the initial KEX signature made by the host key. The message format is: byte SSH_AGENTC_EXTENSION (0x1b) string session-bind@openssh.com string hostkey string session identifier string signature bool is_forwarding Where 'hostkey' is the encoded server host public key, 'session identifier' is the exchange hash derived from the initial key exchange, 'signature' is the server's signature of the session identifier using the private hostkey, as sent in the final SSH2_MSG_KEXDH_REPLY/SSH2_MSG_KEXECDH_REPLY message of the initial key exchange. 'is_forwarding' is a flag indicating whether this connection should be bound for user authentication or forwarding. When an agent received this message, it will verify the signature and check the consistency of its contents, including refusing to accept a duplicate session identifier, or any attempt to bind a connection previously bound for authentication. It will then record the binding for the life of the connection for use later in testing per-key destination constraints. 2. restrict-destination-v00@openssh.com key constraint extension The key constraint extension supports destination- and forwarding path- restricted keys. It may be attached as a constraint when keys or smartcard keys are added to an agent. byte SSH_AGENT_CONSTRAIN_EXTENSION (0xff) string restrict-destination-v00@openssh.com constraint[] constraints Where a constraint consists of: string from_username (must be empty) string from_hostname string reserved keyspec[] from_hostkeys string to_username string to_hostname string reserved keyspec[] to_hostkeys string reserved And a keyspec consists of: string keyblob bool is_ca When receiving this message, the agent will ensure that the 'from_username' field is empty, and that 'to_hostname' and 'to_hostkeys' have been supplied (empty 'from_hostname' and 'from_hostkeys' are valid and signify the initial hop from the host running ssh-agent). The agent will then record the constraint against the key. Subsequent operations on this key including add/remove/request identities and, in particular, signature requests will check the key constraints against the session-bind@openssh.com bindings recorded for the agent connection over which they were received. 3. SSH_AGENT_CONSTRAIN_MAXSIGN key constraint This key constraint allows communication to an agent of the maximum number of signatures that may be made with an XMSS key. The format of the constraint is: byte SSH_AGENT_CONSTRAIN_MAXSIGN (0x03) uint32 max_signatures This option is only valid for XMSS keys. 3. associated-certs-v00@openssh.com key constraint extension The key constraint extension allows certificates to be associated with private keys as they are loaded from a PKCS#11 token. byte SSH_AGENT_CONSTRAIN_EXTENSION (0xff) string associated-certs-v00@openssh.com bool certs_only string certsblob Where "certsblob" consists of one or more certificates encoded as public key blobs: string[] certificates This extension is only valid for SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests. When an agent receives this extension, it will attempt to match each certificate in the request with a corresponding private key loaded from the requested PKCS#11 token. When a matching key is found, the agent will graft the certificate contents to the token-hosted private key and store the result for subsequent use by regular agent operations. If the "certs_only" flag is set, then this extension will cause ONLY the resultant certificates to be loaded to the agent. The default behaviour is to load the PKCS#11-hosted private key as well as the resultant certificate. A SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED will return SSH_AGENT_SUCCESS if any key (plain private or certificate) was successfully loaded, or SSH_AGENT_FAILURE if no key was loaded. $OpenBSD: PROTOCOL.agent,v 1.24 2024/11/27 13:27:34 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.certkeys100644 001750 001750 0000000003614775415623 0016170xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.certkeys010064400017500001750000000320501477541562300145530ustar00djmdjmThis document describes a simple public-key certificate authentication system for use by SSH. Background ---------- The SSH protocol currently supports a simple public key authentication mechanism. Unlike other public key implementations, SSH eschews the use of X.509 certificates and uses raw keys. This approach has some benefits relating to simplicity of configuration and minimisation of attack surface, but it does not support the important use-cases of centrally managed, passwordless authentication and centrally certified host keys. These protocol extensions build on the simple public key authentication system already in SSH to allow certificate-based authentication. The certificates used are not traditional X.509 certificates, with numerous options and complex encoding rules, but something rather more minimal: a key, some identity information and usage options that have been signed with some other trusted key. A sshd server may be configured to allow authentication via certified keys, by extending the existing ~/.ssh/authorized_keys mechanism to allow specification of certification authority keys in addition to raw user keys. The ssh client will support automatic verification of acceptance of certified host keys, by adding a similar ability to specify CA keys in ~/.ssh/known_hosts. All certificate types include certification information along with the public key that is used to sign challenges. In OpenSSH, ssh-keygen performs the CA signing operation. Certified keys are represented using new key types: ssh-rsa-cert-v01@openssh.com ssh-dss-cert-v01@openssh.com ecdsa-sha2-nistp256-cert-v01@openssh.com ecdsa-sha2-nistp384-cert-v01@openssh.com ecdsa-sha2-nistp521-cert-v01@openssh.com ssh-ed25519-cert-v01@openssh.com Two additional types exist for RSA certificates to force use of SHA-2 signatures (SHA-256 and SHA-512 respectively): rsa-sha2-256-cert-v01@openssh.com rsa-sha2-512-cert-v01@openssh.com These RSA/SHA-2 types should not appear in keys at rest or transmitted on the wire, but do appear in a SSH_MSG_KEXINIT's host-key algorithms field or in the "public key algorithm name" field of a "publickey" SSH_USERAUTH_REQUEST to indicate that the signature will use the specified algorithm. Protocol extensions ------------------- The SSH wire protocol includes several extensibility mechanisms. These modifications shall take advantage of namespaced public key algorithm names to add support for certificate authentication without breaking the protocol - implementations that do not support the extensions will simply ignore them. Authentication using the new key formats described below proceeds using the existing SSH "publickey" authentication method described in RFC4252 section 7. New public key formats ---------------------- The certificate key types take a similar high-level format (note: data types and encoding are as per RFC4251 section 5). The serialised wire encoding of these certificates is also used for storing them on disk. #define SSH_CERT_TYPE_USER 1 #define SSH_CERT_TYPE_HOST 2 RSA certificate string "ssh-rsa-cert-v01@openssh.com" string nonce mpint e mpint n uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before string critical options string extensions string reserved string signature key string signature DSA certificate string "ssh-dss-cert-v01@openssh.com" string nonce mpint p mpint q mpint g mpint y uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before string critical options string extensions string reserved string signature key string signature ECDSA certificate string "ecdsa-sha2-nistp256-cert-v01@openssh.com" | "ecdsa-sha2-nistp384-cert-v01@openssh.com" | "ecdsa-sha2-nistp521-cert-v01@openssh.com" string nonce string curve string public_key uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before string critical options string extensions string reserved string signature key string signature ED25519 certificate string "ssh-ed25519-cert-v01@openssh.com" string nonce string pk uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before string critical options string extensions string reserved string signature key string signature The nonce field is a CA-provided random bitstring of arbitrary length (but typically 16 or 32 bytes) included to make attacks that depend on inducing collisions in the signature hash infeasible. e and n are the RSA exponent and public modulus respectively. p, q, g, y are the DSA parameters as described in FIPS-186-2. curve and public key are respectively the ECDSA "[identifier]" and "Q" defined in section 3.1 of RFC5656. pk is the encoded Ed25519 public key as defined by RFC8032. serial is an optional certificate serial number set by the CA to provide an abbreviated way to refer to certificates from that CA. If a CA does not wish to number its certificates, it must set this field to zero. type specifies whether this certificate is for identification of a user or a host using a SSH_CERT_TYPE_... value. key id is a free-form text field that is filled in by the CA at the time of signing; the intention is that the contents of this field are used to identify the identity principal in log messages. "valid principals" is a string containing zero or more principals as strings packed inside it. These principals list the names for which this certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and usernames for SSH_CERT_TYPE_USER certificates. As a special case, a zero-length "valid principals" field means the certificate is valid for any principal of the specified type. "valid after" and "valid before" specify a validity period for the certificate. Each represents a time in seconds since 1970-01-01 00:00:00. A certificate is considered valid if: valid after <= current time < valid before critical options is a set of zero or more key options encoded as below. All such options are "critical" in the sense that an implementation must refuse to authorise a key that has an unrecognised option. extensions is a set of zero or more optional extensions. These extensions are not critical, and an implementation that encounters one that it does not recognise may safely ignore it. Generally, critical options are used to control features that restrict access where extensions are used to enable features that grant access. This ensures that certificates containing unknown restrictions do not inadvertently grant access while allowing new protocol features to be enabled via extensions without breaking certificates' backwards compatibility. The reserved field is currently unused and is ignored in this version of the protocol. The signature key field contains the CA key used to sign the certificate. The valid key types for CA keys are ssh-rsa, ssh-dss, ssh-ed25519 and the ECDSA types ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" certificates, where the signature key type is a certificate type itself are NOT supported. Note that it is possible for a RSA certificate key to be signed by a Ed25519 or ECDSA CA key and vice-versa. signature is computed over all preceding fields from the initial string up to, and including the signature key. Signatures are computed and encoded according to the rules defined for the CA's public key algorithm (RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA types, and RFC8032 for Ed25519). Critical options ---------------- The critical options section of the certificate specifies zero or more options on the certificate's validity. The format of this field is a sequence of zero or more tuples: string name string data Options must be lexically ordered by "name" if they appear in the sequence. Each named option may only appear once in a certificate. The name field identifies the option. The data field contains option-specific information encoded as zero or more values inside the string. I.e. an empty data field would be encoded as a zero- length string (00 00 00 00), and data field that holds a single string value "a" would be encoded as (00 00 00 05 00 00 00 01 65). All options are "critical"; if an implementation does not recognise a option, then the validating party should refuse to accept the certificate. Custom options should append the originating author or organisation's domain name to the option name, e.g. "my-option@example.com". No critical options are defined for host certificates at present. The supported user certificate options and the contents and structure of their data fields are: Name Format Description ----------------------------------------------------------------------------- force-command string Specifies a command that is executed (replacing any the user specified on the ssh command-line) whenever this key is used for authentication. source-address string Comma-separated list of source addresses from which this certificate is accepted for authentication. Addresses are specified in CIDR format (nn.nn.nn.nn/nn or hhhh::hhhh/nn). If this option is not present, then certificates may be presented from any source address. verify-required empty Flag indicating that signatures made with this certificate must assert FIDO user verification (e.g. PIN or biometric). This option only makes sense for the U2F/FIDO security key types that support this feature in their signature formats. Extensions ---------- The extensions section of the certificate specifies zero or more non-critical certificate extensions. The encoding and ordering of extensions in this field is identical to that of the critical options, as is the requirement that each name appear only once. If an implementation does not recognise an extension, then it should ignore it. Custom options should append the originating author or organisation's domain name to the option name, e.g. "my-option@example.com". No extensions are defined for host certificates at present. The supported user certificate extensions and the contents and structure of their data fields are: Name Format Description ----------------------------------------------------------------------------- no-touch-required empty Flag indicating that signatures made with this certificate need not assert FIDO user presence. This option only makes sense for the U2F/FIDO security key types that support this feature in their signature formats. permit-X11-forwarding empty Flag indicating that X11 forwarding should be permitted. X11 forwarding will be refused if this option is absent. permit-agent-forwarding empty Flag indicating that agent forwarding should be allowed. Agent forwarding must not be permitted unless this option is present. permit-port-forwarding empty Flag indicating that port-forwarding should be allowed. If this option is not present, then no port forwarding will be allowed. permit-pty empty Flag indicating that PTY allocation should be permitted. In the absence of this option PTY allocation will be disabled. permit-user-rc empty Flag indicating that execution of ~/.ssh/rc should be permitted. Execution of this script will not be permitted if this option is not present. $OpenBSD: PROTOCOL.certkeys,v 1.20 2024/12/06 16:02:12 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.chacha20poly1305100644 001750 001750 0000000003614775415623 0017125xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.chacha20poly1305010064400017500001750000000110271477541562300155110ustar00djmdjmThis document describes the chacha20-poly1305@openssh.com authenticated encryption cipher supported by OpenSSH. Background ---------- ChaCha20 is a stream cipher designed by Daniel Bernstein and described in [1]. It operates by permuting 128 fixed bits, 128 or 256 bits of key, a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output is used as a keystream, with any unused bytes simply discarded. Poly1305[2], also by Daniel Bernstein, is a one-time Carter-Wegman MAC that computes a 128 bit integrity tag given a message and a single-use 256 bit secret key. The chacha20-poly1305@openssh.com combines these two primitives into an authenticated encryption mode. The construction used is based on that proposed for TLS by Adam Langley in [3], but differs in the layout of data passed to the MAC and in the addition of encryption of the packet lengths. Negotiation ----------- The chacha20-poly1305@openssh.com offers both encryption and authentication. As such, no separate MAC is required. If the chacha20-poly1305@openssh.com cipher is selected in key exchange, the offered MAC algorithms are ignored and no MAC is required to be negotiated. Detailed Construction --------------------- The chacha20-poly1305@openssh.com cipher requires 512 bits of key material as output from the SSH key exchange. This forms two 256 bit keys (K_1 and K_2), used by two separate instances of chacha20. The first 256 bits constitute K_2 and the second 256 bits become K_1. The instance keyed by K_1 is a stream cipher that is used only to encrypt the 4 byte packet length field. The second instance, keyed by K_2, is used in conjunction with poly1305 to build an AEAD (Authenticated Encryption with Associated Data) that is used to encrypt and authenticate the entire packet. Two separate cipher instances are used here so as to keep the packet lengths confidential but not create an oracle for the packet payload cipher by decrypting and using the packet length prior to checking the MAC. By using an independently-keyed cipher instance to encrypt the length, an active attacker seeking to exploit the packet input handling as a decryption oracle can learn nothing about the payload contents or its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure). The AEAD is constructed as follows: for each packet, generate a Poly1305 key by taking the first 256 bits of ChaCha20 stream output generated using K_2, an IV consisting of the packet sequence number encoded as an uint64 under the SSH wire encoding rules and a ChaCha20 block counter of zero. The K_2 ChaCha20 block counter is then set to the little-endian encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used for encryption of the packet payload. Packet Handling --------------- When receiving a packet, the length must be decrypted first. When 4 bytes of ciphertext length have been received, they may be decrypted using the K_1 key, a nonce consisting of the packet sequence number encoded as a uint64 under the usual SSH wire encoding and a zero block counter to obtain the plaintext length. Once the entire packet has been received, the MAC MUST be checked before decryption. A per-packet Poly1305 key is generated as described above and the MAC tag calculated using Poly1305 with this key over the ciphertext of the packet length and the payload together. The calculated MAC is then compared in constant time with the one appended to the packet and the packet decrypted using ChaCha20 as described above (with K_2, the packet sequence number as nonce and a starting block counter of 1). To send a packet, first encode the 4 byte length and encrypt it using K_1. Encrypt the packet payload (using K_2) and append it to the encrypted length. Finally, calculate a MAC tag and append it. Rekeying -------- ChaCha20 must never reuse a {key, nonce} for encryption nor may it be used to encrypt more than 2^70 bytes under the same {key, nonce}. The SSH Transport protocol (RFC4253) recommends a far more conservative rekeying every 1GB of data sent or received. If this recommendation is followed, then chacha20-poly1305@openssh.com requires no special handling in this area. References ---------- [1] "ChaCha, a variant of Salsa20", Daniel Bernstein http://cr.yp.to/chacha/chacha-20080128.pdf [2] "The Poly1305-AES message-authentication code", Daniel Bernstein http://cr.yp.to/mac/poly1305-20050329.pdf [3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 $OpenBSD: PROTOCOL.chacha20poly1305,v 1.5 2020/02/21 00:04:43 dtucker Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.key100644 001750 001750 0000000003614775415623 0015127xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.key010064400017500001750000000031221477541562300135100ustar00djmdjmThis document describes the private key format for OpenSSH. 1. Overall format The key consists of a header, a list of public keys, and an encrypted list of matching private keys. #define AUTH_MAGIC "openssh-key-v1" byte[] AUTH_MAGIC string ciphername string kdfname string kdfoptions uint32 number of keys N string publickey1 string publickey2 ... string publickeyN string encrypted, padded list of private keys 2. KDF options for kdfname "bcrypt" The options: string salt uint32 rounds are concatenated and represented as a string. 3. Unencrypted list of N private keys The list of privatekey/comment pairs is padded with the bytes 1, 2, 3, ... until the total length is a multiple of the cipher block size. uint32 checkint uint32 checkint byte[] privatekey1 string comment1 byte[] privatekey2 string comment2 ... byte[] privatekeyN string commentN byte 1 byte 2 byte 3 ... byte padlen % 255 where each private key is encoded using the same rules as used for SSH agent. Before the key is encrypted, a random integer is assigned to both checkint fields so successful decryption can be quickly checked by verifying that both checkint fields hold the same value. 4. Encryption The KDF is used to derive a key, IV (and other values required by the cipher) from the passphrase. These values are then used to encrypt the unencrypted list of private keys. 5. No encryption For unencrypted keys the cipher "none" and the KDF "none" are used with empty passphrases. The options if the KDF "none" are the empty string. $OpenBSD: PROTOCOL.key,v 1.4 2024/03/30 05:56:22 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.krl100644 001750 001750 0000000003614775415623 0015127xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.krl010064400017500001750000000155751477541562300135270ustar00djmdjmThis describes the key/certificate revocation list format for OpenSSH. 1. Overall format The KRL consists of a header and zero or more sections. The header is: #define KRL_MAGIC 0x5353484b524c0a00ULL /* "SSHKRL\n\0" */ #define KRL_FORMAT_VERSION 1 uint64 KRL_MAGIC uint32 KRL_FORMAT_VERSION uint64 krl_version uint64 generated_date uint64 flags string reserved string comment Where "krl_version" is a version number that increases each time the KRL is modified, "generated_date" is the time in seconds since 1970-01-01 00:00:00 UTC that the KRL was generated, "comment" is an optional comment and "reserved" an extension field whose contents are currently ignored. No "flags" are currently defined. Following the header are zero or more sections, each consisting of: byte section_type string section_data Where "section_type" indicates the type of the "section_data". An exception to this is the KRL_SECTION_SIGNATURE section, that has a slightly different format (see below). The available section types are: #define KRL_SECTION_CERTIFICATES 1 #define KRL_SECTION_EXPLICIT_KEY 2 #define KRL_SECTION_FINGERPRINT_SHA1 3 #define KRL_SECTION_SIGNATURE 4 #define KRL_SECTION_FINGERPRINT_SHA256 5 #define KRL_SECTION_EXTENSION 255 2. Certificate section These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by serial number or key ID. The consist of the CA key that issued the certificates to be revoked and a reserved field whose contents is currently ignored. string ca_key string reserved Where "ca_key" is the standard SSH wire serialisation of the CA's public key. Alternately, "ca_key" may be an empty string to indicate the certificate section applies to all CAs (this is most useful when revoking key IDs). Followed by one or more sections: byte cert_section_type string cert_section_data The certificate section types are: #define KRL_SECTION_CERT_SERIAL_LIST 0x20 #define KRL_SECTION_CERT_SERIAL_RANGE 0x21 #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 #define KRL_SECTION_CERT_KEY_ID 0x23 #define KRL_SECTION_CERT_EXTENSION 0x39 2.1 Certificate serial list section This section is identified as KRL_SECTION_CERT_SERIAL_LIST. It revokes certificates by listing their serial numbers. The cert_section_data in this case contains: uint64 revoked_cert_serial uint64 ... This section may appear multiple times. 2.2. Certificate serial range section These sections use type KRL_SECTION_CERT_SERIAL_RANGE and hold a range of serial numbers of certificates: uint64 serial_min uint64 serial_max All certificates in the range serial_min <= serial <= serial_max are revoked. This section may appear multiple times. 2.3. Certificate serial bitmap section Bitmap sections use type KRL_SECTION_CERT_SERIAL_BITMAP and revoke keys by listing their serial number in a bitmap. uint64 serial_offset mpint revoked_keys_bitmap A bit set at index N in the bitmap corresponds to revocation of a keys with serial number (serial_offset + N). This section may appear multiple times. 2.4. Revoked key ID sections KRL_SECTION_CERT_KEY_ID sections revoke particular certificate "key ID" strings. This may be useful in revoking all certificates associated with a particular identity, e.g. a host or a user. string key_id[0] ... This section must contain at least one "key_id". This section may appear multiple times. 2.5. Certificate Extension subsections This subsection type provides a generic extension mechanism to the certificates KRL section that may be used to provide optional or critical data. Extensions are stored in subsections of type KRL_SECTION_CERT_EXTENSION with the following contents: string extension_name boolean is_critical string extension_contents. Where "extension_name" describes the type of extension. It is recommended that user extensions follow "cert-name@domain.org" naming. The "is_critical" indicates whether this extension is mandatory or optional. If true, then any unsupported extension encountered should result in KRL parsing failure. If false, then it may be safely be ignored. The "extension_contents" contains the body of the extension. 3. Explicit key sections These sections, identified as KRL_SECTION_EXPLICIT_KEY, revoke keys (not certificates). They are less space efficient than serial numbers, but are able to revoke plain keys. string public_key_blob[0] .... This section must contain at least one "public_key_blob". The blob must be a raw key (i.e. not a certificate). This section may appear multiple times. 4. SHA1/SHA256 fingerprint sections 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 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. Extension sections This section type provides a generic extension mechanism to the KRL format that may be used to provide optional or critical data. Extensions are recorded in sections of type KRL_SECTION_EXTENSION with the following contents: string extension_name boolean is_critical string extension_contents. Where "extension_name" describes the type of extension. It is recommended that user extensions follow "name@domain.org" naming. The "is_critical" indicates whether this extension is mandatory or optional. If true, then any unsupported extension encountered should result in KRL parsing failure. If false, then it may be safely be ignored. The "extension_contents" contains the body of the extension. 6. KRL signature sections Note: KRL signatures are not supported by OpenSSH. OpenSSH >= 9.4 will refuse to load KRLs that contain signatures. We recommend the use of SSHSIG (`ssh-keygen -Y sign ...`) style signatures for KRLs instead. The KRL_SECTION_SIGNATURE section serves a different purpose to the 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" two string components instead of one. byte KRL_SECTION_SIGNATURE string signature_key string signature The signature is calculated over the entire KRL from the KRL_MAGIC to this subsection's "signature_key", including both and using the signature generation rules appropriate for the type of "signature_key". This section must appear last in the KRL. If multiple signature sections appear, they must appear consecutively at the end of the KRL file. 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.7 2023/07/17 04:01:10 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.mux100644 001750 001750 0000000003614775415623 0015150xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.mux010064400017500001750000000214451477541562300135410ustar00djmdjmThis document describes the multiplexing protocol used by ssh(1)'s ControlMaster connection-sharing. 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 multiplexing (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 client ssh(1), the first action of each is send a hello messages to its peer: uint32 MUX_MSG_HELLO uint32 protocol version string extension name [optional] string extension value [optional] ... 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 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 string reserved bool want tty flag bool want X11 forwarding flag bool want agent flag bool subsystem flag uint32 escape char string terminal type string command string environment string 0 [optional] ... To disable the use of an escape character, "escape char" may be set to 0xffffffff. "terminal type" is generally set to the value of $TERM. zero or more environment strings may follow the command. The client then sends its standard input, output and error file descriptors (in that order) using Unix domain socket control messages. The contents of "reserved" are currently ignored. If successful, the server will reply with MUX_S_SESSION_OPENED uint32 MUX_S_SESSION_OPENED uint32 client request id uint32 session id Otherwise it will reply with an error: MUX_S_PERMISSION_DENIED or MUX_S_FAILURE. Once the server has received the fds, it will respond with MUX_S_OK indicating that the session is up. The client now waits for the session to end. When it does, the server will send an exit status message: uint32 MUX_S_EXIT_MESSAGE uint32 session id uint32 exit value The client should exit with this value to mimic the behaviour of a non-multiplexed ssh(1) connection. Two additional cases that the client must cope with are it receiving a signal itself and the server disconnecting without sending an exit message. A master may also send a MUX_S_TTY_ALLOC_FAIL before MUX_S_EXIT_MESSAGE if remote TTY allocation was unsuccessful. The client may use this to return its local tty to "cooked" mode. uint32 MUX_S_TTY_ALLOC_FAIL uint32 session id 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: uint32 MUX_C_ALIVE_CHECK uint32 request id The server replies with: uint32 MUX_S_ALIVE uint32 client request id uint32 server pid 5. Remotely terminating a master A client may request that a master terminate immediately: uint32 MUX_C_TERMINATE uint32 request id The server will reply with one of MUX_S_OK or MUX_S_PERMISSION_DENIED. 6. Requesting establishment of port forwards A client may request the master to establish a port forward: uint32 MUX_C_OPEN_FWD uint32 request id uint32 forwarding type string listen host uint32 listen port string connect host uint32 connect port 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. For dynamically allocated listen port the server replies with uint32 MUX_S_REMOTE_PORT uint32 client request id uint32 allocated remote listen port 7. Requesting closure of port forwards A client may request the master to close a port forward: uint32 MUX_C_CLOSE_FWD uint32 request id uint32 forwarding type string listen host uint32 listen port string connect host uint32 connect port A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE. 8. Requesting shutdown of mux listener A client may request the master to stop accepting new multiplexing requests and remove its listener socket. uint32 MUX_C_STOP_LISTENING uint32 request id A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE. 9. Requesting proxy mode A client may request that the control connection be placed in proxy mode: uint32 MUX_C_PROXY uint32 request id When a mux master receives this message, it will reply with a confirmation: uint32 MUX_S_PROXY uint32 request id 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] ... 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: uint32 MUX_S_OK uint32 client request id The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: uint32 MUX_S_PERMISSION_DENIED uint32 client request id string reason uint32 MUX_S_FAILURE uint32 client request id string reason 11. Protocol numbers #define MUX_MSG_HELLO 0x00000001 #define MUX_C_NEW_SESSION 0x10000002 #define MUX_C_ALIVE_CHECK 0x10000004 #define MUX_C_TERMINATE 0x10000005 #define MUX_C_OPEN_FWD 0x10000006 #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 #define MUX_C_STOP_LISTENING 0x10000009 #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 #define MUX_S_EXIT_MESSAGE 0x80000004 #define MUX_S_ALIVE 0x80000005 #define MUX_S_SESSION_OPENED 0x80000006 #define MUX_S_REMOTE_PORT 0x80000007 #define MUX_S_TTY_ALLOC_FAIL 0x80000008 #define MUX_FWD_LOCAL 1 #define MUX_FWD_REMOTE 2 #define MUX_FWD_DYNAMIC 3 XXX TODO XXX extended status (e.g. report open channels / forwards) XXX lock (maybe) 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 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.14 2024/01/08 05:11:18 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.sshsig100644 001750 001750 0000000003614775415623 0015637xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.sshsig010064400017500001750000000065411477541562300142300ustar00djmdjmThis 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 RFC4253 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. $OpenBSD: PROTOCOL.sshsig,v 1.4 2020/08/31 00:17:41 djm Exp $ openssh-10.0p1/PaxHeaders.10889/PROTOCOL.u2f100644 001750 001750 0000000003614775415623 0015033xustar0030 atime=1744182234.462719264 openssh-10.0p1/PROTOCOL.u2f010064400017500001750000000255101477541562300134210ustar00djmdjmThis document describes OpenSSH's support for U2F/FIDO security keys. Background ---------- U2F is an open standard for two-factor authentication hardware, widely used for user authentication to websites. U2F tokens are ubiquitous, available from a number of manufacturers and are currently by far the cheapest way for users to achieve hardware-backed credential storage. The U2F protocol however cannot be trivially used as an SSH protocol key type as both the inputs to the signature operation and the resultant signature differ from those specified for SSH. For similar reasons, integration of U2F devices cannot be achieved via the PKCS#11 API. U2F also offers a number of features that are attractive in the context of SSH authentication. They can be configured to require indication of "user presence" for each signature operation (typically achieved by requiring the user touch the key). They also offer an attestation mechanism at key enrollment time that can be used to prove that a given key is backed by hardware. Finally the signature format includes a monotonic signature counter that can be used (at scale) to detect concurrent use of a private key, should it be extracted from hardware. U2F private keys are generated through an enrollment operation, which takes an application ID - a URL-like string, typically "ssh:" in this case, but a HTTP origin for the case of web authentication, and a challenge string (typically randomly generated). The enrollment operation returns a public key, a key handle that must be used to invoke the hardware-backed private key, some flags and signed attestation information that may be used to verify that a private key is hosted on a particular hardware instance. It is common for U2F hardware to derive private keys from the key handle in conjunction with a small per-device secret that is unique to the hardware, thus requiring little on-device storage for an effectively unlimited number of supported keys. This drives the requirement that the key handle be supplied for each signature operation. U2F tokens primarily use ECDSA signatures in the NIST-P256 field, though the FIDO2 standard specifies additional key types, including one based on Ed25519. Use of U2F security keys does not automatically imply multi-factor authentication. From sshd's perspective, a security key constitutes a single factor of authentication, even if protected by a PIN or biometric authentication. To enable multi-factor authentication in ssh, please refer to the AuthenticationMethods option in sshd_config(5). SSH U2F Key formats ------------------- OpenSSH integrates U2F as new key and corresponding certificate types: sk-ecdsa-sha2-nistp256@openssh.com sk-ecdsa-sha2-nistp256-cert-v01@openssh.com sk-ssh-ed25519@openssh.com sk-ssh-ed25519-cert-v01@openssh.com While each uses ecdsa-sha256-nistp256 as the underlying signature primitive, keys require extra information in the public and private keys, and in the signature object itself. As such they cannot be made compatible with the existing ecdsa-sha2-nistp* key types. The format of a sk-ecdsa-sha2-nistp256@openssh.com public key is: string "sk-ecdsa-sha2-nistp256@openssh.com" string curve name ec_point Q string application (user-specified, but typically "ssh:") The corresponding private key contains: string "sk-ecdsa-sha2-nistp256@openssh.com" string curve name ec_point Q string application (user-specified, but typically "ssh:") uint8 flags string key_handle string reserved The format of a sk-ssh-ed25519@openssh.com public key is: string "sk-ssh-ed25519@openssh.com" string public key string application (user-specified, but typically "ssh:") With a private half consisting of: string "sk-ssh-ed25519@openssh.com" string public key string application (user-specified, but typically "ssh:") uint8 flags string key_handle string reserved The certificate form for SSH U2F keys appends the usual certificate information to the public key: string "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" string nonce string curve name ec_point Q string application uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before string critical options string extensions string reserved string signature key string signature and for security key ed25519 certificates: string "sk-ssh-ed25519-cert-v01@openssh.com" string nonce string public key string application uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before string critical options string extensions string reserved string signature key string signature Both security key certificates use the following encoding for private keys: string type (e.g. "sk-ssh-ed25519-cert-v01@openssh.com") string pubkey (the above key/cert structure) string application uint8 flags string key_handle string reserved During key generation, the hardware also returns attestation information that may be used to cryptographically prove that a given key is hardware-backed. Unfortunately, the protocol required for this proof is not privacy-preserving and may be used to identify U2F tokens with at least manufacturer and batch number granularity. For this reason, we choose not to include this information in the public key or save it by default. Attestation information is useful for out-of-band key and certificate registration workflows, e.g. proving to a CA that a key is backed by trusted hardware before it will issue a certificate. To support this case, OpenSSH optionally allows retaining the attestation information at the time of key generation. It will take the following format: string "ssh-sk-attest-v01" string attestation certificate string enrollment signature string authenticator data (CBOR encoded) uint32 reserved flags string reserved string A previous version of this format, emitted prior to OpenSSH 8.4 omitted the authenticator data. string "ssh-sk-attest-v00" string attestation certificate string enrollment signature uint32 reserved flags string reserved string OpenSSH treats the attestation certificate and enrollment signatures as opaque objects and does no interpretation of them itself. SSH U2F signatures ------------------ In addition to the message to be signed, the U2F signature operation requires the key handle and a few additional parameters. The signature is signed over a blob that consists of: byte[32] SHA256(application) byte flags (including "user present", extensions present) uint32 counter byte[] extensions byte[32] SHA256(message) No extensions are yet defined for SSH use. If any are defined in the future, it will be possible to infer their presence from the contents of the "flags" value. The signature returned from U2F hardware takes the following format: byte flags (including "user present") uint32 counter byte[] ecdsa_signature (in X9.62 format). For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1 format data in the pre-authentication attack surface. Therefore, the signature format used on the wire in SSH2_USERAUTH_REQUEST packets will be reformatted to better match the existing signature encoding: string "sk-ecdsa-sha2-nistp256@openssh.com" string ecdsa_signature byte flags uint32 counter Where the "ecdsa_signature" field follows the RFC5656 ECDSA signature encoding: mpint r mpint s For Ed25519 keys the signature is encoded as: string "sk-ssh-ed25519@openssh.com" string signature byte flags uint32 counter webauthn signatures ------------------- The W3C/FIDO webauthn[1] standard defines a mechanism for a web browser to interact with FIDO authentication tokens. This standard builds upon the FIDO standards, but requires different signature contents to raw FIDO messages. OpenSSH supports ECDSA/p256 webauthn signatures through the "webauthn-sk-ecdsa-sha2-nistp256@openssh.com" signature algorithm. The wire encoding for a webauthn-sk-ecdsa-sha2-nistp256@openssh.com signature is similar to the sk-ecdsa-sha2-nistp256@openssh.com format: string "webauthn-sk-ecdsa-sha2-nistp256@openssh.com" string ecdsa_signature byte flags uint32 counter string origin string clientData string extensions Where "origin" is the HTTP origin making the signature, "clientData" is the JSON-like structure signed by the browser and "extensions" are any extensions used in making the signature. [1] https://www.w3.org/TR/webauthn-2/ ssh-agent protocol extensions ----------------------------- ssh-agent requires a protocol extension to support U2F keys. At present the closest analogue to Security Keys in ssh-agent are PKCS#11 tokens, insofar as they require a middleware library to communicate with the device that holds the keys. Unfortunately, the protocol message used to add PKCS#11 keys to ssh-agent does not include any way to send the key handle to the agent as U2F keys require. To avoid this, without having to add wholly new messages to the agent protocol, we will use the existing SSH2_AGENTC_ADD_ID_CONSTRAINED message with a new key constraint extension to encode a path to the middleware library for the key. The format of this constraint extension would be: byte SSH_AGENT_CONSTRAIN_EXTENSION string sk-provider@openssh.com string middleware path This constraint-based approach does not present any compatibility problems. OpenSSH integration ------------------- U2F tokens may be attached via a number of means, including USB and NFC. The USB interface is standardised around a HID protocol, but we want to be able to support other transports as well as dummy implementations for regress testing. For this reason, OpenSSH shall support a dynamically- loaded middleware libraries to communicate with security keys, but offer support for the common case of USB HID security keys internally. The middleware library need only expose a handful of functions and numbers listed in sk-api.h. Included in the defined numbers is a SSH_SK_VERSION_MAJOR that should be incremented for each incompatible API change. miscellaneous options may be passed to the middleware as a NULL- terminated array of pointers to struct sk_option. The middleware may ignore unsupported or unknown options unless the "required" flag is set, in which case it should return failure if an unsupported option is requested. At present the following options names are supported: "device" Specifies a specific FIDO device on which to perform the operation. The value in this field is interpreted by the middleware but it would be typical to specify a path to a /dev node for the device in question. "user" Specifies the FIDO2 username used when enrolling a key, overriding OpenSSH's default of using an all-zero username. In OpenSSH, the middleware will be invoked by using a similar mechanism to ssh-pkcs11-helper to provide address-space containment of the middleware from ssh-agent. $OpenBSD: PROTOCOL.u2f,v 1.26 2020/09/09 03:08:01 djm Exp $ openssh-10.0p1/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0014034xustar0030 atime=1744182234.463696283 openssh-10.0p1/README010064400017500001750000000037361477541562300124300ustar00djmdjmSee https://www.openssh.com/releasenotes.html#10.0p1 for the release notes. Please read https://www.openssh.com/report.html for bug reporting instructions and note that we do not use Github for bug reporting. This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other Unices. OpenSSH is based on the last free version of Tatu Ylonen's sample implementation with all patent-encumbered algorithms removed (to external libraries), all known security bugs fixed, new features reintroduced and many other clean-ups. OpenSSH was created by Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt, and Dug Song, and has been developed and maintained by Andre Lucas, Ben Lindstom, Damien Miller, Darren Tucker and Tim Rice. It has a homepage at https://www.openssh.com/ This port consists of the re-introduction of autoconf support, PAM support, EGD/PRNGD support and replacements for OpenBSD library functions that are (regrettably) absent from other unices. This port has been best tested on AIX, Cygwin, HP-UX, Linux, MacOS/X, FreeBSD, NetBSD, OpenBSD, OpenServer, Solaris and UnixWare. This version actively tracks changes in the OpenBSD CVS repository. There is now several mailing lists for this port of OpenSSH. Please refer to https://www.openssh.com/list.html for details on how to join. Please send bug reports and patches to 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 dependencies and how to install OpenSSH on your system. Damien Miller Miscellania - This version of OpenSSH is based upon code retrieved from the OpenBSD CVS repository which in turn was based on the last free sample implementation released by Tatu Ylonen. References - [0] https://www.openssh.com/ [1] https://man.openbsd.org/style.9 openssh-10.0p1/PaxHeaders.10889/README.dns100644 001750 001750 0000000003614775415623 0014617xustar0030 atime=1744182234.463696283 openssh-10.0p1/README.dns010064400017500001750000000031171477541562300132040ustar00djmdjmHow to verify host keys using OpenSSH and DNS --------------------------------------------- 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 To create a DNS resource record (RR) containing a fingerprint of the public host key, use the following command: ssh-keygen -r hostname -f keyfile -g where "hostname" is your fully qualified hostname and "keyfile" is the file containing the public host key file. If you have multiple keys, you should generate one RR for each key. In the example above, ssh-keygen will print the fingerprint in a generic DNS RR format parsable by most modern name server implementations. If your nameserver has support for the SSHFP RR you can omit the -g flag and ssh-keygen will print a standard SSHFP RR. To publish the fingerprint using the DNS you must add the generated RR to your DNS zone file and sign your zone. (2) Client: Enable ssh to verify host keys using DNS To enable the ssh client to verify host keys using DNS, you have to add the following option to the ssh configuration file ($HOME/.ssh/config or /etc/ssh/ssh_config): VerifyHostKeyDNS yes Upon connection the client will try to look up the fingerprint RR using DNS. If the fingerprint received from the DNS server matches the remote host key, the user will be notified. Jakob Schlyter Wesley Griffin $OpenBSD: README.dns,v 1.2 2003/10/14 19:43:23 jakob Exp $ openssh-10.0p1/PaxHeaders.10889/README.md100644 001750 001750 0000000003614775415623 0014433xustar0030 atime=1744182234.463696283 openssh-10.0p1/README.md010064400017500001750000000122401477541562300130150ustar00djmdjm# Portable OpenSSH [![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:openssh) [![Coverity Status](https://scan.coverity.com/projects/21341/badge.svg)](https://scan.coverity.com/projects/openssh-portable) 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. ``libcrypto`` from either [LibreSSL](https://www.libressl.org/) or [OpenSSL](https://www.openssl.org) may also be used. OpenSSH may be built without either of these, but the resulting binaries will have only a subset of the cryptographic algorithms normally available. [zlib](https://www.zlib.net/) is optional; without it transport compression is not supported. FIDO security token support needs [libfido2](https://github.com/Yubico/libfido2) and its dependencies and will be enabled automatically if they are found. In addition, certain platforms and build-time options may require additional dependencies; see README.platform for details about your platform. ### Building a release Release tarballs and release branches in git 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 the git master branch, 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. ## 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). openssh-10.0p1/PaxHeaders.10889/README.platform100644 001750 001750 0000000003614775415623 0015657xustar0030 atime=1744182234.463696283 openssh-10.0p1/README.platform010064400017500001750000000077611477541562300142550ustar00djmdjmThis file contains notes about OpenSSH on specific platforms. AIX Beginning with OpenSSH 3.8p1, sshd will honour an account's password expiry settings, where prior to that it did not. Because of this, it's possible for sites that have used OpenSSH's sshd exclusively to have accounts which have passwords expired longer than the inactive time (ie the "Weeks between password EXPIRATION and LOCKOUT" setting in SMIT or the maxexpired chuser attribute). Accounts in this state must have their passwords reset manually by the administrator. As a precaution, it is recommended that the administrative passwords be reset before upgrading from OpenSSH <3.8. As of OpenSSH 4.0p1, configure will attempt to detect if your version and maintenance level of AIX has a working getaddrinfo, and will use it if found. This will enable IPv6 support. If for some reason configure gets it wrong, or if you want to build binaries to work on earlier MLs than the build host then you can add "-DBROKEN_GETADDRINFO" to CFLAGS to force the previous IPv4-only behaviour. IPv6 known to work: 5.1ML7 5.2ML2 5.2ML5 IPv6 known broken: 4.3.3ML11 5.1ML4 If you wish to use dynamic libraries that aren't in the normal system locations (eg IBM's OpenSSL and zlib packages) then you will need to define the environment variable blibpath before running configure, eg blibpath=/lib:/usr/lib:/opt/freeware/lib ./configure \ --with-ssl-dir=/opt/freeware --with-zlib=/opt/freeware If sshd is built with the WITH_AIXAUTHENTICATE option (which is enabled by default) then sshd checks that users are permitted via the 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 ------ To build on Cygwin, OpenSSH requires the following packages: gcc, gcc-mingw-core, mingw-runtime, binutils, make, openssl, openssl-devel, zlib, minres, minires-devel. Darwin and MacOS X ------------------ Darwin does not provide a tun(4) driver required for OpenSSH-based virtual private networks. The BSD manpage still exists, but the driver has been removed in recent releases of Darwin and MacOS X. Tunnel support is known to work with Darwin 8 and MacOS X 10.4 in Point-to-Point (Layer 3) and Ethernet (Layer 2) mode using a third party driver. More information is available at: https://tuntaposx.sourceforge.net Recent Darwin/MacOS X versions are likely unsupported. Linux ----- Some Linux distributions (including Red Hat/Fedora/CentOS) include headers and library links in the -devel RPMs rather than the main binary RPMs. If you get an error about headers, or complaining about a missing prerequisite then you may need to install the equivalent development packages. On Redhat based distros these may be openssl-devel, zlib-devel and pam-devel, on Debian based distros these may be libssl-dev, libz-dev and libpam-dev. Solaris ------- If you enable BSM auditing on Solaris, you need to update audit_event(4) for praudit(1m) to give sensible output. The following line needs to be 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 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. Platforms using PAM ------------------- As of OpenSSH 4.3p1, sshd will no longer check /etc/nologin itself when PAM is enabled. To maintain existing behaviour, pam_nologin should be 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. openssh-10.0p1/PaxHeaders.10889/README.privsep100644 001750 001750 0000000003614775415623 0015523xustar0030 atime=1744182234.463696283 openssh-10.0p1/README.privsep010064400017500001750000000042501477541562300141070ustar00djmdjmPrivilege separation, or privsep, is method in OpenSSH by which operations that require root privilege are performed by a separate privileged monitor process. Its purpose is to prevent privilege 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 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 preauth environment: # mkdir /var/empty # chown root:sys /var/empty # chmod 755 /var/empty # groupadd sshd # useradd -g sshd -c 'sshd privsep' -d /var/empty -s /bin/false sshd /var/empty should not contain any files. configure supports the following options to change the default 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 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 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 will require 1 additional process per login session. Given the following process listing (from HP-UX): UID PID PPID C STIME TTY TIME COMMAND root 1005 1 0 10:45:17 ? 0:08 /opt/openssh/sbin/sshd -u0 root 6917 1005 0 15:19:16 ? 0:00 sshd: stevesk [priv] stevesk 6919 6917 0 15:19:17 ? 0:03 sshd: stevesk@2 stevesk 6921 6919 0 15:19:17 pts/2 0:00 -bash 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. openssh-10.0p1/PaxHeaders.10889/README.tun100644 001750 001750 0000000003614775415623 0014641xustar0030 atime=1744182234.463696283 openssh-10.0p1/README.tun010064400017500001750000000114321477541562300132250ustar00djmdjmHow to use OpenSSH-based virtual private networks ------------------------------------------------- OpenSSH contains support for VPN tunneling using the tun(4) network tunnel pseudo-device which is available on most platforms, either for layer 2 or 3 traffic. The following brief instructions on how to use this feature use a network configuration specific to the OpenBSD operating system. (1) Server: Enable support for SSH tunneling To enable the ssh server to accept tunnel requests from the client, you have to add the following option to the ssh server configuration file (/etc/ssh/sshd_config): PermitTunnel yes Restart the server or send the hangup signal (SIGHUP) to let the server reread it's configuration. (2) Server: Restrict client access and assign the tunnel The OpenSSH server simply uses the file /root/.ssh/authorized_keys to restrict the client to connect to a specified tunnel and to automatically start the related interface configuration command. These settings are optional but recommended: tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... reyk@openbsd.org (3) Client: Configure the local network tunnel interface Use the hostname.if(5) interface-specific configuration file to set up the network tunnel configuration with OpenBSD. For example, use the following configuration in /etc/hostname.tun0 to set up the layer 3 tunnel on the client: inet 192.168.5.1 255.255.255.252 192.168.5.2 OpenBSD also supports layer 2 tunneling over the tun device by adding the link0 flag: inet 192.168.1.78 255.255.255.0 192.168.1.255 link0 Layer 2 tunnels can be used in combination with an Ethernet bridge(4) interface, like the following example for /etc/bridgename.bridge0: add tun0 add sis0 up (4) Client: Configure the OpenSSH client To establish tunnel forwarding for connections to a specified remote host by default, use the following ssh client configuration for the privileged user (in /root/.ssh/config): Host sshgateway Tunnel yes TunnelDevice 0:any PermitLocalCommand yes LocalCommand sh /etc/netstart tun0 A more complicated configuration is possible to establish a tunnel to a remote host which is not directly accessible by the client. The following example describes a client configuration to connect to the remote host over two ssh hops in between. It uses the OpenSSH ProxyCommand in combination with the nc(1) program to forward the final ssh tunnel destination over multiple ssh sessions. Host access.somewhere.net User puffy Host dmzgw User puffy ProxyCommand ssh access.somewhere.net nc dmzgw 22 Host sshgateway Tunnel Ethernet TunnelDevice 0:any PermitLocalCommand yes LocalCommand sh /etc/netstart tun0 ProxyCommand ssh dmzgw nc sshgateway 22 The following network plan illustrates the previous configuration in combination with layer 2 tunneling and Ethernet bridging. +--------+ ( ) +----------------------+ | Client |------( Internet )-----| access.somewhere.net | +--------+ ( ) +----------------------+ : 192.168.1.78 | :............................. +-------+ Forwarded ssh connection : | dmzgw | Layer 2 tunnel : +-------+ : | : | : +------------+ :......| sshgateway | | +------------+ --- real connection Bridge -> | +----------+ ... "virtual connection" [ X ]--------| somehost | [X] switch +----------+ 192.168.1.25 (5) Client: Connect to the server and establish the tunnel Finally connect to the OpenSSH server to establish the tunnel by using the following command: ssh sshgateway It is also possible to tell the client to fork into the background after the connection has been successfully established: ssh -f sshgateway true Without the ssh configuration done in step (4), it is also possible to use the following command lines: ssh -fw 0:1 sshgateway true ifconfig tun0 192.168.5.1 192.168.5.2 netmask 255.255.255.252 Using OpenSSH tunnel forwarding is a simple way to establish secure and ad hoc virtual private networks. Possible fields of application could be wireless networks or administrative VPN tunnels. Nevertheless, ssh tunneling requires some packet header overhead and runs on top of TCP. It is still suggested to use the IP Security Protocol (IPSec) for robust and permanent VPN connections and to interconnect corporate networks. Reyk Floeter $OpenBSD: README.tun,v 1.4 2006/03/28 00:12:31 deraadt Exp $ openssh-10.0p1/PaxHeaders.10889/SECURITY.md100644 001750 001750 0000000003614775415623 0014745xustar0030 atime=1744182234.463696283 openssh-10.0p1/SECURITY.md010064400017500001750000000002431477541562300133270ustar00djmdjm# Reporting OpenSSH Security Issues To report security issues in OpenSSH, please refer to our website [OpenSSH Security](https://www.openssh.com/security.html). openssh-10.0p1/PaxHeaders.10889/TODO100644 001750 001750 0000000003614775415623 0013644xustar0030 atime=1744182234.463696283 openssh-10.0p1/TODO010064400017500001750000000050501477541562300122270ustar00djmdjmDocumentation: - Update the docs - Update README - Update INSTALL - Merge INSTALL & README.privsep - Install FAQ? - General FAQ on S/Key, TIS, RSA, RSA2, DSA, etc and suggestions on when it would be best to use them. - Create a Documentation/ directory? Programming: - Grep for 'XXX' comments and fix - Link order is incorrect for some systems using Kerberos 4 and AFS. Result is multiple inclusion of DES symbols. Holger Trapp reports that changing the configure generated link order from: -lresolv -lkrb -lz -lnsl -lutil -lkafs -lkrb -ldes -lcrypto to: -lresolv -lkrb -lz -lnsl -lutil -lcrypto -lkafs -lkrb -ldes fixing the problem. - Write a test program that calls stat() to search for EGD/PRNGd socket rather than use the (non-portable) "test -S". - More platforms for for setproctitle() emulation (testing needed) - Improve PAM ChallengeResponseAuthentication - Informational messages - 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 pam" - Complete Tru64 SIA support - It looks like we could merge it into the password auth code to cut down on diff size. Maybe PAM password auth too? - Finish integrating kernel-level auditing code for IRIX and SOLARIS (Gilbert.r.loomis@saic.com) - 64-bit builds on HP-UX 11.X (stevesk@pobox.com): - utmp/wtmp get corrupted (something in loginrec?) - can't build with PAM (no 64-bit libpam yet) Clean up configure/makefiles: - Clean up configure.ac - There are a few double #defined variables left to do. HAVE_LOGIN is one of them. Consider NOT looking for information in wtmpx or utmpx or any of that stuff if it's not detected from the start - 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 separate test to allow people to (right/wrongfully) link against Bind directly. - 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. Packaging: - HP-UX: Provide DEPOT package scripts. (gilbert.r.loomis@saic.com) PrivSep Issues: - PAM + See above PAM notes - AIX + usrinfo() does not set TTY, but only required for legacy systems. Works with PrivSep. - OSF + SIA is broken - Cygwin + Privsep for Pre-auth only (no fd passing) openssh-10.0p1/PaxHeaders.10889/aclocal.m4100644 001750 001750 0000000003614775415623 0015014xustar0030 atime=1744182234.463696283 openssh-10.0p1/aclocal.m4010064400017500001750000000012661477541562300134040ustar00djmdjm# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_include([m4/openssh.m4]) openssh-10.0p1/PaxHeaders.10889/addr.c100644 001750 001750 0000000003614775415623 0014232xustar0030 atime=1744182234.464672479 openssh-10.0p1/addr.c010064400017500001750000000241341477541562300126210ustar00djmdjm/* $OpenBSD: addr.c,v 1.9 2024/10/18 04:30:09 djm Exp $ */ /* * Copyright (c) 2004-2008 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include "addr.h" #define _SA(x) ((struct sockaddr *)(x)) static int addr_unicast_masklen(int af) { switch (af) { case AF_INET: return 32; case AF_INET6: return 128; default: return -1; } } static inline int masklen_valid(int af, u_int masklen) { switch (af) { case AF_INET: return masklen <= 32 ? 0 : -1; case AF_INET6: return masklen <= 128 ? 0 : -1; default: return -1; } } static int addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len, u_int16_t port) { struct sockaddr_in *in4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; if (xa == NULL || sa == NULL || len == NULL) return -1; switch (xa->af) { case AF_INET: if (*len < sizeof(*in4)) return -1; memset(sa, '\0', sizeof(*in4)); *len = sizeof(*in4); #ifdef SOCK_HAS_LEN in4->sin_len = sizeof(*in4); #endif in4->sin_family = AF_INET; in4->sin_port = htons(port); memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr)); break; case AF_INET6: if (*len < sizeof(*in6)) return -1; memset(sa, '\0', sizeof(*in6)); *len = sizeof(*in6); #ifdef SOCK_HAS_LEN in6->sin6_len = sizeof(*in6); #endif in6->sin6_family = AF_INET6; in6->sin6_port = htons(port); memcpy(&in6->sin6_addr, &xa->v6, sizeof(in6->sin6_addr)); #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID in6->sin6_scope_id = xa->scope_id; #endif break; default: return -1; } return 0; } /* * Convert struct sockaddr to struct xaddr * Returns 0 on success, -1 on failure. */ int addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa) { struct sockaddr_in *in4 = (struct sockaddr_in *)sa; struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; memset(xa, '\0', sizeof(*xa)); switch (sa->sa_family) { case AF_INET: if (slen < (socklen_t)sizeof(*in4)) return -1; xa->af = AF_INET; memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4)); break; case AF_INET6: if (slen < (socklen_t)sizeof(*in6)) return -1; xa->af = AF_INET6; memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6)); #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID xa->scope_id = in6->sin6_scope_id; #endif break; default: return -1; } return 0; } static int addr_invert(struct xaddr *n) { int i; if (n == NULL) return -1; switch (n->af) { case AF_INET: n->v4.s_addr = ~n->v4.s_addr; return 0; case AF_INET6: for (i = 0; i < 4; i++) n->addr32[i] = ~n->addr32[i]; return 0; default: return -1; } } /* * Calculate a netmask of length 'l' for address family 'af' and * store it in 'n'. * Returns 0 on success, -1 on failure. */ int addr_netmask(int af, u_int l, struct xaddr *n) { int i; if (masklen_valid(af, l) != 0 || n == NULL) return -1; memset(n, '\0', sizeof(*n)); switch (af) { case AF_INET: n->af = AF_INET; if (l == 0) return 0; n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); return 0; case AF_INET6: n->af = AF_INET6; for (i = 0; i < 4 && l >= 32; i++, l -= 32) n->addr32[i] = 0xffffffffU; if (i < 4 && l != 0) n->addr32[i] = htonl((0xffffffff << (32 - l)) & 0xffffffff); return 0; default: return -1; } } static int addr_hostmask(int af, u_int l, struct xaddr *n) { if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1) return -1; return 0; } /* * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'. * Returns 0 on success, -1 on failure. */ int addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) { int i; if (dst == NULL || a == NULL || b == NULL || a->af != b->af) return -1; memcpy(dst, a, sizeof(*dst)); switch (a->af) { case AF_INET: dst->v4.s_addr &= b->v4.s_addr; return 0; case AF_INET6: dst->scope_id = a->scope_id; for (i = 0; i < 4; i++) dst->addr32[i] &= b->addr32[i]; return 0; default: return -1; } } static int addr_or(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) { int i; if (dst == NULL || a == NULL || b == NULL || a->af != b->af) return (-1); memcpy(dst, a, sizeof(*dst)); switch (a->af) { case AF_INET: dst->v4.s_addr |= b->v4.s_addr; return (0); case AF_INET6: for (i = 0; i < 4; i++) dst->addr32[i] |= b->addr32[i]; return (0); default: return (-1); } } int addr_cmp(const struct xaddr *a, const struct xaddr *b) { int i; if (a->af != b->af) return (a->af == AF_INET6 ? 1 : -1); switch (a->af) { case AF_INET: /* * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is * too big to fit into a signed int */ if (a->v4.s_addr == b->v4.s_addr) return 0; return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1); case AF_INET6: /* * Do this a byte at a time to avoid the above issue and * any endian problems */ for (i = 0; i < 16; i++) if (a->addr8[i] - b->addr8[i] != 0) return (a->addr8[i] - b->addr8[i]); if (a->scope_id == b->scope_id) return (0); return (a->scope_id > b->scope_id ? 1 : -1); default: return (-1); } } static int addr_is_all0s(const struct xaddr *a) { int i; switch (a->af) { case AF_INET: return (a->v4.s_addr == 0 ? 0 : -1); case AF_INET6: for (i = 0; i < 4; i++) if (a->addr32[i] != 0) return -1; return 0; default: return -1; } } /* Increment the specified address. Note, does not do overflow checking */ void addr_increment(struct xaddr *a) { int i; uint32_t n; switch (a->af) { case AF_INET: a->v4.s_addr = htonl(ntohl(a->v4.s_addr) + 1); break; case AF_INET6: for (i = 0; i < 4; i++) { /* Increment with carry */ n = ntohl(a->addr32[3 - i]) + 1; a->addr32[3 - i] = htonl(n); if (n != 0) break; } break; } } /* * Test whether host portion of address 'a', as determined by 'masklen' * is all zeros. * Returns 0 if host portion of address is all-zeros, * -1 if not all zeros or on failure. */ static int addr_host_is_all0s(const struct xaddr *a, u_int masklen) { struct xaddr tmp_addr, tmp_mask, tmp_result; memcpy(&tmp_addr, a, sizeof(tmp_addr)); if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) return -1; if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1) return -1; return addr_is_all0s(&tmp_result); } #if 0 static int addr_host_to_all0s(struct xaddr *a, u_int masklen) { struct xaddr tmp_mask; if (addr_netmask(a->af, masklen, &tmp_mask) == -1) return (-1); if (addr_and(a, a, &tmp_mask) == -1) return (-1); return (0); } #endif int addr_host_to_all1s(struct xaddr *a, u_int masklen) { struct xaddr tmp_mask; if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) return (-1); if (addr_or(a, a, &tmp_mask) == -1) return (-1); return (0); } /* * Parse string address 'p' into 'n'. * Returns 0 on success, -1 on failure. */ int addr_pton(const char *p, struct xaddr *n) { struct addrinfo hints, *ai; memset(&hints, '\0', sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) return -1; if (ai == NULL) return -1; if (ai->ai_addr == NULL) { freeaddrinfo(ai); return -1; } if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) { freeaddrinfo(ai); return -1; } freeaddrinfo(ai); return 0; } #if 0 static int addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen) { struct addrinfo hints, *ai; memset(&hints, '\0', sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0) return -1; if (ai == NULL) return -1; if (ai->ai_addr == NULL) { freeaddrinfo(ai); return -1; } if (sa != NULL) { if (slen < ai->ai_addrlen) { freeaddrinfo(ai); return -1; } memcpy(sa, &ai->ai_addr, ai->ai_addrlen); } freeaddrinfo(ai); return 0; } #endif int addr_ntop(const struct xaddr *n, char *p, size_t len) { struct sockaddr_storage ss; socklen_t slen = sizeof(ss); if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1) return -1; if (p == NULL || len == 0) return -1; if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0, NI_NUMERICHOST) != 0) return -1; return 0; } /* * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z). * Return -1 on parse error, -2 on inconsistency or 0 on success. */ int addr_pton_cidr(const char *p, struct xaddr *n, u_int *l) { struct xaddr tmp; u_int masklen = 999; char addrbuf[64], *mp; const char *errstr; /* Don't modify argument */ if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf)) return -1; if ((mp = strchr(addrbuf, '/')) != NULL) { *mp = '\0'; mp++; masklen = (u_int)strtonum(mp, 0, INT_MAX, &errstr); if (errstr) return -1; } if (addr_pton(addrbuf, &tmp) == -1) return -1; if (mp == NULL) masklen = addr_unicast_masklen(tmp.af); if (masklen_valid(tmp.af, masklen) == -1) return -2; if (addr_host_is_all0s(&tmp, masklen) != 0) return -2; if (n != NULL) memcpy(n, &tmp, sizeof(*n)); if (l != NULL) *l = masklen; return 0; } int addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen) { struct xaddr tmp_mask, tmp_result; if (host->af != net->af) return -1; if (addr_netmask(host->af, masklen, &tmp_mask) == -1) return -1; if (addr_and(&tmp_result, host, &tmp_mask) == -1) return -1; return addr_cmp(&tmp_result, net); } openssh-10.0p1/PaxHeaders.10889/addr.h100644 001750 001750 0000000003614775415623 0014237xustar0030 atime=1744182234.464672479 openssh-10.0p1/addr.h010064400017500001750000000035561477541562300126330ustar00djmdjm/* * Copyright (c) 2004,2005 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Address handling routines */ #ifndef _ADDR_H #define _ADDR_H #include #include struct xaddr { sa_family_t af; union { struct in_addr v4; struct in6_addr v6; u_int8_t addr8[16]; u_int16_t addr16[8]; u_int32_t addr32[4]; } xa; /* 128-bit address */ u_int32_t scope_id; /* iface scope id for v6 */ #define v4 xa.v4 #define v6 xa.v6 #define addr8 xa.addr8 #define addr16 xa.addr16 #define addr32 xa.addr32 }; int addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa); int addr_netmask(int af, u_int l, struct xaddr *n); int addr_pton(const char *p, struct xaddr *n); int addr_pton_cidr(const char *p, struct xaddr *n, u_int *l); int addr_ntop(const struct xaddr *n, char *p, size_t len); int addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b); int addr_cmp(const struct xaddr *a, const struct xaddr *b); int addr_host_to_all1s(struct xaddr *a, u_int masklen); int addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen); void addr_increment(struct xaddr *a); #endif /* _ADDR_H */ openssh-10.0p1/PaxHeaders.10889/addrmatch.c100644 001750 001750 0000000003614775415623 0015247xustar0030 atime=1744182234.464672479 openssh-10.0p1/addrmatch.c010064400017500001750000000106001477541562300136270ustar00djmdjm/* $OpenBSD: addrmatch.c,v 1.17 2021/04/03 06:18:40 djm Exp $ */ /* * Copyright (c) 2004-2008 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include "addr.h" #include "match.h" #include "log.h" /* * Match "addr" against list pattern list "_list", which may contain a * mix of CIDR addresses and old-school wildcards. * * If addr is NULL, then no matching is performed, but _list is parsed * and checked for well-formedness. * * Returns 1 on match found (never returned when addr == NULL). * Returns 0 on if no match found, or no errors found when addr == NULL. * Returns -1 on negated match found (never returned when addr == NULL). * Returns -2 on invalid list entry. */ int addr_match_list(const char *addr, const char *_list) { char *list, *cp, *o; struct xaddr try_addr, match_addr; u_int masklen, neg; int ret = 0, r; if (addr != NULL && addr_pton(addr, &try_addr) != 0) { debug2_f("couldn't parse address %.100s", addr); return 0; } if ((o = list = strdup(_list)) == NULL) return -1; while ((cp = strsep(&list, ",")) != NULL) { neg = *cp == '!'; if (neg) cp++; if (*cp == '\0') { ret = -2; break; } /* Prefer CIDR address matching */ r = addr_pton_cidr(cp, &match_addr, &masklen); if (r == -2) { debug2_f("inconsistent mask length for " "match network \"%.100s\"", cp); ret = -2; break; } else if (r == 0) { if (addr != NULL && addr_netmatch(&try_addr, &match_addr, masklen) == 0) { foundit: if (neg) { ret = -1; break; } ret = 1; } continue; } else { /* If CIDR parse failed, try wildcard string match */ if (addr != NULL && match_pattern(addr, cp) == 1) goto foundit; } } free(o); return ret; } /* * Match "addr" against list CIDR list "_list". Lexical wildcards and * negation are not supported. If "addr" == NULL, will verify structure * of "_list". * * Returns 1 on match found (never returned when addr == NULL). * Returns 0 on if no match found, or no errors found when addr == NULL. * Returns -1 on error */ int addr_match_cidr_list(const char *addr, const char *_list) { char *list, *cp, *o; struct xaddr try_addr, match_addr; u_int masklen; int ret = 0, r; if (addr != NULL && addr_pton(addr, &try_addr) != 0) { debug2_f("couldn't parse address %.100s", addr); return 0; } if ((o = list = strdup(_list)) == NULL) return -1; while ((cp = strsep(&list, ",")) != NULL) { if (*cp == '\0') { error_f("empty entry in list \"%.100s\"", o); ret = -1; break; } /* * NB. This function is called in pre-auth with untrusted data, * so be extra paranoid about junk reaching getaddrino (via * addr_pton_cidr). */ /* Stop junk from reaching getaddrinfo. +3 is for masklen */ if (strlen(cp) > INET6_ADDRSTRLEN + 3) { error_f("list entry \"%.100s\" too long", cp); ret = -1; break; } #define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/" if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) { error_f("list entry \"%.100s\" contains invalid " "characters", cp); ret = -1; } /* Prefer CIDR address matching */ r = addr_pton_cidr(cp, &match_addr, &masklen); if (r == -1) { error("Invalid network entry \"%.100s\"", cp); ret = -1; break; } else if (r == -2) { error("Inconsistent mask length for " "network \"%.100s\"", cp); ret = -1; break; } else if (r == 0 && addr != NULL) { if (addr_netmatch(&try_addr, &match_addr, masklen) == 0) ret = 1; continue; } } free(o); return ret; } openssh-10.0p1/PaxHeaders.10889/atomicio.c100644 001750 001750 0000000003614775415623 0015124xustar0030 atime=1744182234.464672479 openssh-10.0p1/atomicio.c010064400017500001750000000112341477541562300135100ustar00djmdjm/* $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. * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #include #include #include #include "atomicio.h" /* * ensure all of data on socket comes through. f==read || f==vwrite */ size_t atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n, int (*cb)(void *, size_t), void *cb_arg) { char *s = _s; size_t pos = 0; ssize_t res; struct pollfd pfd; 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) { /* possible SIGALARM, update callback */ if (cb != NULL && cb(cb_arg, 0) == -1) { errno = EINTR; return pos; } continue; } else if (errno == EAGAIN || errno == EWOULDBLOCK) { (void)poll(&pfd, 1, -1); continue; } return 0; case 0: errno = EPIPE; return pos; default: pos += (size_t)res; if (cb != NULL && cb(cb_arg, (size_t)res) == -1) { errno = EINTR; return pos; } } } return pos; } size_t atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) { return atomicio6(f, fd, _s, n, NULL, NULL); } /* * ensure all of data on socket comes through. f==readv || f==writev */ size_t atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd, const struct iovec *_iov, int iovcnt, int (*cb)(void *, size_t), void *cb_arg) { size_t pos = 0, rem; ssize_t res; struct iovec iov_array[IOV_MAX], *iov = iov_array; struct pollfd pfd; 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, (size_t)iovcnt * sizeof(*_iov)); 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) { /* possible SIGALARM, update callback */ if (cb != NULL && cb(cb_arg, 0) == -1) { errno = EINTR; return pos; } continue; } else if (errno == EAGAIN || errno == EWOULDBLOCK) { (void)poll(&pfd, 1, -1); continue; } return 0; case 0: errno = EPIPE; return pos; default: rem = (size_t)res; pos += rem; /* skip completed iov entries */ while (iovcnt > 0 && rem >= iov[0].iov_len) { rem -= iov[0].iov_len; iov++; iovcnt--; } /* This shouldn't happen... */ if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) { errno = EFAULT; return 0; } if (iovcnt == 0) break; /* update pointer in partially complete iov */ iov[0].iov_base = ((char *)iov[0].iov_base) + rem; iov[0].iov_len -= rem; } if (cb != NULL && cb(cb_arg, (size_t)res) == -1) { errno = EINTR; return pos; } } return pos; } size_t atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, const struct iovec *_iov, int iovcnt) { return atomiciov6(f, fd, _iov, iovcnt, NULL, NULL); } openssh-10.0p1/PaxHeaders.10889/atomicio.h100644 001750 001750 0000000003614775415623 0015131xustar0030 atime=1744182234.464672479 openssh-10.0p1/atomicio.h010064400017500001750000000042331477541562300135160ustar00djmdjm/* $OpenBSD: atomicio.h,v 1.12 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2006 Damien Miller. All rights reserved. * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. * 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 _ATOMICIO_H #define _ATOMICIO_H struct iovec; /* * Ensure all of data on socket comes through. f==read || f==vwrite */ size_t atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n, int (*cb)(void *, size_t), void *); size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); #define vwrite (ssize_t (*)(int, void *, size_t))write /* * ensure all of data on socket comes through. f==readv || f==writev */ size_t atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd, const struct iovec *_iov, int iovcnt, int (*cb)(void *, size_t), void *); size_t atomiciov(ssize_t (*)(int, const struct iovec *, int), int, const struct iovec *, int); #endif /* _ATOMICIO_H */ openssh-10.0p1/PaxHeaders.10889/audit-bsm.c100644 001750 001750 0000000003614775415623 0015205xustar0030 atime=1744182234.464672479 openssh-10.0p1/audit-bsm.c010064400017500001750000000273771477541562300136100ustar00djmdjm/* * TODO * * - deal with overlap between this and sys_auth_allowed_user * sys_auth_record_login and record_failed_login. */ /* * Copyright 1988-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * 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. * */ /* #pragma ident "@(#)bsmaudit.c 1.1 01/09/17 SMI" */ #include "includes.h" #if defined(USE_BSM_AUDIT) #include #include #include #include #include #include #ifdef BROKEN_BSM_API #include #endif #include "ssh.h" #include "log.h" #include "hostfile.h" #include "auth.h" #include "xmalloc.h" #ifndef AUE_openssh # define AUE_openssh 32800 #endif #include #include #include #include #include #if defined(HAVE_GETAUDIT_ADDR) #define AuditInfoStruct auditinfo_addr #define AuditInfoTermID au_tid_addr_t #define SetAuditFunc(a,b) setaudit_addr((a),(b)) #define SetAuditFuncText "setaudit_addr" #define AUToSubjectFunc au_to_subject_ex #define AUToReturnFunc(a,b) au_to_return32((a), (int32_t)(b)) #else #define AuditInfoStruct auditinfo #define AuditInfoTermID au_tid_t #define SetAuditFunc(a,b) setaudit(a) #define SetAuditFuncText "setaudit" #define AUToSubjectFunc au_to_subject #define AUToReturnFunc(a,b) au_to_return((a), (u_int)(b)) #endif #ifndef cannot_audit extern int cannot_audit(int); #endif extern void aug_init(void); extern void aug_save_auid(au_id_t); extern void aug_save_uid(uid_t); extern void aug_save_euid(uid_t); extern void aug_save_gid(gid_t); extern void aug_save_egid(gid_t); extern void aug_save_pid(pid_t); extern void aug_save_asid(au_asid_t); extern void aug_save_tid(dev_t, unsigned int); extern void aug_save_tid_ex(dev_t, u_int32_t *, u_int32_t); extern int aug_save_me(void); extern int aug_save_namask(void); extern void aug_save_event(au_event_t); extern void aug_save_sorf(int); extern void aug_save_text(char *); extern void aug_save_text1(char *); extern void aug_save_text2(char *); extern void aug_save_na(int); extern void aug_save_user(char *); extern void aug_save_path(char *); extern int aug_save_policy(void); extern void aug_save_afunc(int (*)(int)); extern int aug_audit(void); extern int aug_na_selected(void); extern int aug_selected(void); extern int aug_daemon_session(void); #ifndef HAVE_GETTEXT # define gettext(a) (a) #endif extern Authctxt *the_authctxt; static AuditInfoTermID ssh_bsm_tid; #ifdef BROKEN_BSM_API /* For some reason this constant is no longer defined in Solaris 11. */ #define BSM_TEXTBUFSZ 256 #endif /* Below is the low-level BSM interface code */ /* * aug_get_machine is only required on IPv6 capable machines, we use a * different mechanism in audit_connection_from() for IPv4-only machines. * getaudit_addr() is only present on IPv6 capable machines. */ #if defined(HAVE_AUG_GET_MACHINE) || !defined(HAVE_GETAUDIT_ADDR) extern int aug_get_machine(char *, u_int32_t *, u_int32_t *); #else static int aug_get_machine(char *host, u_int32_t *addr, u_int32_t *type) { struct addrinfo *ai; struct sockaddr_in *in4; struct sockaddr_in6 *in6; int ret = 0, r; if ((r = getaddrinfo(host, NULL, NULL, &ai)) != 0) { error("BSM audit: getaddrinfo failed for %.100s: %.100s", host, r == EAI_SYSTEM ? strerror(errno) : gai_strerror(r)); return -1; } switch (ai->ai_family) { case AF_INET: in4 = (struct sockaddr_in *)ai->ai_addr; *type = AU_IPv4; memcpy(addr, &in4->sin_addr, sizeof(struct in_addr)); break; #ifdef AU_IPv6 case AF_INET6: in6 = (struct sockaddr_in6 *)ai->ai_addr; *type = AU_IPv6; memcpy(addr, &in6->sin6_addr, sizeof(struct in6_addr)); break; #endif default: error("BSM audit: unknown address family for %.100s: %d", host, ai->ai_family); ret = -1; } freeaddrinfo(ai); return ret; } #endif #ifdef BROKEN_BSM_API /* In Solaris 11 the audit daemon has been moved to SMF. In the process they simply dropped getacna() from the API, since it read from a now non-existent config file. This function re-implements getacna() to read from the SMF repository instead. */ int getacna(char *auditstring, int len) { scf_handle_t *handle = NULL; scf_property_t *property = NULL; scf_value_t *value = NULL; int ret = 0; /* * The man page for getacna on Solaris 10 states we should return -2 * in case of error and set errno to indicate the error. We don't * bother with errno here, though, since the only use of this function * below doesn't check for errors anyway. */ handle = scf_handle_create(SCF_VERSION); if (handle == NULL) return -2; ret = scf_handle_bind(handle); if (ret == -1) return -2; property = scf_property_create(handle); if (property == NULL) return -2; ret = scf_handle_decode_fmri(handle, "svc:/system/auditd:default/:properties/preselection/naflags", NULL, NULL, NULL, NULL, property, 0); if (ret == -1) return -2; value = scf_value_create(handle); if (value == NULL) return -2; ret = scf_property_get_value(property, value); if (ret == -1) return -2; ret = scf_value_get_astring(value, auditstring, len); if (ret == -1) return -2; scf_value_destroy(value); scf_property_destroy(property); scf_handle_destroy(handle); return 0; } #endif /* * Check if the specified event is selected (enabled) for auditing. * Returns 1 if the event is selected, 0 if not and -1 on failure. */ static int selected(char *username, uid_t uid, au_event_t event, int sf) { int rc, sorf; char naflags[512]; struct au_mask mask; mask.am_success = mask.am_failure = 0; if (uid < 0) { /* get flags for non-attributable (to a real user) events */ rc = getacna(naflags, sizeof(naflags)); if (rc == 0) (void) getauditflagsbin(naflags, &mask); } else rc = au_user_mask(username, &mask); sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE; return(au_preselect(event, &mask, sorf, AU_PRS_REREAD)); } static void bsm_audit_record(int typ, char *string, au_event_t event_no) { int ad, rc, sel; uid_t uid = -1; gid_t gid = -1; pid_t pid = getpid(); AuditInfoTermID tid = ssh_bsm_tid; if (the_authctxt != NULL && the_authctxt->valid) { uid = the_authctxt->pw->pw_uid; gid = the_authctxt->pw->pw_gid; } rc = (typ == 0) ? 0 : -1; sel = selected(the_authctxt->user, uid, event_no, rc); debug3("BSM audit: typ %d rc %d \"%s\"", typ, rc, string); if (!sel) return; /* audit event does not match mask, do not write */ debug3("BSM audit: writing audit new record"); ad = au_open(); (void) au_write(ad, AUToSubjectFunc(uid, uid, gid, uid, gid, pid, pid, &tid)); (void) au_write(ad, au_to_text(string)); (void) au_write(ad, AUToReturnFunc(typ, rc)); #ifdef BROKEN_BSM_API /* * The last argument is the event modifier flags. For some seemingly * undocumented reason it was added in Solaris 11. */ rc = au_close(ad, AU_TO_WRITE, event_no, 0); #else rc = au_close(ad, AU_TO_WRITE, event_no); #endif if (rc < 0) error("BSM audit: %s failed to write \"%s\" record: %s", __func__, string, strerror(errno)); } static void bsm_audit_session_setup(void) { int rc; struct AuditInfoStruct info; au_mask_t mask; if (the_authctxt == NULL) { error("BSM audit: session setup internal error (NULL ctxt)"); return; } if (the_authctxt->valid) info.ai_auid = the_authctxt->pw->pw_uid; else info.ai_auid = -1; info.ai_asid = getpid(); mask.am_success = 0; mask.am_failure = 0; (void) au_user_mask(the_authctxt->user, &mask); info.ai_mask.am_success = mask.am_success; info.ai_mask.am_failure = mask.am_failure; info.ai_termid = ssh_bsm_tid; rc = SetAuditFunc(&info, sizeof(info)); if (rc < 0) error("BSM audit: %s: %s failed: %s", __func__, SetAuditFuncText, strerror(errno)); } static void bsm_audit_bad_login(const char *what) { char textbuf[BSM_TEXTBUFSZ]; if (the_authctxt->valid) { (void) snprintf(textbuf, sizeof (textbuf), gettext("invalid %s for user %s"), what, the_authctxt->user); bsm_audit_record(4, textbuf, AUE_openssh); } else { (void) snprintf(textbuf, sizeof (textbuf), gettext("invalid user name \"%s\""), the_authctxt->user); bsm_audit_record(3, textbuf, AUE_openssh); } } /* Below is the sshd audit API code */ void audit_connection_from(const char *host, int port) { AuditInfoTermID *tid = &ssh_bsm_tid; char buf[1024]; if (cannot_audit(0)) return; debug3("BSM audit: connection from %.100s port %d", host, port); /* populate our terminal id structure */ #if defined(HAVE_GETAUDIT_ADDR) tid->at_port = (dev_t)port; aug_get_machine((char *)host, &(tid->at_addr[0]), &(tid->at_type)); snprintf(buf, sizeof(buf), "%08x %08x %08x %08x", tid->at_addr[0], tid->at_addr[1], tid->at_addr[2], tid->at_addr[3]); debug3("BSM audit: iptype %d machine ID %s", (int)tid->at_type, buf); #else /* this is used on IPv4-only machines */ tid->port = (dev_t)port; tid->machine = inet_addr(host); snprintf(buf, sizeof(buf), "%08x", tid->machine); debug3("BSM audit: machine ID %s", buf); #endif } void audit_run_command(const char *command) { /* not implemented */ } void audit_session_open(struct logininfo *li) { /* not implemented */ } void audit_session_close(struct logininfo *li) { /* not implemented */ } void audit_event(struct ssh *ssh, ssh_audit_event_t event) { char textbuf[BSM_TEXTBUFSZ]; static int logged_in = 0; const char *user = the_authctxt ? the_authctxt->user : "(unknown user)"; if (cannot_audit(0)) return; switch(event) { case SSH_AUTH_SUCCESS: logged_in = 1; bsm_audit_session_setup(); snprintf(textbuf, sizeof(textbuf), gettext("successful login %s"), user); bsm_audit_record(0, textbuf, AUE_openssh); break; case SSH_CONNECTION_CLOSE: /* * We can also get a close event if the user attempted auth * but never succeeded. */ if (logged_in) { snprintf(textbuf, sizeof(textbuf), gettext("sshd logout %s"), the_authctxt->user); bsm_audit_record(0, textbuf, AUE_logout); } else { debug("%s: connection closed without authentication", __func__); } break; case SSH_NOLOGIN: bsm_audit_record(1, gettext("logins disabled by /etc/nologin"), AUE_openssh); break; case SSH_LOGIN_EXCEED_MAXTRIES: snprintf(textbuf, sizeof(textbuf), gettext("too many tries for user %s"), the_authctxt->user); bsm_audit_record(1, textbuf, AUE_openssh); break; case SSH_LOGIN_ROOT_DENIED: bsm_audit_record(2, gettext("not_console"), AUE_openssh); break; case SSH_AUTH_FAIL_PASSWD: bsm_audit_bad_login("password"); break; case SSH_AUTH_FAIL_KBDINT: bsm_audit_bad_login("interactive password entry"); break; default: debug("%s: unhandled event %d", __func__, event); } } #endif /* BSM */ openssh-10.0p1/PaxHeaders.10889/audit-linux.c100644 001750 001750 0000000003614775415623 0015563xustar0030 atime=1744182234.464672479 openssh-10.0p1/audit-linux.c010064400017500001750000000066771477541562300141660ustar00djmdjm/* * Copyright 2010 Red Hat, Inc. All rights reserved. * Use is subject to license terms. * * 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. * * Red Hat author: Jan F. Chadima */ #include "includes.h" #if defined(USE_LINUX_AUDIT) #include #include #include #include "log.h" #include "audit.h" #include "canohost.h" #include "packet.h" 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) { int audit_fd, rc, saved_errno; if ((audit_fd = audit_open()) < 0) { if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) return 1; /* No audit support in kernel */ else return 0; /* Must prevent login */ } rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, NULL, "login", username ? username : "(unknown)", 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. */ if ((rc == -EPERM) && (geteuid() != 0)) rc = 0; errno = saved_errno; return rc >= 0; } /* Below is the sshd audit API code */ void audit_connection_from(const char *host, int port) { /* not implemented */ } void audit_run_command(const char *command) { /* not implemented */ } void audit_session_open(struct logininfo *li) { if (linux_audit_record_event(li->uid, NULL, li->hostname, NULL, li->line, 1) == 0) fatal("linux_audit_write_entry failed: %s", strerror(errno)); } void audit_session_close(struct logininfo *li) { /* not implemented */ } void audit_event(struct ssh *ssh, ssh_audit_event_t event) { switch(event) { case SSH_AUTH_SUCCESS: case SSH_CONNECTION_CLOSE: case SSH_NOLOGIN: 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: case SSH_AUTH_FAIL_PUBKEY: case SSH_AUTH_FAIL_HOSTBASED: case SSH_AUTH_FAIL_GSSAPI: case SSH_INVALID_USER: linux_audit_record_event(-1, audit_username(), NULL, ssh_remote_ipaddr(ssh), "sshd", 0); break; default: debug("%s: unhandled event %d", __func__, event); break; } } #endif /* USE_LINUX_AUDIT */ openssh-10.0p1/PaxHeaders.10889/audit.c100644 001750 001750 0000000003614775415623 0014426xustar0030 atime=1744182234.465649577 openssh-10.0p1/audit.c010064400017500001750000000133241477541562300130140ustar00djmdjm/* * Copyright (c) 2004, 2005 Darren Tucker. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #ifdef SSH_AUDIT_EVENTS #include "audit.h" #include "log.h" #include "hostfile.h" #include "auth.h" /* * Care must be taken when using this since it WILL NOT be initialized when * audit_connection_from() is called and MAY NOT be initialized when * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. */ extern Authctxt *the_authctxt; /* Maybe add the audit class to struct Authmethod? */ ssh_audit_event_t audit_classify_auth(const char *method) { if (strcmp(method, "none") == 0) return SSH_AUTH_FAIL_NONE; else if (strcmp(method, "password") == 0) return SSH_AUTH_FAIL_PASSWD; else if (strcmp(method, "publickey") == 0 || strcmp(method, "rsa") == 0) return SSH_AUTH_FAIL_PUBKEY; else if (strncmp(method, "keyboard-interactive", 20) == 0 || strcmp(method, "challenge-response") == 0) return SSH_AUTH_FAIL_KBDINT; else if (strcmp(method, "hostbased") == 0 || strcmp(method, "rhosts-rsa") == 0) return SSH_AUTH_FAIL_HOSTBASED; else if (strcmp(method, "gssapi-with-mic") == 0) return SSH_AUTH_FAIL_GSSAPI; else return SSH_AUDIT_UNKNOWN; } /* helper to return supplied username */ const char * audit_username(void) { static const char unknownuser[] = "(unknown user)"; static const char invaliduser[] = "(invalid user)"; if (the_authctxt == NULL || the_authctxt->user == NULL) return (unknownuser); if (!the_authctxt->valid) return (invaliduser); return (the_authctxt->user); } const char * audit_event_lookup(ssh_audit_event_t ev) { int i; static struct event_lookup_struct { ssh_audit_event_t event; const char *name; } event_lookup[] = { {SSH_LOGIN_EXCEED_MAXTRIES, "LOGIN_EXCEED_MAXTRIES"}, {SSH_LOGIN_ROOT_DENIED, "LOGIN_ROOT_DENIED"}, {SSH_AUTH_SUCCESS, "AUTH_SUCCESS"}, {SSH_AUTH_FAIL_NONE, "AUTH_FAIL_NONE"}, {SSH_AUTH_FAIL_PASSWD, "AUTH_FAIL_PASSWD"}, {SSH_AUTH_FAIL_KBDINT, "AUTH_FAIL_KBDINT"}, {SSH_AUTH_FAIL_PUBKEY, "AUTH_FAIL_PUBKEY"}, {SSH_AUTH_FAIL_HOSTBASED, "AUTH_FAIL_HOSTBASED"}, {SSH_AUTH_FAIL_GSSAPI, "AUTH_FAIL_GSSAPI"}, {SSH_INVALID_USER, "INVALID_USER"}, {SSH_NOLOGIN, "NOLOGIN"}, {SSH_CONNECTION_CLOSE, "CONNECTION_CLOSE"}, {SSH_CONNECTION_ABANDON, "CONNECTION_ABANDON"}, {SSH_AUDIT_UNKNOWN, "AUDIT_UNKNOWN"} }; for (i = 0; event_lookup[i].event != SSH_AUDIT_UNKNOWN; i++) if (event_lookup[i].event == ev) break; return(event_lookup[i].name); } # ifndef CUSTOM_SSH_AUDIT_EVENTS /* * Null implementations of audit functions. * These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled. */ /* * Called after a connection has been accepted but before any authentication * has been attempted. */ void audit_connection_from(const char *host, int port) { debug("audit connection from %s port %d euid %d", host, port, (int)geteuid()); } /* * Called when various events occur (see audit.h for a list of possible * events and what they mean). */ void 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)); } /* * Called when a user session is started. Argument is the tty allocated to * the session, or NULL if no tty was allocated. * * Note that this may be called multiple times if multiple sessions are used * within a single connection. */ void audit_session_open(struct logininfo *li) { const char *t = li->line ? li->line : "(no tty)"; debug("audit session open euid %d user %s tty name %s", geteuid(), audit_username(), t); } /* * Called when a user session is closed. Argument is the tty allocated to * the session, or NULL if no tty was allocated. * * Note that this may be called multiple times if multiple sessions are used * within a single connection. */ void audit_session_close(struct logininfo *li) { const char *t = li->line ? li->line : "(no tty)"; debug("audit session close euid %d user %s tty name %s", geteuid(), audit_username(), t); } /* * This will be called when a user runs a non-interactive command. Note that * it may be called multiple times for a single connection since SSH2 allows * multiple sessions within a single connection. */ void audit_run_command(const char *command) { debug("audit run command euid %d user %s command '%.200s'", geteuid(), audit_username(), command); } # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ #endif /* SSH_AUDIT_EVENTS */ openssh-10.0p1/PaxHeaders.10889/audit.h100644 001750 001750 0000000003614775415623 0014433xustar0030 atime=1744182234.465649577 openssh-10.0p1/audit.h010064400017500001750000000044611477541562300130230ustar00djmdjm/* * Copyright (c) 2004, 2005 Darren Tucker. 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_AUDIT_H # define _SSH_AUDIT_H #include "loginrec.h" struct ssh; enum ssh_audit_event_type { SSH_LOGIN_EXCEED_MAXTRIES, SSH_LOGIN_ROOT_DENIED, SSH_AUTH_SUCCESS, SSH_AUTH_FAIL_NONE, SSH_AUTH_FAIL_PASSWD, SSH_AUTH_FAIL_KBDINT, /* keyboard-interactive or challenge-response */ SSH_AUTH_FAIL_PUBKEY, /* ssh2 pubkey or ssh1 rsa */ SSH_AUTH_FAIL_HOSTBASED, /* ssh2 hostbased or ssh1 rhostsrsa */ SSH_AUTH_FAIL_GSSAPI, SSH_INVALID_USER, SSH_NOLOGIN, /* denied by /etc/nologin, not implemented */ SSH_CONNECTION_CLOSE, /* closed after attempting auth or session */ SSH_CONNECTION_ABANDON, /* closed without completing auth */ SSH_AUDIT_UNKNOWN }; typedef enum ssh_audit_event_type ssh_audit_event_t; void audit_connection_from(const char *, int); 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 *); ssh_audit_event_t audit_classify_auth(const char *); #endif /* _SSH_AUDIT_H */ openssh-10.0p1/PaxHeaders.10889/auth-bsdauth.c100644 001750 001750 0000000003614775415623 0015711xustar0030 atime=1744182234.465649577 openssh-10.0p1/auth-bsdauth.c010064400017500001750000000072011477541562300142740ustar00djmdjm/* $OpenBSD: auth-bsdauth.c,v 1.15 2018/07/09 21:35:50 markus 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 #include #include #ifdef BSD_AUTH #include "xmalloc.h" #include "sshkey.h" #include "sshbuf.h" #include "hostfile.h" #include "auth.h" #include "log.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" static void * bsdauth_init_ctx(Authctxt *authctxt) { return authctxt; } int bsdauth_query(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { Authctxt *authctxt = ctx; char *challenge = NULL; *infotxt = NULL; *numprompts = 0; *prompts = NULL; *echo_on = NULL; if (authctxt->as != NULL) { debug2("bsdauth_query: try reuse session"); challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); if (challenge == NULL) { auth_close(authctxt->as); authctxt->as = NULL; } } if (challenge == NULL) { debug2("bsdauth_query: new bsd auth session"); debug3("bsdauth_query: style %s", authctxt->style ? authctxt->style : ""); authctxt->as = auth_userchallenge(authctxt->user, authctxt->style, "auth-ssh", &challenge); if (authctxt->as == NULL) challenge = NULL; debug2("bsdauth_query: <%s>", challenge ? challenge : "empty"); } if (challenge == NULL) return -1; *name = xstrdup(""); *infotxt = xstrdup(""); *numprompts = 1; *prompts = xcalloc(*numprompts, sizeof(char *)); *echo_on = xcalloc(*numprompts, sizeof(u_int)); (*prompts)[0] = xstrdup(challenge); return 0; } int bsdauth_respond(void *ctx, u_int numresponses, char **responses) { Authctxt *authctxt = ctx; int authok; if (!authctxt->valid) return -1; if (authctxt->as == NULL) error("bsdauth_respond: no bsd auth session"); if (numresponses != 1) return -1; authok = auth_userresponse(authctxt->as, responses[0], 0); authctxt->as = NULL; debug3("bsdauth_respond: <%s> = <%d>", responses[0], authok); return (authok == 0) ? -1 : 0; } static void bsdauth_free_ctx(void *ctx) { Authctxt *authctxt = ctx; if (authctxt && authctxt->as) { auth_close(authctxt->as); authctxt->as = NULL; } } KbdintDevice bsdauth_device = { "bsdauth", bsdauth_init_ctx, bsdauth_query, bsdauth_respond, bsdauth_free_ctx }; KbdintDevice mm_bsdauth_device = { "bsdauth", bsdauth_init_ctx, mm_bsdauth_query, mm_bsdauth_respond, bsdauth_free_ctx }; #endif openssh-10.0p1/PaxHeaders.10889/auth-krb5.c100644 001750 001750 0000000003614775415623 0015122xustar0030 atime=1744182234.465649577 openssh-10.0p1/auth-krb5.c010064400017500001750000000156661477541562300135230ustar00djmdjm/* $OpenBSD: auth-krb5.c,v 1.24 2021/04/03 06:18:40 djm Exp $ */ /* * Kerberos v5 authentication and ticket-passing routines. * * 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include "xmalloc.h" #include "ssh.h" #include "packet.h" #include "log.h" #include "sshbuf.h" #include "sshkey.h" #include "misc.h" #include "servconf.h" #include "uidswap.h" #include "hostfile.h" #include "auth.h" #ifdef KRB5 #include #include #include #include extern ServerOptions options; static int krb5_init(void *context) { Authctxt *authctxt = (Authctxt *)context; krb5_error_code problem; if (authctxt->krb5_ctx == NULL) { problem = krb5_init_context(&authctxt->krb5_ctx); if (problem) return (problem); } return (0); } int auth_krb5_password(Authctxt *authctxt, const char *password) { #ifndef HEIMDAL krb5_creds creds; krb5_principal server; #endif krb5_error_code problem; krb5_ccache ccache = NULL; int len; char *client, *platform_client; const char *errmsg; /* get platform-specific kerberos client principal name (if it exists) */ platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name); client = platform_client ? platform_client : authctxt->pw->pw_name; temporarily_use_uid(authctxt->pw); problem = krb5_init(authctxt); if (problem) goto out; problem = krb5_parse_name(authctxt->krb5_ctx, client, &authctxt->krb5_user); if (problem) goto out; #ifdef HEIMDAL # ifdef HAVE_KRB5_CC_NEW_UNIQUE problem = krb5_cc_new_unique(authctxt->krb5_ctx, krb5_mcc_ops.prefix, NULL, &ccache); # else problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache); # endif if (problem) goto out; problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, authctxt->krb5_user); if (problem) goto out; restore_uid(); problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, ccache, password, 1, NULL); temporarily_use_uid(authctxt->pw); if (problem) goto out; # ifdef HAVE_KRB5_CC_NEW_UNIQUE problem = krb5_cc_new_unique(authctxt->krb5_ctx, krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache); # else problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &authctxt->krb5_fwd_ccache); # endif if (problem) goto out; problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache, authctxt->krb5_fwd_ccache); krb5_cc_destroy(authctxt->krb5_ctx, ccache); ccache = NULL; if (problem) goto out; #else problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL); if (problem) goto out; problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, KRB5_NT_SRV_HST, &server); if (problem) goto out; restore_uid(); problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, NULL, NULL, NULL); krb5_free_principal(authctxt->krb5_ctx, server); temporarily_use_uid(authctxt->pw); if (problem) goto out; if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->pw->pw_name)) { problem = -1; goto out; } problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache); if (problem) goto out; problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, authctxt->krb5_user); if (problem) goto out; problem = krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, &creds); if (problem) goto out; #endif authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); len = strlen(authctxt->krb5_ticket_file) + 6; authctxt->krb5_ccname = xmalloc(len); snprintf(authctxt->krb5_ccname, len, "FILE:%s", authctxt->krb5_ticket_file); #ifdef USE_PAM if (options.use_pam) do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname); #endif out: restore_uid(); free(platform_client); if (problem) { if (ccache) krb5_cc_destroy(authctxt->krb5_ctx, ccache); if (authctxt->krb5_ctx != NULL && problem!=-1) { errmsg = krb5_get_error_message(authctxt->krb5_ctx, problem); debug("Kerberos password authentication failed: %s", errmsg); krb5_free_error_message(authctxt->krb5_ctx, errmsg); } else debug("Kerberos password authentication failed: %d", problem); krb5_cleanup_proc(authctxt); if (options.kerberos_or_local_passwd) return (-1); else return (0); } return (authctxt->valid ? 1 : 0); } void krb5_cleanup_proc(Authctxt *authctxt) { debug("krb5_cleanup_proc called"); if (authctxt->krb5_fwd_ccache) { krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); authctxt->krb5_fwd_ccache = NULL; } if (authctxt->krb5_user) { krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); authctxt->krb5_user = NULL; } if (authctxt->krb5_ctx) { krb5_free_context(authctxt->krb5_ctx); authctxt->krb5_ctx = NULL; } } #ifndef HEIMDAL krb5_error_code ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { int tmpfd, ret, oerrno; char ccname[40]; mode_t old_umask; ret = snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); if (ret < 0 || (size_t)ret >= sizeof(ccname)) return ENOMEM; old_umask = umask(0177); tmpfd = mkstemp(ccname + strlen("FILE:")); oerrno = errno; umask(old_umask); if (tmpfd == -1) { logit("mkstemp(): %.100s", strerror(oerrno)); return oerrno; } if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { oerrno = errno; logit("fchmod(): %.100s", strerror(oerrno)); close(tmpfd); return oerrno; } close(tmpfd); return (krb5_cc_resolve(ctx, ccname, ccache)); } #endif /* !HEIMDAL */ #endif /* KRB5 */ openssh-10.0p1/PaxHeaders.10889/auth-options.c100644 001750 001750 0000000003614775415623 0015752xustar0030 atime=1744182234.469555095 openssh-10.0p1/auth-options.c010064400017500001750000000570041477541562300143430ustar00djmdjm/* $OpenBSD: auth-options.c,v 1.101 2023/07/14 07:44:21 dtucker Exp $ */ /* * Copyright (c) 2018 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssherr.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "sshkey.h" #include "match.h" #include "ssh2.h" #include "auth-options.h" static int dup_strings(char ***dstp, size_t *ndstp, char **src, size_t nsrc) { char **dst; size_t i, j; *dstp = NULL; *ndstp = 0; if (nsrc == 0) return 0; if (nsrc >= SIZE_MAX / sizeof(*src) || (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; } } /* success */ *dstp = dst; *ndstp = nsrc; return 0; } #define OPTIONS_CRITICAL 1 #define OPTIONS_EXTENSIONS 2 static int cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob, u_int which, int crit) { char *command, *allowed; char *name = NULL; struct sshbuf *c = NULL, *data = NULL; int r, ret = -1, found; if ((c = sshbuf_fromb(oblob)) == NULL) { error_f("sshbuf_fromb failed"); goto out; } while (sshbuf_len(c) > 0) { sshbuf_free(data); data = NULL; if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 || (r = sshbuf_froms(c, &data)) != 0) { error_r(r, "Unable to parse certificate options"); goto out; } debug3("found certificate option \"%.100s\" len %zu", name, sshbuf_len(data)); found = 0; if ((which & OPTIONS_EXTENSIONS) != 0) { if (strcmp(name, "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) { opts->permit_agent_forwarding_flag = 1; found = 1; } else if (strcmp(name, "permit-port-forwarding") == 0) { opts->permit_port_forwarding_flag = 1; found = 1; } else if (strcmp(name, "permit-pty") == 0) { opts->permit_pty_flag = 1; found = 1; } else if (strcmp(name, "permit-user-rc") == 0) { opts->permit_user_rc = 1; found = 1; } } if (!found && (which & OPTIONS_CRITICAL) != 0) { if (strcmp(name, "verify-required") == 0) { opts->require_verify = 1; found = 1; } else if (strcmp(name, "force-command") == 0) { if ((r = sshbuf_get_cstring(data, &command, NULL)) != 0) { error_r(r, "Unable to parse \"%s\" " "section", name); goto out; } if (opts->force_command != NULL) { error("Certificate has multiple " "force-command options"); free(command); goto out; } opts->force_command = command; found = 1; } else if (strcmp(name, "source-address") == 0) { if ((r = sshbuf_get_cstring(data, &allowed, NULL)) != 0) { error_r(r, "Unable to parse \"%s\" " "section", name); goto out; } if (opts->required_from_host_cert != NULL) { error("Certificate has multiple " "source-address options"); free(allowed); goto out; } /* 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; } } if (!found) { if (crit) { error("Certificate critical option \"%s\" " "is not supported", name); goto out; } else { logit("Certificate extension \"%s\" " "is not supported", name); } } else if (sshbuf_len(data) != 0) { error("Certificate option \"%s\" corrupt " "(extra data)", name); goto out; } free(name); name = NULL; } /* successfully parsed all options */ ret = 0; out: 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; } /* * Parse and record a permitopen/permitlisten directive. * Return 0 on success. Return -1 on failure and sets *errstrp to error reason. */ static int handle_permit(const char **optsp, int allow_bare_port, char ***permitsp, size_t *npermitsp, const char **errstrp) { 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 = hpdelim2(&cp, NULL); 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; size_t i, l; 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("verify-required", 1, &opts)) != -1) { ret->require_verify = r == 1; } else if ((r = opt_flag("pty", 1, &opts)) != -1) { ret->permit_pty_flag = r == 1; } else if ((r = opt_flag("user-rc", 1, &opts)) != -1) { 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 > SSH_AUTHOPT_ENV_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) { free(opt); goto alloc_fail; } l = (size_t)(tmp - opt); cp[l] = '\0'; /* truncate at '=' */ if (!valid_env_name(cp)) { free(cp); free(opt); errstr = "invalid environment string"; goto fail; } /* Check for duplicates; XXX O(n*log(n)) */ for (i = 0; i < ret->nenv; i++) { if (strncmp(ret->env[i], cp, l) == 0 && ret->env[i][l] == '=') break; } free(cp); /* First match wins */ if (i >= ret->nenv) { /* Append it. */ oarray = ret->env; if ((ret->env = recallocarray(ret->env, ret->nenv, ret->nenv + 1, sizeof(*ret->env))) == NULL) { free(opt); /* put it back for cleanup */ ret->env = oarray; goto alloc_fail; } ret->env[ret->nenv++] = opt; opt = NULL; /* transferred */ } free(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) #define OPTFLAG_OR(x) ret->x = (primary->x == 1) || (additional->x == 1) /* Permissive flags are logical-AND (i.e. must be set in both) */ OPTFLAG_AND(permit_port_forwarding_flag); OPTFLAG_AND(permit_agent_forwarding_flag); OPTFLAG_AND(permit_x11_forwarding_flag); OPTFLAG_AND(permit_pty_flag); OPTFLAG_AND(permit_user_rc); OPTFLAG_AND(no_require_user_presence); /* Restrictive flags are logical-OR (i.e. must be set in either) */ OPTFLAG_OR(require_verify); #undef OPTFLAG_AND /* Earliest expiry time should win */ if (primary->valid_before != 0) 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); OPTSCALAR(require_verify); #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 = SSH_ERR_INTERNAL_ERROR; 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) goto out; } if ((r = sshbuf_put_u32(m, n)) != 0 || (r = sshbuf_put_stringb(m, b)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } 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 || (r = sshbuf_put_u8(m, opts->require_verify)) != 0) return r; /* Simple integer options */ if ((r = sshbuf_put_u64(m, opts->valid_before)) != 0) return r; /* tunnel number can be negative to indicate "unset" */ 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); OPT_FLAG(require_verify); #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; } openssh-10.0p1/PaxHeaders.10889/auth-options.h100644 001750 001750 0000000003614775415623 0015757xustar0030 atime=1744182234.469555095 openssh-10.0p1/auth-options.h010064400017500001750000000061231477541562300143440ustar00djmdjm/* $OpenBSD: auth-options.h,v 1.31 2021/07/23 03:57:20 djm Exp $ */ /* * Copyright (c) 2018 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. */ #ifndef AUTH_OPTIONS_H #define AUTH_OPTIONS_H struct passwd; struct sshkey; /* Maximum number of permitopen/permitlisten directives to accept */ #define SSH_AUTHOPT_PERMIT_MAX 4096 /* Maximum number of environment directives to accept */ #define SSH_AUTHOPT_ENV_MAX 1024 /* * sshauthopt represents key options parsed from authorized_keys or * 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; /* Key requires user verification (e.g. PIN) */ int require_verify; }; 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 openssh-10.0p1/PaxHeaders.10889/auth-pam.c100644 001750 001750 0000000003614775415623 0015034xustar0030 atime=1744182234.470531842 openssh-10.0p1/auth-pam.c010064400017500001750000001110131477541562300134140ustar00djmdjm/*- * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by ThinkSec AS and * NAI Labs, the Security Research Division of Network Associates, Inc. * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the * DARPA CHATS research program. * * 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 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. */ /* * Copyright (c) 2003,2004 Damien Miller * Copyright (c) 2003,2004 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. */ /* Based on FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des */ #include "includes.h" #include #include #include #include #include #include #include #include #include #ifdef USE_PAM #if defined(HAVE_SECURITY_PAM_APPL_H) #include #elif defined (HAVE_PAM_PAM_APPL_H) #include #endif /* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */ #ifdef PAM_SUN_CODEBASE # define sshpam_const /* Solaris, HP-UX, SunOS */ #else # define sshpam_const const /* LinuxPAM, OpenPAM, AIX */ #endif /* Ambiguity in spec: is it an array of pointers or a pointer to an array? */ #ifdef PAM_SUN_CODEBASE # define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member) #else # define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member) #endif #include "xmalloc.h" #include "sshbuf.h" #include "ssherr.h" #include "hostfile.h" #include "auth.h" #include "auth-pam.h" #include "canohost.h" #include "log.h" #include "msg.h" #include "packet.h" #include "misc.h" #include "servconf.h" #include "ssh2.h" #include "auth-options.h" #include "misc.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "srclimit.h" extern ServerOptions options; extern struct sshbuf *loginmsg; extern u_int utmp_len; /* so we don't silently change behaviour */ #ifdef USE_POSIX_THREADS # error "USE_POSIX_THREADS replaced by UNSUPPORTED_POSIX_THREADS_HACK" #endif /* * Formerly known as USE_POSIX_THREADS, using this is completely unsupported * and generally a bad idea. Use at own risk and do not expect support if * this breaks. */ #ifdef UNSUPPORTED_POSIX_THREADS_HACK #include /* * Avoid namespace clash when *not* using pthreads for systems *with* * pthreads, which unconditionally define pthread_t via sys/types.h * (e.g. Linux) */ 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 { sp_pthread_t pam_thread; int pam_psock; int pam_csock; int pam_done; }; static void sshpam_free_ctx(void *); static struct pam_ctxt *cleanup_ctxt; #ifndef UNSUPPORTED_POSIX_THREADS_HACK /* * Simulate threads with processes. */ static int sshpam_thread_status = -1; static sshsig_t sshpam_oldsig; static void sshpam_sigchld_handler(int sig) { 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); while (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) == -1) { if (errno == EINTR) continue; return; } } if (sshpam_thread_status == -1) return; if (WIFSIGNALED(sshpam_thread_status)) { if (signal_is_crash(WTERMSIG(sshpam_thread_status))) _exit(EXIT_CHILD_CRASH); } else if (!WIFEXITED(sshpam_thread_status)) _exit(EXIT_CHILD_CRASH); } /* ARGSUSED */ static void pthread_exit(void *value) { _exit(0); } /* ARGSUSED */ static int pthread_create(sp_pthread_t *thread, const void *attr, void *(*thread_start)(void *), void *arg) { pid_t pid; struct pam_ctxt *ctx = arg; sshpam_thread_status = -1; switch ((pid = fork())) { case -1: error("fork(): %s", strerror(errno)); return errno; case 0: close(ctx->pam_psock); ctx->pam_psock = -1; thread_start(arg); _exit(1); default: *thread = pid; close(ctx->pam_csock); ctx->pam_csock = -1; sshpam_oldsig = ssh_signal(SIGCHLD, sshpam_sigchld_handler); return (0); } } static int pthread_cancel(sp_pthread_t thread) { ssh_signal(SIGCHLD, sshpam_oldsig); return (kill(thread, SIGTERM)); } /* ARGSUSED */ static int pthread_join(sp_pthread_t thread, void **value) { int status; if (sshpam_thread_status != -1) return (sshpam_thread_status); 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 static pam_handle_t *sshpam_handle = NULL; static int sshpam_err = 0; 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 *sshpam_rhost = NULL; static char *sshpam_laddr = NULL; /* Some PAM implementations don't implement this */ #ifndef HAVE_PAM_GETENVLIST static char ** pam_getenvlist(pam_handle_t *pamh) { /* * 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. */ return NULL; } #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 * is 0, on the assumption that it's being called by "passwd" run by root. * This wraps pam_chauthtok and sets/restore the real uid so PAM will do * the right thing. */ #ifdef SSHPAM_CHAUTHTOK_NEEDS_RUID static int sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags) { int result; if (sshpam_authctxt == NULL) fatal("PAM: sshpam_authctxt not initialized"); if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1) fatal("%s: setreuid failed: %s", __func__, strerror(errno)); result = pam_chauthtok(pamh, flags); if (setreuid(0, -1) == -1) fatal("%s: setreuid failed: %s", __func__, strerror(errno)); return result; } # define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b))) #endif 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) { 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 { 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(struct sshbuf *b) { char *env; 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 */ 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 */ if ((r = sshbuf_get_u32(b, &num_env)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (num_env > 1024) { fatal_f("received %u environment variables, expected <= 1024", num_env); } sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env)); debug3("PAM: num env strings %u", num_env); for(i = 0; i < num_env; i++) { if ((r = sshbuf_get_cstring(b, &(sshpam_env[i]), NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } sshpam_env[num_env] = NULL; /* Import PAM environment from subprocess */ if ((r = sshbuf_get_u32(b, &num_env)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (num_env > 1024) { fatal_f("received %u PAM env variables, expected <= 1024", num_env); } debug("PAM: num PAM env strings %u", num_env); for (i = 0; i < num_env; i++) { if ((r = sshbuf_get_cstring(b, &env, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* Errors are not fatal here */ if ((r = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) { error("PAM: pam_putenv: %s", pam_strerror(sshpam_handle, r)); } /* * XXX this possibly leaks env because it is not documented * what pam_putenv() does with it. Does it copy it? Does it * take ownweship? We don't know, so it's safest just to leak. */ } #endif } /* * Conversation function for authentication thread. */ static int sshpam_thread_conv(int n, sshpam_const struct pam_message **msg, struct pam_response **resp, void *data) { struct sshbuf *buffer; struct pam_ctxt *ctxt; struct pam_response *reply; int r, i; u_char status; debug3("PAM: %s entering, %d messages", __func__, n); *resp = NULL; if (data == NULL) { error("PAM: conversation function passed a null context"); return (PAM_CONV_ERR); } ctxt = data; if (n <= 0 || n > PAM_MAX_NUM_MSG) return (PAM_CONV_ERR); if ((reply = calloc(n, sizeof(*reply))) == NULL) return PAM_CONV_ERR; if ((buffer = sshbuf_new()) == NULL) { free(reply); return PAM_CONV_ERR; } for (i = 0; i < n; ++i) { switch (PAM_MSG_MEMBER(msg, i, msg_style)) { case PAM_PROMPT_ECHO_OFF: case PAM_PROMPT_ECHO_ON: 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) goto fail; if (ssh_msg_recv(ctxt->pam_csock, buffer) == -1) goto fail; if ((r = sshbuf_get_u8(buffer, &status)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (status != PAM_AUTHTOK) goto fail; 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: case PAM_TEXT_INFO: 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) goto fail; break; default: goto fail; } sshbuf_reset(buffer); } sshbuf_free(buffer); *resp = reply; return (PAM_SUCCESS); fail: for(i = 0; i < n; i++) { free(reply[i].resp); } free(reply); sshbuf_free(buffer); return (PAM_CONV_ERR); } /* * Authentication thread. */ static void * sshpam_thread(void *ctxtp) { struct pam_ctxt *ctxt = ctxtp; struct sshbuf *buffer = NULL; struct pam_conv sshpam_conv; int r, flags = (options.permit_empty_passwd == 0 ? PAM_DISALLOW_NULL_AUTHTOK : 0); #ifndef UNSUPPORTED_POSIX_THREADS_HACK extern char **environ; char **env_from_pam; u_int i; const char *pam_user; const char **ptr_pam_user = &pam_user; char *tz = getenv("TZ"); sshpam_err = pam_get_item(sshpam_handle, PAM_USER, (sshpam_const void **)ptr_pam_user); if (sshpam_err != PAM_SUCCESS) goto auth_fail; environ[0] = NULL; if (tz != NULL) if (setenv("TZ", tz, 1) == -1) error("PAM: could not set TZ environment: %s", strerror(errno)); if (sshpam_authctxt != NULL) { setproctitle("%s [pam]", sshpam_authctxt->valid ? pam_user : "unknown"); } #endif sshpam_conv.conv = sshpam_thread_conv; sshpam_conv.appdata_ptr = ctxt; if (sshpam_authctxt == NULL) fatal("%s: PAM authctxt not initialized", __func__); 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 (!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; sshpam_password_change_required(0); } 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 */ 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 */ 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 */ 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); sshbuf_free(buffer); pthread_exit(NULL); auth_fail: 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); 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); sshbuf_free(buffer); pthread_exit(NULL); return (NULL); /* Avoid warning for non-pthread case */ } void sshpam_thread_cleanup(void) { struct pam_ctxt *ctxt = cleanup_ctxt; debug3("PAM: %s entering", __func__); if (ctxt != NULL && ctxt->pam_thread != 0) { pthread_cancel(ctxt->pam_thread); pthread_join(ctxt->pam_thread, NULL); close(ctxt->pam_psock); close(ctxt->pam_csock); memset(ctxt, 0, sizeof(*ctxt)); cleanup_ctxt = NULL; } } static int sshpam_null_conv(int n, sshpam_const struct pam_message **msg, struct pam_response **resp, void *data) { debug3("PAM: %s entering, %d messages", __func__, n); return (PAM_CONV_ERR); } static struct pam_conv null_conv = { sshpam_null_conv, NULL }; static int sshpam_store_conv(int n, sshpam_const struct pam_message **msg, struct pam_response **resp, void *data) { struct pam_response *reply; int r, i; debug3("PAM: %s called with %d messages", __func__, n); *resp = NULL; if (n <= 0 || n > PAM_MAX_NUM_MSG) return (PAM_CONV_ERR); if ((reply = calloc(n, sizeof(*reply))) == NULL) return (PAM_CONV_ERR); for (i = 0; i < n; ++i) { switch (PAM_MSG_MEMBER(msg, i, msg_style)) { case PAM_ERROR_MSG: case PAM_TEXT_INFO: 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: goto fail; } } *resp = reply; return (PAM_SUCCESS); fail: for(i = 0; i < n; i++) { free(reply[i].resp); } free(reply); return (PAM_CONV_ERR); } static struct pam_conv store_conv = { sshpam_store_conv, NULL }; void sshpam_cleanup(void) { if (sshpam_handle == NULL || !mm_is_monitor()) return; debug("PAM: cleanup"); pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv); if (sshpam_session_open) { debug("PAM: closing session"); pam_close_session(sshpam_handle, PAM_SILENT); sshpam_session_open = 0; } if (sshpam_cred_established) { debug("PAM: deleting credentials"); pam_setcred(sshpam_handle, PAM_DELETE_CRED); sshpam_cred_established = 0; } sshpam_authenticated = 0; pam_end(sshpam_handle, sshpam_err); sshpam_handle = NULL; } static int sshpam_init(struct ssh *ssh, Authctxt *authctxt) { const char *pam_user, *user = authctxt->user; const char **ptr_pam_user = &pam_user; int r; if (options.pam_service_name == NULL) fatal_f("internal error: NULL PAM service name"); #if defined(PAM_SUN_CODEBASE) && defined(PAM_MAX_RESP_SIZE) /* Protect buggy PAM implementations from excessively long usernames */ if (strlen(user) >= PAM_MAX_RESP_SIZE) fatal("Username too long from %s port %d", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); #endif if (sshpam_handle == NULL) { if (ssh == NULL) { fatal("%s: called initially with no " "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); if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) return (0); pam_end(sshpam_handle, sshpam_err); sshpam_handle = NULL; } debug("PAM: initializing for \"%s\" with service \"%s\"", user, options.pam_service_name); sshpam_err = pam_start(options.pam_service_name, user, &store_conv, &sshpam_handle); sshpam_authctxt = authctxt; 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)); } 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); } } if (ssh != NULL && sshpam_laddr != NULL) { char *conninfo; /* Put SSH_CONNECTION in the PAM environment too */ xasprintf(&conninfo, "SSH_CONNECTION=%.50s %d %.50s %d", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), sshpam_laddr, ssh_local_port(ssh)); if ((r = pam_putenv(sshpam_handle, conninfo)) != PAM_SUCCESS) logit("pam_putenv: %s", pam_strerror(sshpam_handle, r)); free(conninfo); } #ifdef PAM_TTY_KLUDGE /* * Some silly PAM modules (e.g. pam_time) require a TTY to operate. * sshd doesn't set the tty until too late in the auth process and * may not even set one (for tty-less connections) */ debug("PAM: setting PAM_TTY to \"ssh\""); sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, "ssh"); if (sshpam_err != PAM_SUCCESS) { pam_end(sshpam_handle, sshpam_err); sshpam_handle = NULL; return (-1); } #endif 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 result, socks[2]; debug3("PAM: %s entering", __func__); /* * Refuse to start if we don't have PAM enabled or do_pam_account * has previously failed. */ if (!options.use_pam || sshpam_account_status == 0) return NULL; /* Initialize PAM */ if (sshpam_init(NULL, authctxt) == -1) { error("PAM: initialization failed"); return (NULL); } expose_authinfo(__func__); ctxt = xcalloc(1, sizeof *ctxt); /* Start the authentication thread */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) { error("PAM: failed create sockets: %s", strerror(errno)); free(ctxt); return (NULL); } ctxt->pam_psock = socks[0]; ctxt->pam_csock = socks[1]; result = pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt); if (result != 0) { error("PAM: failed to start authentication thread: %s", strerror(result)); close(socks[0]); close(socks[1]); free(ctxt); return (NULL); } cleanup_ctxt = ctxt; return (ctxt); } static int sshpam_query(void *ctx, char **name, char **info, u_int *num, char ***prompts, u_int **echo_on) { struct sshbuf *buffer; struct pam_ctxt *ctxt = ctx; size_t plen; u_char type; char *msg; size_t len, mlen, nmesg = 0; int r; debug3("PAM: %s entering", __func__); 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) { if (++nmesg > PAM_MAX_NUM_MSG) fatal_f("too many query messages"); if ((r = sshbuf_get_u8(buffer, &type)) != 0 || (r = sshbuf_get_cstring(buffer, &msg, &mlen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); switch (type) { case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_OFF: *num = 1; len = plen + mlen + 1; **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 = xreallocarray(**prompts, 1, len); strlcpy(**prompts + plen, msg, len - plen); plen += mlen; strlcat(**prompts + plen, "\n", len - plen); plen++; free(msg); break; case PAM_ACCT_EXPIRED: 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)); if (**prompts != NULL && strlen(**prompts) != 0) { free(*info); *info = **prompts; **prompts = NULL; *num = 0; **echo_on = 0; ctxt->pam_done = -1; free(msg); sshbuf_free(buffer); return 0; } /* FALLTHROUGH */ case PAM_SUCCESS: if (**prompts != NULL) { /* drain any accumulated messages */ debug("PAM: %s", **prompts); if ((r = sshbuf_put(loginmsg, **prompts, strlen(**prompts))) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(**prompts); **prompts = NULL; } if (type == PAM_SUCCESS) { if (!sshpam_authctxt->valid || (sshpam_authctxt->pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)) fatal("Internal error: PAM auth " "succeeded when it should have " "failed"); 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, 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) { struct sshbuf *buffer; struct pam_ctxt *ctxt = ctx; char *fake; int r; debug2("PAM: %s entering, %u responses", __func__, num); switch (ctxt->pam_done) { case 1: sshpam_authenticated = 1; return (0); case 0: break; default: return (-1); } if (num != 1) { error("PAM: expected one response, got %u", num); return (-1); } 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)) { 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); } sshbuf_free(buffer); return (1); } static void sshpam_free_ctx(void *ctxtp) { struct pam_ctxt *ctxt = ctxtp; debug3("PAM: %s entering", __func__); sshpam_thread_cleanup(); free(ctxt); /* * We don't call sshpam_cleanup() here because we may need the PAM * handle at a later stage, e.g. when setting up a session. It's * still on the cleanup list, so pam_end() *will* be called before * the server process terminates. */ } KbdintDevice sshpam_device = { "pam", sshpam_init_ctx, sshpam_query, sshpam_respond, sshpam_free_ctx }; KbdintDevice mm_sshpam_device = { "pam", mm_sshpam_init_ctx, mm_sshpam_query, mm_sshpam_respond, mm_sshpam_free_ctx }; /* * This replaces auth-pam.c */ void start_pam(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; if (!options.use_pam) fatal("PAM: initialisation requested when UsePAM=no"); if (sshpam_init(ssh, authctxt) == -1) fatal("PAM: initialisation failed"); } void finish_pam(void) { sshpam_cleanup(); } u_int do_pam_account(void) { debug("%s: called", __func__); 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)); if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { sshpam_account_status = 0; return (sshpam_account_status); } if (sshpam_err == PAM_NEW_AUTHTOK_REQD) sshpam_password_change_required(1); sshpam_account_status = 1; return (sshpam_account_status); } void do_pam_setcred(void) { sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&store_conv); if (sshpam_err != PAM_SUCCESS) fatal("PAM: failed to set PAM_CONV: %s", pam_strerror(sshpam_handle, sshpam_err)); debug("PAM: establishing credentials"); sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED); if (sshpam_err == PAM_SUCCESS) { sshpam_cred_established = 1; return; } if (sshpam_authenticated) fatal("PAM: pam_setcred(): %s", pam_strerror(sshpam_handle, sshpam_err)); else debug("PAM: pam_setcred(): %s", pam_strerror(sshpam_handle, sshpam_err)); } #if 0 static int sshpam_tty_conv(int n, sshpam_const struct pam_message **msg, struct pam_response **resp, void *data) { char input[PAM_MAX_MSG_SIZE]; struct pam_response *reply; int i; debug3("PAM: %s called with %d messages", __func__, n); *resp = NULL; if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO)) return (PAM_CONV_ERR); if ((reply = calloc(n, sizeof(*reply))) == NULL) return (PAM_CONV_ERR); for (i = 0; i < n; ++i) { switch (PAM_MSG_MEMBER(msg, i, msg_style)) { case PAM_PROMPT_ECHO_OFF: reply[i].resp = read_passphrase(PAM_MSG_MEMBER(msg, i, msg), RP_ALLOW_STDIN); reply[i].resp_retcode = PAM_SUCCESS; break; case PAM_PROMPT_ECHO_ON: fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg)); if (fgets(input, sizeof input, stdin) == NULL) input[0] = '\0'; if ((reply[i].resp = strdup(input)) == NULL) goto fail; reply[i].resp_retcode = PAM_SUCCESS; break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg)); reply[i].resp_retcode = PAM_SUCCESS; break; default: goto fail; } } *resp = reply; return (PAM_SUCCESS); fail: for(i = 0; i < n; i++) { free(reply[i].resp); } free(reply); return (PAM_CONV_ERR); } static struct pam_conv tty_conv = { sshpam_tty_conv, NULL }; #endif /* * XXX this should be done in the authentication phase, but ssh1 doesn't * support that */ void do_pam_chauthtok(void) { fatal("Password expired"); #if 0 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&tty_conv); if (sshpam_err != PAM_SUCCESS) fatal("PAM: failed to set PAM_CONV: %s", pam_strerror(sshpam_handle, sshpam_err)); debug("PAM: changing password"); sshpam_err = pam_chauthtok(sshpam_handle, PAM_CHANGE_EXPIRED_AUTHTOK); if (sshpam_err != PAM_SUCCESS) fatal("PAM: pam_chauthtok(): %s", pam_strerror(sshpam_handle, sshpam_err)); #endif } 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) fatal("PAM: failed to set PAM_CONV: %s", pam_strerror(sshpam_handle, sshpam_err)); sshpam_err = pam_open_session(sshpam_handle, 0); if (sshpam_err == PAM_SUCCESS) sshpam_session_open = 1; else { sshpam_session_open = 0; auth_restrict_session(ssh); error("PAM: pam_open_session(): %s", pam_strerror(sshpam_handle, sshpam_err)); } } int is_pam_session_open(void) { return sshpam_session_open; } /* * Set a PAM environment string. We need to do this so that the session * modules can handle things like Kerberos/GSI credentials that appear * during the ssh authentication process. */ int do_pam_putenv(char *name, char *value) { int ret = 1; char *compound; size_t len; len = strlen(name) + strlen(value) + 2; compound = xmalloc(len); snprintf(compound, len, "%s=%s", name, value); ret = pam_putenv(sshpam_handle, compound); free(compound); return (ret); } char ** fetch_pam_child_environment(void) { return sshpam_env; } char ** fetch_pam_environment(void) { return (pam_getenvlist(sshpam_handle)); } void free_pam_environment(char **env) { char **envp; if (env == NULL) return; for (envp = env; *envp; envp++) free(*envp); free(env); } /* * "Blind" conversation function for password authentication. Assumes that * echo-off prompts are for the password and stores messages for later * display. */ static int sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg, struct pam_response **resp, void *data) { struct pam_response *reply; int r, i; size_t len; debug3("PAM: %s called with %d messages", __func__, n); *resp = NULL; if (n <= 0 || n > PAM_MAX_NUM_MSG) return (PAM_CONV_ERR); if ((reply = calloc(n, sizeof(*reply))) == NULL) return (PAM_CONV_ERR); for (i = 0; i < n; ++i) { switch (PAM_MSG_MEMBER(msg, i, msg_style)) { case PAM_PROMPT_ECHO_OFF: if (sshpam_password == NULL) goto fail; if ((reply[i].resp = strdup(sshpam_password)) == NULL) goto fail; reply[i].resp_retcode = PAM_SUCCESS; break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: len = strlen(PAM_MSG_MEMBER(msg, i, msg)); if (len > 0) { 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; reply[i].resp_retcode = PAM_SUCCESS; break; default: goto fail; } } *resp = reply; return (PAM_SUCCESS); fail: for(i = 0; i < n; i++) { free(reply[i].resp); } free(reply); return (PAM_CONV_ERR); } static struct pam_conv passwd_conv = { sshpam_passwd_conv, NULL }; /* * Attempt password authentication via PAM */ int 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 " "initialise.", __func__); sshpam_password = password; sshpam_authctxt = authctxt; /* * If the user logging in is invalid, or is root but is not permitted * by PermitRootLogin, use an invalid password to prevent leaking * information via timing (eg if the PAM config has a delay on fail). */ if (!authctxt->valid || (authctxt->pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)) sshpam_password = fake = fake_password(password); sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&passwd_conv); if (sshpam_err != PAM_SUCCESS) fatal("PAM: %s: failed to set PAM_CONV: %s", __func__, pam_strerror(sshpam_handle, sshpam_err)); expose_authinfo(__func__); 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); return 1; } else { debug("PAM: password authentication failed for %.100s: %s", authctxt->valid ? authctxt->user : "an illegal user", pam_strerror(sshpam_handle, sshpam_err)); 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; } #endif /* USE_PAM */ openssh-10.0p1/PaxHeaders.10889/auth-pam.h100644 001750 001750 0000000003614775415623 0015041xustar0030 atime=1744182234.470531842 openssh-10.0p1/auth-pam.h010064400017500001750000000036151477541562300134310ustar00djmdjm/* * Copyright (c) 2000 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" #ifdef USE_PAM struct ssh; void start_pam(struct ssh *); void finish_pam(void); u_int do_pam_account(void); void do_pam_session(struct ssh *); void do_pam_setcred(void); void do_pam_chauthtok(void); int do_pam_putenv(char *, char *); char ** fetch_pam_environment(void); char ** fetch_pam_child_environment(void); 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 */ openssh-10.0p1/PaxHeaders.10889/auth-passwd.c100644 001750 001750 0000000003614775415623 0015560xustar0030 atime=1744182234.470531842 openssh-10.0p1/auth-passwd.c010064400017500001750000000145771477541562300141610ustar00djmdjm/* $OpenBSD: auth-passwd.c,v 1.48 2020/10/18 11:32:01 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Password authentication. This file contains the functions to check whether * the password is valid for the user. * * 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 Dug Song. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include "packet.h" #include "sshbuf.h" #include "ssherr.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "auth-options.h" extern struct sshbuf *loginmsg; extern ServerOptions options; #ifdef HAVE_LOGIN_CAP extern login_cap_t *lc; #endif #define DAY (24L * 60 * 60) /* 1 day in seconds */ #define TWO_WEEKS (2L * 7 * DAY) /* 2 weeks in seconds */ #define MAX_PASSWORD_LEN 1024 /* * Tries to authenticate the user using password. Returns true if * authentication succeeds. */ int auth_password(struct ssh *ssh, const char *password) { 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; #endif if (*password == '\0' && options.permit_empty_passwd == 0) return 0; #ifdef KRB5 if (options.kerberos_authentication == 1) { int ret = auth_krb5_password(authctxt, password); if (ret == 1 || ret == 0) return ret && ok; /* Fall back to ordinary passwd authentication. */ } #endif #ifdef HAVE_CYGWIN { HANDLE hToken = cygwin_logon_user(pw, password); if (hToken == INVALID_HANDLE_VALUE) return 0; cygwin_set_impersonation_token(hToken); return ok; } #endif #ifdef USE_PAM if (options.use_pam) return (sshpam_auth_passwd(authctxt, password) && ok); #endif #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) if (!expire_checked) { expire_checked = 1; if (auth_shadow_pwexpired(authctxt)) authctxt->force_pwchange = 1; } #endif result = sys_auth_passwd(ssh, password); if (authctxt->force_pwchange) auth_restrict_session(ssh); return (result && ok); } #ifdef BSD_AUTH static void warn_expiry(Authctxt *authctxt, auth_session_t *as) { int r; quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime; pwwarntime = acwarntime = TWO_WEEKS; pwtimeleft = auth_check_change(as); actimeleft = auth_check_expire(as); #ifdef HAVE_LOGIN_CAP if (authctxt->valid) { pwwarntime = login_getcaptime(lc, "password-warn", TWO_WEEKS, TWO_WEEKS); acwarntime = login_getcaptime(lc, "expire-warn", TWO_WEEKS, TWO_WEEKS); } #endif if (pwtimeleft != 0 && pwtimeleft < pwwarntime) { daysleft = pwtimeleft / DAY + 1; if ((r = sshbuf_putf(loginmsg, "Your password will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) fatal_fr(r, "buffer error"); } if (actimeleft != 0 && actimeleft < acwarntime) { daysleft = actimeleft / DAY + 1; if ((r = sshbuf_putf(loginmsg, "Your account will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) fatal_fr(r, "buffer error"); } } int sys_auth_passwd(struct ssh *ssh, const char *password) { Authctxt *authctxt = ssh->authctxt; auth_session_t *as; static int expire_checked = 0; 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); auth_restrict_session(ssh); authctxt->force_pwchange = 1; return (1); } else { if (!expire_checked) { expire_checked = 1; warn_expiry(authctxt, as); } return (auth_close(as)); } } #elif !defined(CUSTOM_SYS_AUTH_PASSWD) int sys_auth_passwd(struct ssh *ssh, const char *password) { Authctxt *authctxt = ssh->authctxt; struct passwd *pw = authctxt->pw; 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, 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 * are identical. */ return encrypted_password != NULL && strcmp(encrypted_password, pw_password) == 0; } #endif openssh-10.0p1/PaxHeaders.10889/auth-rhosts.c100644 001750 001750 0000000003614775415623 0015601xustar0030 atime=1744182234.471508289 openssh-10.0p1/auth-rhosts.c010064400017500001750000000222511477541562300141660ustar00djmdjm/* $OpenBSD: auth-rhosts.c,v 1.58 2024/05/17 00:30:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Rhosts authentication. This file contains code to check whether to admit * the login based on rhosts authentication. This file also processes * /etc/hosts.equiv. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #ifdef HAVE_NETGROUP_H # include #endif #include #include #include #include #include #include #include "packet.h" #include "uidswap.h" #include "pathnames.h" #include "log.h" #include "misc.h" #include "xmalloc.h" #include "sshbuf.h" #include "sshkey.h" #include "servconf.h" #include "canohost.h" #include "hostfile.h" #include "auth.h" /* import */ extern ServerOptions options; /* * This function processes an rhosts-style file (.rhosts, .shosts, or * /etc/hosts.equiv). This returns true if authentication can be granted * based on the file, and returns zero otherwise. */ static int check_rhosts_file(const char *filename, const char *hostname, const char *ipaddr, const char *client_user, const char *server_user) { FILE *f; #define RBUFLN 1024 char buf[RBUFLN];/* Must not be larger than host, user, dummy below. */ int fd; struct stat st; /* Open the .rhosts file, deny if unreadable */ if ((fd = open(filename, O_RDONLY|O_NONBLOCK)) == -1) return 0; if (fstat(fd, &st) == -1) { close(fd); return 0; } if (!S_ISREG(st.st_mode)) { logit("User %s hosts file %s is not a regular file", server_user, filename); close(fd); return 0; } unset_nonblock(fd); if ((f = fdopen(fd, "r")) == NULL) { close(fd); return 0; } while (fgets(buf, sizeof(buf), f)) { /* All three must have length >= buf to avoid overflows. */ char hostbuf[RBUFLN], userbuf[RBUFLN], dummy[RBUFLN]; char *host, *user, *cp; int negated; for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) ; if (*cp == '#' || *cp == '\n' || !*cp) continue; /* * NO_PLUS is supported at least on OSF/1. We skip it (we * don't ever support the plus syntax). */ if (strncmp(cp, "NO_PLUS", 7) == 0) continue; /* * This should be safe because each buffer is as big as the * whole string, and thus cannot be overwritten. */ switch (sscanf(buf, "%1023s %1023s %1023s", hostbuf, userbuf, dummy)) { case 0: auth_debug_add("Found empty line in %.100s.", filename); continue; case 1: /* Host name only. */ strlcpy(userbuf, server_user, sizeof(userbuf)); break; case 2: /* Got both host and user name. */ break; case 3: auth_debug_add("Found garbage in %.100s.", filename); continue; default: /* Weird... */ continue; } host = hostbuf; user = userbuf; negated = 0; /* Process negated host names, or positive netgroups. */ if (host[0] == '-') { negated = 1; host++; } else if (host[0] == '+') host++; if (user[0] == '-') { negated = 1; user++; } else if (user[0] == '+') user++; /* Check for empty host/user names (particularly '+'). */ if (!host[0] || !user[0]) { /* We come here if either was '+' or '-'. */ auth_debug_add("Ignoring wild host/user names " "in %.100s.", filename); continue; } /* Verify that host name matches. */ if (host[0] == '@') { if (!innetgr(host + 1, hostname, NULL, NULL) && !innetgr(host + 1, ipaddr, NULL, NULL)) continue; } else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0) continue; /* Different hostname. */ /* Verify that user name matches. */ if (user[0] == '@') { if (!innetgr(user + 1, NULL, client_user, NULL)) continue; } else if (strcmp(user, client_user) != 0) continue; /* Different username. */ /* Found the user and host. */ fclose(f); /* If the entry was negated, deny access. */ if (negated) { auth_debug_add("Matched negative entry in %.100s.", filename); return 0; } /* Accept authentication. */ return 1; } /* Authentication using this file denied. */ fclose(f); return 0; } /* * Tries to authenticate the user using the .shosts or .rhosts file. Returns * true if authentication succeeds. If ignore_rhosts is true, only * /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored). */ int auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, const char *ipaddr) { char *path = NULL; struct stat st; static const char * const rhosts_files[] = {".shosts", ".rhosts", NULL}; u_int rhosts_file_index; int r; debug2_f("clientuser %s hostname %s ipaddr %s", client_user, hostname, ipaddr); /* Switch to the user's uid. */ temporarily_use_uid(pw); /* * Quick check: if the user has no .shosts or .rhosts files and * no system hosts.equiv/shosts.equiv files exist then return * failure immediately without doing costly lookups from name * servers. */ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; rhosts_file_index++) { /* Check users .rhosts or .shosts. */ xasprintf(&path, "%s/%s", pw->pw_dir, rhosts_files[rhosts_file_index]); r = stat(path, &st); free(path); if (r >= 0) break; } /* Switch back to privileged uid. */ restore_uid(); /* * Deny if The user has no .shosts or .rhosts file and there * are no system-wide files. */ if (!rhosts_files[rhosts_file_index] && stat(_PATH_RHOSTS_EQUIV, &st) == -1 && stat(_PATH_SSH_HOSTS_EQUIV, &st) == -1) { debug3_f("no hosts access files exist"); return 0; } /* * If not logging in as superuser, try /etc/hosts.equiv and * shosts.equiv. */ if (pw->pw_uid == 0) debug3_f("root user, ignoring system hosts files"); else { if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, client_user, pw->pw_name)) { auth_debug_add("Accepted for %.100s [%.100s] by " "/etc/hosts.equiv.", hostname, ipaddr); return 1; } if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, client_user, pw->pw_name)) { auth_debug_add("Accepted for %.100s [%.100s] by " "%.100s.", hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); return 1; } } /* * 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) == -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: " "no home directory %.200s", pw->pw_name, pw->pw_dir); return 0; } if (options.strict_modes && ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || (st.st_mode & 022) != 0)) { logit("Rhosts authentication refused for %.100s: " "bad ownership or modes for home directory.", pw->pw_name); auth_debug_add("Rhosts authentication refused for %.100s: " "bad ownership or modes for home directory.", pw->pw_name); return 0; } /* Temporarily use the user's uid. */ temporarily_use_uid(pw); /* Check all .rhosts files (currently .shosts and .rhosts). */ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; rhosts_file_index++) { /* Check users .rhosts or .shosts. */ xasprintf(&path, "%s/%s", pw->pw_dir, rhosts_files[rhosts_file_index]); if (stat(path, &st) == -1) { debug3_f("stat %s: %s", path, strerror(errno)); free(path); continue; } /* * Make sure that the file is either owned by the user or by * root, and make sure it is not writable by anyone but the * owner. This is to help avoid novices accidentally * allowing access to their account by anyone. */ if (options.strict_modes && ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || (st.st_mode & 022) != 0)) { logit("Rhosts authentication refused for %.100s: " "bad modes for %.200s", pw->pw_name, path); auth_debug_add("Bad file modes for %.200s", path); free(path); continue; } /* * Check if we have been configured to ignore .rhosts * and .shosts files. */ 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]); free(path); continue; } /* Check if authentication is permitted by the file. */ if (check_rhosts_file(path, hostname, ipaddr, client_user, pw->pw_name)) { auth_debug_add("Accepted by %.100s.", rhosts_files[rhosts_file_index]); /* Restore the privileged uid. */ restore_uid(); auth_debug_add("Accepted host %s ip %s client_user " "%s server_user %s", hostname, ipaddr, client_user, pw->pw_name); free(path); return 1; } free(path); } /* Restore the privileged uid. */ restore_uid(); return 0; } openssh-10.0p1/PaxHeaders.10889/auth-shadow.c100644 001750 001750 0000000003614775415623 0015544xustar0030 atime=1744182234.471508289 openssh-10.0p1/auth-shadow.c010064400017500001750000000104521477541562300141310ustar00djmdjm/* * Copyright (c) 2004 Darren Tucker. 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(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) #include #include #include #include #include "hostfile.h" #include "auth.h" #include "sshbuf.h" #include "ssherr.h" #include "log.h" #ifdef DAY # undef DAY #endif #define DAY (24L * 60 * 60) /* 1 day in seconds */ extern struct sshbuf *loginmsg; /* * For the account and password expiration functions, we assume the expiry * occurs the day after the day specified. */ /* * Check if specified account is expired. Returns 1 if account is expired, * 0 otherwise. */ int auth_shadow_acctexpired(struct spwd *spw) { time_t today; long long daysleft; int r; today = time(NULL) / DAY; daysleft = spw->sp_expire - today; debug3("%s: today %lld sp_expire %lld days left %lld", __func__, (long long)today, (long long)spw->sp_expire, daysleft); if (spw->sp_expire == -1) { debug3("account expiration disabled"); } else if (daysleft < 0) { logit("Account %.100s has expired", spw->sp_namp); return 1; } else if (daysleft <= spw->sp_warn) { debug3("account will expire in %lld days", daysleft); if ((r = sshbuf_putf(loginmsg, "Your account will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } return 0; } /* * Checks password expiry for platforms that use shadow passwd files. * Returns: 1 = password expired, 0 = password not expired */ int auth_shadow_pwexpired(Authctxt *ctxt) { struct spwd *spw = NULL; const char *user = ctxt->pw->pw_name; time_t today; int r, daysleft, disabled = 0; if ((spw = getspnam((char *)user)) == NULL) { error("Could not get shadow information for %.100s", user); return 0; } today = time(NULL) / DAY; debug3_f("today %lld sp_lstchg %lld sp_max %lld", (long long)today, (long long)spw->sp_lstchg, (long long)spw->sp_max); #if defined(__hpux) && !defined(HAVE_SECUREWARE) if (iscomsec()) { struct pr_passwd *pr; pr = getprpwnam((char *)user); /* Test for Trusted Mode expiry disabled */ if (pr != NULL && pr->ufld.fd_min == 0 && pr->ufld.fd_lifetime == 0 && pr->ufld.fd_expire == 0 && pr->ufld.fd_pw_expire_warning == 0 && pr->ufld.fd_schange != 0) disabled = 1; } #endif /* TODO: check sp_inact */ daysleft = spw->sp_lstchg + spw->sp_max - today; if (disabled) { debug3("password expiration disabled"); } else if (spw->sp_lstchg == 0) { logit("User %.100s password has expired (root forced)", user); return 1; } else if (spw->sp_max == -1) { debug3("password expiration disabled"); } else if (daysleft < 0) { logit("User %.100s password has expired (password aged)", user); return 1; } else if (daysleft <= spw->sp_warn) { debug3("password will expire in %d days", daysleft); if ((r = sshbuf_putf(loginmsg, "Your password will expire in %d day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } return 0; } #endif /* USE_SHADOW && HAS_SHADOW_EXPIRE */ openssh-10.0p1/PaxHeaders.10889/auth-sia.c100644 001750 001750 0000000003614775415623 0015033xustar0030 atime=1744182234.471508289 openssh-10.0p1/auth-sia.c010064400017500001750000000062321477541562300134210ustar00djmdjm/* * Copyright (c) 2002 Chris Adams. 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 HAVE_OSF_SIA #include #include #include #include #include #include #include #include #include #include "ssh.h" #include "ssh_api.h" #include "hostfile.h" #include "auth.h" #include "auth-sia.h" #include "log.h" #include "servconf.h" #include "canohost.h" #include "uidswap.h" extern ServerOptions options; extern int saved_argc; extern char **saved_argv; int 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); if (!authctxt->user || pass == NULL || pass[0] == '\0') return (0); if (sia_ses_init(&ent, saved_argc, saved_argv, host, authctxt->user, NULL, 0, NULL) != SIASUCCESS) return (0); if ((ret = sia_ses_authent(NULL, pass, ent)) != SIASUCCESS) { error("Couldn't authenticate %s from %s", authctxt->user, host); if (ret & SIASTOP) sia_ses_release(&ent); return (0); } sia_ses_release(&ent); return (1); } void session_setup_sia(struct passwd *pw, char *tty) { SIAENTITY *ent = NULL; const char *host; host = get_canonical_hostname(options.use_dns); if (sia_ses_init(&ent, saved_argc, saved_argv, host, pw->pw_name, tty, 0, NULL) != SIASUCCESS) fatal("sia_ses_init failed"); if (sia_make_entity_pwd(pw, ent) != SIASUCCESS) { sia_ses_release(&ent); fatal("sia_make_entity_pwd failed"); } ent->authtype = SIA_A_NONE; if (sia_ses_estab(sia_collect_trm, ent) != SIASUCCESS) fatal("Couldn't establish session for %s from %s", pw->pw_name, host); if (sia_ses_launch(sia_collect_trm, ent) != SIASUCCESS) fatal("Couldn't launch session for %s from %s", pw->pw_name, host); sia_ses_release(&ent); setuid(0); permanently_set_uid(pw); } #endif /* HAVE_OSF_SIA */ openssh-10.0p1/PaxHeaders.10889/auth-sia.h100644 001750 001750 0000000003614775415623 0015040xustar0030 atime=1744182234.471508289 openssh-10.0p1/auth-sia.h010064400017500001750000000026331477541562300134270ustar00djmdjm/* * Copyright (c) 2002 Chris Adams. 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 HAVE_OSF_SIA void session_setup_sia(struct passwd *, char *); #endif /* HAVE_OSF_SIA */ openssh-10.0p1/PaxHeaders.10889/auth.c100644 001750 001750 0000000003614775415623 0014261xustar0030 atime=1744182234.472485017 openssh-10.0p1/auth.c010064400017500001750000000524611477541562300126540ustar00djmdjm/* $OpenBSD: auth.c,v 1.162 2024/09/15 01:18:26 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #ifdef HAVE_LOGIN_H #include #endif #ifdef USE_SHADOW #include #endif #include #include #include #include #include #include #include #include "xmalloc.h" #include "match.h" #include "groupaccess.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "servconf.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "auth-options.h" #include "canohost.h" #include "uidswap.h" #include "packet.h" #include "loginrec.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "authfile.h" #include "monitor_wrap.h" #include "ssherr.h" #include "channels.h" /* import */ extern ServerOptions options; extern struct include_list includes; extern struct sshbuf *loginmsg; extern struct passwd *privsep_pw; extern struct sshauthopt *auth_opts; /* Debugging messages */ static struct sshbuf *auth_debug; /* * Check if the user is allowed to log in via ssh. If user is listed * in DenyUsers or one of user's groups is listed in DenyGroups, false * will be returned. If AllowUsers isn't empty and user isn't listed * there, or if AllowGroups isn't empty and one of user's groups isn't * listed there, false will be returned. * If the user's shell is not executable, false will be returned. * Otherwise true is returned. */ int allowed_user(struct ssh *ssh, struct passwd * pw) { struct stat st; const char *hostname = NULL, *ipaddr = NULL; u_int i; int r; /* Shouldn't be called if pw is NULL, but better safe than sorry... */ if (!pw || !pw->pw_name) return 0; if (!options.use_pam && platform_locked_account(pw)) { logit("User %.100s not allowed because account is locked", pw->pw_name); return 0; } /* * Deny if shell does not exist or is not executable unless we * are chrooting. */ if (options.chroot_directory == NULL || strcasecmp(options.chroot_directory, "none") == 0) { char *shell = xstrdup((pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */ if (stat(shell, &st) == -1) { logit("User %.100s not allowed because shell %.100s " "does not exist", pw->pw_name, shell); free(shell); return 0; } if (S_ISREG(st.st_mode) == 0 || (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { logit("User %.100s not allowed because shell %.100s " "is not executable", pw->pw_name, shell); free(shell); return 0; } free(shell); } if (options.num_deny_users > 0 || options.num_allow_users > 0 || options.num_deny_groups > 0 || options.num_allow_groups > 0) { 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++) { 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++) { 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 " "not listed in AllowUsers", pw->pw_name, hostname); return 0; } } if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { /* Get the user's group access list (primary and supplementary) */ if (ga_init(pw->pw_name, pw->pw_gid) == 0) { logit("User %.100s from %.100s not allowed because " "not in any group", pw->pw_name, hostname); return 0; } /* Return false if one of user's groups is listed in DenyGroups */ if (options.num_deny_groups > 0) if (ga_match(options.deny_groups, options.num_deny_groups)) { ga_free(); logit("User %.100s from %.100s not allowed " "because a group is listed in DenyGroups", pw->pw_name, hostname); return 0; } /* * Return false if AllowGroups isn't empty and one of user's groups * isn't listed there */ if (options.num_allow_groups > 0) if (!ga_match(options.allow_groups, options.num_allow_groups)) { ga_free(); logit("User %.100s from %.100s not allowed " "because none of user's groups are listed " "in AllowGroups", pw->pw_name, hostname); return 0; } ga_free(); } #ifdef CUSTOM_SYS_AUTH_ALLOWED_USER if (!sys_auth_allowed_user(pw, loginmsg)) return 0; #endif /* We found no reason not to let this user try to log on... */ return 1; } /* * 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) { const struct sshkey *key = authctxt->auth_method_key; const char *methinfo = authctxt->auth_method_info; char *fp, *cafp, *ret = NULL; if (key == NULL) return NULL; 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(struct ssh *ssh, int authenticated, int partial, const char *method, const char *submethod) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; int level = SYSLOG_LEVEL_VERBOSE; const char *authmsg; char *extra = NULL; if (!mm_is_monitor() && !authctxt->postponed) return; /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || authctxt->failures >= options.max_authtries / 2 || strcmp(method, "password") == 0) level = SYSLOG_LEVEL_INFO; if (authctxt->postponed) authmsg = "Postponed"; else if (partial) authmsg = "Partial"; else authmsg = authenticated ? "Accepted" : "Failed"; 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, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), extra != NULL ? ": " : "", extra != NULL ? extra : ""); free(extra); #if defined(CUSTOM_FAILED_LOGIN) || defined(SSH_AUDIT_EVENTS) if (authenticated == 0 && !(authctxt->postponed || partial)) { /* Log failed login attempt */ # ifdef CUSTOM_FAILED_LOGIN if (strcmp(method, "password") == 0 || strncmp(method, "keyboard-interactive", 20) == 0 || strcmp(method, "challenge-response") == 0) record_failed_login(ssh, authctxt->user, auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); # endif # ifdef SSH_AUDIT_EVENTS audit_event(ssh, audit_classify_auth(method)); # endif } #endif #if defined(CUSTOM_FAILED_LOGIN) && defined(WITH_AIXAUTHENTICATE) if (authenticated) sys_auth_record_login(authctxt->user, auth_get_canonical_hostname(ssh, options.use_dns), "ssh", loginmsg); #endif } void auth_maxtries_exceeded(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; error("maximum authentication attempts exceeded for " "%s%.100s from %.200s port %d ssh2", authctxt->valid ? "" : "invalid user ", authctxt->user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); ssh_packet_disconnect(ssh, "Too many authentication failures"); /* NOTREACHED */ } /* * Check whether root logins are disallowed. */ int 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, "publickey") == 0 || strcmp(method, "hostbased") == 0 || strcmp(method, "gssapi-with-mic") == 0) return 1; break; case PERMIT_FORCED_ONLY: if (auth_opts->force_command != NULL) { logit("Root login accepted for forced command."); return 1; } break; } logit("ROOT LOGIN REFUSED FROM %.200s port %d", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); return 0; } /* * Given a template and a passwd structure, build a filename * by substituting % tokenised options. Currently, %% becomes '%', * %h becomes the home directory and %u the username. * * This returns a buffer allocated by xmalloc. */ char * expand_authorized_keys(const char *filename, struct passwd *pw) { 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, "U", uidstr, (char *)NULL); /* * Ensure that filename starts anchored. If not, be backward * compatible and prepend the '%h/' */ if (path_absolute(file)) return (file); i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file); if (i < 0 || (size_t)i >= sizeof(ret)) fatal("expand_authorized_keys: path too long"); free(file); return (xstrdup(ret)); } char * authorized_principals_file(struct passwd *pw) { 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, struct sshkey *key, const char *host, const char *sysfile, const char *userfile) { char *user_hostfile; struct stat st; HostStatus host_status; struct hostkeys *hostkeys; const struct hostkey_entry *found; hostkeys = init_hostkeys(); load_hostkeys(hostkeys, host, sysfile, 0); if (userfile != NULL) { user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); if (options.strict_modes && (stat(user_hostfile, &st) == 0) && ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || (st.st_mode & 022) != 0)) { logit("Authentication refused for %.100s: " "bad owner or modes for %.200s", pw->pw_name, user_hostfile); auth_debug_add("Ignored %.200s: bad ownership or modes", user_hostfile); } else { temporarily_use_uid(pw); load_hostkeys(hostkeys, host, user_hostfile, 0); restore_uid(); } free(user_hostfile); } host_status = check_key_in_hostkeys(hostkeys, key, &found); if (host_status == HOST_REVOKED) error("WARNING: revoked key for %s attempted authentication", host); else if (host_status == HOST_OK) debug_f("key for %s found at %s:%ld", found->host, found->file, found->line); else debug_f("key for host %s not found", host); free_hostkeys(hostkeys); return host_status; } struct passwd * getpwnamallow(struct ssh *ssh, const char *user) { #ifdef HAVE_LOGIN_CAP extern login_cap_t *lc; #ifdef HAVE_AUTH_HOSTOK const char *from_host, *from_ip; #endif #ifdef BSD_AUTH auth_session_t *as; #endif #endif struct passwd *pw; struct connection_info *ci; u_int i; ci = server_get_connection_info(ssh, 1, options.use_dns); ci->user = user; ci->user_invalid = getpwnam(user) == NULL; parse_server_match_config(&options, &includes, ci); log_change_level(options.log_level); log_verbose_reset(); for (i = 0; i < options.num_log_verbose; i++) log_verbose_add(options.log_verbose[i]); server_process_permitopen(ssh); #if defined(_AIX) && defined(HAVE_SETAUTHDB) aix_setauthdb(user); #endif pw = getpwnam(user); #if defined(_AIX) && defined(HAVE_SETAUTHDB) aix_restoreauthdb(); #endif if (pw == NULL) { logit("Invalid user %.100s from %.100s port %d", user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); #ifdef CUSTOM_FAILED_LOGIN record_failed_login(ssh, user, auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); #endif #ifdef SSH_AUDIT_EVENTS audit_event(ssh, SSH_INVALID_USER); #endif /* SSH_AUDIT_EVENTS */ return (NULL); } if (!allowed_user(ssh, pw)) return (NULL); #ifdef HAVE_LOGIN_CAP if ((lc = login_getpwclass(pw)) == NULL) { debug("unable to get login class: %s", user); return (NULL); } #ifdef HAVE_AUTH_HOSTOK from_host = auth_get_canonical_hostname(ssh, options.use_dns); from_ip = ssh_remote_ipaddr(ssh); if (!auth_hostok(lc, from_host, from_ip)) { debug("Denied connection for %.200s from %.200s [%.200s].", pw->pw_name, from_host, from_ip); return (NULL); } #endif /* HAVE_AUTH_HOSTOK */ #ifdef HAVE_AUTH_TIMEOK if (!auth_timeok(lc, time(NULL))) { debug("LOGIN %.200s REFUSED (TIME)", pw->pw_name); return (NULL); } #endif /* HAVE_AUTH_TIMEOK */ #ifdef BSD_AUTH if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 || auth_approval(as, lc, pw->pw_name, "ssh") <= 0) { debug("Approval failure for %s", user); pw = NULL; } if (as != NULL) auth_close(as); #endif #endif if (pw != NULL) return (pwcopy(pw)); return (NULL); } /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */ int auth_key_is_revoked(struct sshkey *key) { char *fp = NULL; int r; if (options.revoked_keys_file == NULL) return 0; if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { r = SSH_ERR_ALLOC_FAIL; error_fr(r, "fingerprint key"); goto out; } r = sshkey_check_revoked(key, options.revoked_keys_file); switch (r) { case 0: break; /* not revoked */ case SSH_ERR_KEY_REVOKED: error("Authentication key %s %s revoked by file %s", sshkey_type(key), fp, options.revoked_keys_file); goto out; default: error_r(r, "Error checking authentication key %s %s in " "revoked keys file %s", sshkey_type(key), fp, options.revoked_keys_file); goto out; } /* Success */ r = 0; out: free(fp); return r == 0 ? 0 : 1; } void auth_debug_add(const char *fmt,...) { char buf[1024]; va_list args; int r; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); debug3("%s", buf); if (auth_debug != NULL) if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0) fatal_fr(r, "sshbuf_put_cstring"); } void auth_debug_send(struct ssh *ssh) { char *msg; int r; if (auth_debug == NULL) return; while (sshbuf_len(auth_debug) != 0) { if ((r = sshbuf_get_cstring(auth_debug, &msg, NULL)) != 0) fatal_fr(r, "sshbuf_get_cstring"); ssh_packet_send_debug(ssh, "%s", msg); free(msg); } } void auth_debug_reset(void) { if (auth_debug != NULL) sshbuf_reset(auth_debug); else if ((auth_debug = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); } struct passwd * fakepw(void) { static int done = 0; static struct passwd fake; const char hashchars[] = "./ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz0123456789"; /* from bcrypt.c */ char *cp; if (done) return (&fake); memset(&fake, 0, sizeof(fake)); fake.pw_name = "NOUSER"; fake.pw_passwd = xstrdup("$2a$10$" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); for (cp = fake.pw_passwd + 7; *cp != '\0'; cp++) *cp = hashchars[arc4random_uniform(sizeof(hashchars) - 1)]; #ifdef HAVE_STRUCT_PASSWD_PW_GECOS fake.pw_gecos = "NOUSER"; #endif fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid; fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid; #ifdef HAVE_STRUCT_PASSWD_PW_CLASS fake.pw_class = ""; #endif fake.pw_dir = "/nonexist"; fake.pw_shell = "/nonexist"; done = 1; return (&fake); } /* * 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); if (dnsname != NULL) return dnsname; dnsname = ssh_remote_hostname(ssh); return dnsname; } /* 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%s", opts->permit_agent_forwarding_flag ? " agent-forwarding" : "", opts->force_command == NULL ? "" : " command", do_env ? " environment" : "", opts->valid_before == 0 ? "" : "expires", opts->no_require_user_presence ? " no-touch-required" : "", do_permitopen ? " permitopen" : "", do_permitlisten ? " permitlisten" : "", opts->permit_port_forwarding_flag ? " port-forwarding" : "", opts->cert_principals == NULL ? "" : " principals", opts->permit_pty_flag ? " pty" : "", opts->require_verify ? " uv" : "", opts->force_tun_device == -1 ? "" : " tun=", opts->force_tun_device == -1 ? "" : buf, opts->permit_user_rc ? " user-rc" : "", opts->permit_x11_forwarding_flag ? " x11-forwarding" : ""); 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_f("setting new authentication options"); 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_f("restricting session"); /* A blank sshauthopt defaults to permitting nothing */ if ((restricted = sshauthopt_new()) == NULL) fatal_f("sshauthopt_new failed"); restricted->permit_pty_flag = 1; restricted->restricted = 1; if (auth_activate_options(ssh, restricted) != 0) fatal_f("failed to restrict session"); sshauthopt_free(restricted); } openssh-10.0p1/PaxHeaders.10889/auth.h100644 001750 001750 0000000003614775415623 0014266xustar0030 atime=1744182234.472485017 openssh-10.0p1/auth.h010064400017500001750000000201601477541562300126500ustar00djmdjm/* $OpenBSD: auth.h,v 1.108 2024/05/17 06:42:04 jsg 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. * */ #ifndef AUTH_H #define AUTH_H #include #include #ifdef HAVE_LOGIN_CAP #include #endif #ifdef BSD_AUTH #include #endif #ifdef KRB5 #include #endif struct passwd; struct ssh; struct sshbuf; struct sshkey; struct sshkey_cert; struct sshauthopt; typedef struct Authctxt Authctxt; typedef struct Authmethod Authmethod; typedef struct KbdintDevice KbdintDevice; struct Authctxt { sig_atomic_t success; int authenticated; /* authenticated and alarms cancelled */ int postponed; /* authentication needs another step */ int valid; /* user exists and is allowed to login */ int attempt; int failures; 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; #ifdef BSD_AUTH auth_session_t *as; #endif #ifdef KRB5 krb5_context krb5_ctx; krb5_ccache krb5_fwd_ccache; krb5_principal krb5_user; char *krb5_ticket_file; char *krb5_ccname; #endif 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; /* 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 * case 'valid' is set to 0, but 'user' points to the username requested by * the client. */ struct authmethod_cfg { const char *name; const char *synonym; int *enabled; }; struct Authmethod { struct authmethod_cfg *cfg; int (*userauth)(struct ssh *, const char *); }; /* * Keyboard interactive device: * init_ctx returns: non NULL upon success * query returns: 0 - success, otherwise failure * respond returns: 0 - success, 1 - need further interaction, * otherwise - failure */ struct KbdintDevice { const char *name; void* (*init_ctx)(Authctxt*); int (*query)(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on); int (*respond)(void *ctx, u_int numresp, char **responses); void (*free_ctx)(void *ctx); }; int auth_rhosts2(struct passwd *, const char *, const char *, const char *); 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 *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_password(Authctxt *authctxt, const char *password); void krb5_cleanup_proc(Authctxt *authctxt); #endif /* KRB5 */ #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) #include int auth_shadow_acctexpired(struct spwd *); int auth_shadow_pwexpired(Authctxt *); #endif #include "auth-pam.h" #include "audit.h" void remove_kbdint_device(const char *); void do_authentication2(struct ssh *); 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); int auth2_update_methods_lists(Authctxt *, const char *, const char *); int auth2_setup_methods_lists(Authctxt *); int auth2_method_allowed(Authctxt *, const char *, const char *); void privsep_challenge_enable(void); 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 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 *); int auth_key_is_revoked(struct sshkey *); const char *auth_get_canonical_hostname(struct ssh *, int); HostStatus check_key_in_hostfiles(struct passwd *, struct sshkey *, const char *, const char *, const char *); /* hostkey handling */ 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 */ int auth_activate_options(struct ssh *, struct sshauthopt *); void auth_restrict_session(struct ssh *); 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(struct ssh *); void auth_debug_reset(void); struct passwd *fakepw(void); /* auth2-pubkeyfile.c */ int auth_authorise_keyopts(struct passwd *, struct sshauthopt *, int, const char *, const char *, const char *); int auth_check_principals_line(char *, const struct sshkey_cert *, const char *, struct sshauthopt **); int auth_process_principals(FILE *, const char *, const struct sshkey_cert *, struct sshauthopt **); int auth_check_authkey_line(struct passwd *, struct sshkey *, char *, const char *, const char *, const char *, struct sshauthopt **); int auth_check_authkeys_file(struct passwd *, FILE *, char *, struct sshkey *, const char *, const char *, struct sshauthopt **); FILE *auth_openkeyfile(const char *, struct passwd *, int); FILE *auth_openprincipals(const char *, struct passwd *, int); int sys_auth_passwd(struct ssh *, const char *); #if defined(KRB5) && !defined(HEIMDAL) krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); #endif #endif /* AUTH_H */ openssh-10.0p1/PaxHeaders.10889/auth2-chall.c100644 001750 001750 0000000003614775415623 0015424xustar0030 atime=1744182234.472485017 openssh-10.0p1/auth2-chall.c010064400017500001750000000230201477541562300140040ustar00djmdjm/* $OpenBSD: auth2-chall.c,v 1.54 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include "xmalloc.h" #include "ssh2.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "sshbuf.h" #include "packet.h" #include "dispatch.h" #include "ssherr.h" #include "log.h" #include "misc.h" #include "servconf.h" /* import */ extern ServerOptions options; 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; #else #ifdef USE_PAM extern KbdintDevice sshpam_device; #endif #endif KbdintDevice *devices[] = { #ifdef BSD_AUTH &bsdauth_device, #else #ifdef USE_PAM &sshpam_device, #endif #endif NULL }; typedef struct KbdintAuthctxt KbdintAuthctxt; struct KbdintAuthctxt { char *devices; void *ctxt; KbdintDevice *device; u_int nreq; u_int devices_done; }; #ifdef USE_PAM void remove_kbdint_device(const char *devname) { int i, j; for (i = 0; devices[i] != NULL; i++) if (strcmp(devices[i]->name, devname) == 0) { for (j = i; devices[j] != NULL; j++) devices[j] = devices[j+1]; i--; } } #endif static KbdintAuthctxt * kbdint_alloc(const char *devs) { KbdintAuthctxt *kbdintctxt; struct sshbuf *b; int i, r; #ifdef USE_PAM if (!options.use_pam) remove_kbdint_device("pam"); #endif kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt)); if (strcmp(devs, "") == 0) { if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (i = 0; devices[i]; i++) { if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", devices[i]->name)) != 0) fatal_fr(r, "buffer error"); } if ((kbdintctxt->devices = sshbuf_dup_string(b)) == NULL) fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); } else { kbdintctxt->devices = xstrdup(devs); } debug("kbdint_alloc: devices '%s'", kbdintctxt->devices); kbdintctxt->ctxt = NULL; kbdintctxt->device = NULL; kbdintctxt->nreq = 0; return kbdintctxt; } static void kbdint_reset_device(KbdintAuthctxt *kbdintctxt) { if (kbdintctxt->ctxt) { kbdintctxt->device->free_ctx(kbdintctxt->ctxt); kbdintctxt->ctxt = NULL; } kbdintctxt->device = NULL; } static void kbdint_free(KbdintAuthctxt *kbdintctxt) { if (kbdintctxt->device) kbdint_reset_device(kbdintctxt); free(kbdintctxt->devices); freezero(kbdintctxt, sizeof(*kbdintctxt)); } /* get next device */ static int kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt) { size_t len; char *t; int i; if (kbdintctxt->device) kbdint_reset_device(kbdintctxt); do { len = kbdintctxt->devices ? strcspn(kbdintctxt->devices, ",") : 0; if (len == 0) break; for (i = 0; devices[i]; i++) { 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) { kbdintctxt->device = devices[i]; kbdintctxt->devices_done |= 1 << i; } } t = kbdintctxt->devices; kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; free(t); debug2("kbdint_next_device: devices %s", kbdintctxt->devices ? kbdintctxt->devices : ""); } while (kbdintctxt->devices && !kbdintctxt->device); return kbdintctxt->device ? 1 : 0; } /* * try challenge-response, set authctxt->postponed if we have to * wait for the response. */ int auth2_challenge(struct ssh *ssh, char *devs) { Authctxt *authctxt = ssh->authctxt; debug("auth2_challenge: user=%s devs=%s", authctxt->user ? authctxt->user : "", devs ? devs : ""); if (authctxt->user == NULL || !devs) return 0; if (authctxt->kbdintctxt == NULL) authctxt->kbdintctxt = kbdint_alloc(devs); return auth2_challenge_start(ssh); } /* unregister kbd-int callbacks and context */ void auth2_challenge_stop(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; /* unregister callback */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); if (authctxt->kbdintctxt != NULL) { kbdint_free(authctxt->kbdintctxt); authctxt->kbdintctxt = NULL; } } /* side effect: sets authctxt->postponed if a reply was sent*/ static int auth2_challenge_start(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt; debug2("auth2_challenge_start: devices %s", kbdintctxt->devices ? kbdintctxt->devices : ""); if (kbdint_next_device(authctxt, kbdintctxt) == 0) { 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(ssh); return 0; } if (send_userauth_info_request(ssh) == 0) { auth2_challenge_stop(ssh); return 0; } ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, &input_userauth_info_response); authctxt->postponed = 1; return 0; } static int send_userauth_info_request(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt; char *name, *instr, **prompts; u_int r, i, *echo_on; kbdintctxt = authctxt->kbdintctxt; if (kbdintctxt->device->query(kbdintctxt->ctxt, &name, &instr, &kbdintctxt->nreq, &prompts, &echo_on)) return 0; 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_fr(r, "start packet"); for (i = 0; i < kbdintctxt->nreq; i++) { if ((r = sshpkt_put_cstring(ssh, prompts[i])) != 0 || (r = sshpkt_put_u8(ssh, echo_on[i])) != 0) fatal_fr(r, "assemble packet"); } if ((r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send packet"); for (i = 0; i < kbdintctxt->nreq; i++) free(prompts[i]); free(prompts); free(echo_on); free(name); free(instr); return 1; } static int input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt; int authenticated = 0, res; int r; u_int i, nresp; const char *devicename = NULL; char **response = NULL; if (authctxt == NULL) fatal_f("no authctxt"); kbdintctxt = authctxt->kbdintctxt; if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL) fatal_f("no kbdintctxt"); if (kbdintctxt->device == NULL) fatal_f("no device"); authctxt->postponed = 0; /* reset */ if ((r = sshpkt_get_u32(ssh, &nresp)) != 0) fatal_fr(r, "parse packet"); if (nresp != kbdintctxt->nreq) fatal_f("wrong number of replies"); if (nresp > 100) fatal_f("too many replies"); if (nresp > 0) { response = xcalloc(nresp, sizeof(char *)); for (i = 0; i < nresp; i++) { if ((r = sshpkt_get_cstring(ssh, &response[i], NULL)) != 0) fatal_fr(r, "parse response"); } } if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response); for (i = 0; i < nresp; i++) { explicit_bzero(response[i], strlen(response[i])); free(response[i]); } free(response); switch (res) { case 0: /* Success! */ authenticated = authctxt->valid ? 1 : 0; break; case 1: /* Authentication needs further interaction */ if (send_userauth_info_request(ssh) == 1) authctxt->postponed = 1; break; default: /* Failure! */ break; } devicename = kbdintctxt->device->name; if (!authctxt->postponed) { if (authenticated) { auth2_challenge_stop(ssh); } else { /* start next device */ /* may set authctxt->postponed */ auth2_challenge_start(ssh); } } userauth_finish(ssh, authenticated, "keyboard-interactive", devicename); return 0; } void privsep_challenge_enable(void) { #if defined(BSD_AUTH) || defined(USE_PAM) int n = 0; #endif #ifdef BSD_AUTH extern KbdintDevice mm_bsdauth_device; #endif #ifdef USE_PAM extern KbdintDevice mm_sshpam_device; #endif #ifdef BSD_AUTH devices[n++] = &mm_bsdauth_device; #else #ifdef USE_PAM devices[n++] = &mm_sshpam_device; #endif #endif } openssh-10.0p1/PaxHeaders.10889/auth2-gss.c100644 001750 001750 0000000003614775415623 0015135xustar0030 atime=1744182234.473462024 openssh-10.0p1/auth2-gss.c010064400017500001750000000223171477541562300135250ustar00djmdjm/* $OpenBSD: auth2-gss.c,v 1.36 2024/05/17 04:42:13 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. 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 GSSAPI #include #include #include "xmalloc.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "ssh2.h" #include "log.h" #include "dispatch.h" #include "sshbuf.h" #include "ssherr.h" #include "misc.h" #include "servconf.h" #include "packet.h" #include "kex.h" #include "ssh-gss.h" #include "monitor_wrap.h" #define SSH_GSSAPI_MAX_MECHS 2048 extern ServerOptions options; extern struct authmethod_cfg methodcfg_gssapi; 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(struct ssh *ssh, const char *method) { Authctxt *authctxt = ssh->authctxt; gss_OID_desc goid = {0, NULL}; Gssctxt *ctxt = NULL; int r, present; u_int mechs; OM_uint32 ms; size_t len; u_char *doid = NULL; if ((r = sshpkt_get_u32(ssh, &mechs)) != 0) fatal_fr(r, "parse packet"); if (mechs == 0) { logit_f("mechanism negotiation is not supported"); return (0); } else if (mechs > SSH_GSSAPI_MAX_MECHS) { logit_f("too many mechanisms requested %u > %u", mechs, SSH_GSSAPI_MAX_MECHS); return (0); } do { mechs--; free(doid); present = 0; if ((r = sshpkt_get_string(ssh, &doid, &len)) != 0) fatal_fr(r, "parse oid"); if (len > 2 && doid[0] == SSH_GSS_OIDTYPE && doid[1] == len - 2) { goid.elements = doid + 2; goid.length = len - 2; ssh_gssapi_test_oid_supported(&ms, &goid, &present); } else { logit_f("badly formed OID received"); } } while (mechs > 0 && !present); if (!present) { free(doid); authctxt->server_caused_failure = 1; return (0); } if (!authctxt->valid || authctxt->user == NULL) { debug2_f("disabled because of invalid user"); free(doid); return (0); } if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, &goid))) { if (ctxt != NULL) ssh_gssapi_delete_ctx(&ctxt); free(doid); authctxt->server_caused_failure = 1; return (0); } authctxt->methoddata = (void *)ctxt; /* Return the OID that we received */ 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_fr(r, "send packet"); free(doid); 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, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; OM_uint32 maj_status, min_status, flags; u_char *p; size_t len; int r; if (authctxt == NULL) fatal("No authentication or GSSAPI context"); gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); recv_tok.value = p; recv_tok.length = len; maj_status = mm_ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok, &flags); free(p); if (GSS_ERROR(maj_status)) { if (send_tok.length != 0) { 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_fr(r, "send ERRTOK packet"); } authctxt->postponed = 0; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); userauth_finish(ssh, 0, "gssapi-with-mic", NULL); } else { if (send_tok.length != 0) { 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_fr(r, "send TOKEN packet"); } if (maj_status == GSS_S_COMPLETE) { ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); if (flags & GSS_C_INTEG_FLAG) ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, &input_gssapi_mic); else ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, &input_gssapi_exchange_complete); } } gss_release_buffer(&min_status, &send_tok); return 0; } static int input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; OM_uint32 maj_status; int r; u_char *p; size_t len; if (authctxt == NULL) fatal("No authentication or GSSAPI context"); gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); recv_tok.value = p; recv_tok.length = len; /* Push the error token into GSSAPI to see what it says */ maj_status = mm_ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok, NULL); free(recv_tok.value); /* We can't return anything to the client, even if we wanted to */ 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 */ gss_release_buffer(&maj_status, &send_tok); return 0; } /* * This is called when the client thinks we've completed authentication. * It should only be enabled in the dispatch handler by the function above, * which only enables it once the GSSAPI exchange is complete. */ static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; int r, authenticated; if (authctxt == NULL) fatal("No authentication or GSSAPI context"); /* * We don't need to check the status, because we're only enabled in * the dispatcher once the exchange is complete */ if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); authenticated = mm_ssh_gssapi_userok(authctxt->user); authctxt->postponed = 0; 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, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; int r, authenticated = 0; struct sshbuf *b; gss_buffer_desc mic, gssbuf; u_char *p; size_t len; if (authctxt == NULL) fatal("No authentication or GSSAPI context"); gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0) fatal_fr(r, "parse packet"); if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mic.value = p; mic.length = len; ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, "gssapi-with-mic", ssh->kex->session_id); if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) fatal_f("sshbuf_mutable_ptr failed"); gssbuf.length = sshbuf_len(b); if (!GSS_ERROR(mm_ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))) authenticated = mm_ssh_gssapi_userok(authctxt->user); else logit("GSSAPI MIC check failed"); sshbuf_free(b); free(mic.value); authctxt->postponed = 0; 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; } Authmethod method_gssapi = { &methodcfg_gssapi, userauth_gssapi, }; #endif /* GSSAPI */ openssh-10.0p1/PaxHeaders.10889/auth2-hostbased.c100644 001750 001750 0000000003614775415623 0016315xustar0030 atime=1744182234.473462024 openssh-10.0p1/auth2-hostbased.c010064400017500001750000000174141477541562300147070ustar00djmdjm/* $OpenBSD: auth2-hostbased.c,v 1.53 2024/05/17 00:30:23 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include "xmalloc.h" #include "ssh2.h" #include "packet.h" #include "kex.h" #include "sshbuf.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "canohost.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "pathnames.h" #include "ssherr.h" #include "match.h" /* import */ extern ServerOptions options; extern struct authmethod_cfg methodcfg_hostbased; static int userauth_hostbased(struct ssh *ssh, const char *method) { Authctxt *authctxt = ssh->authctxt; struct sshbuf *b; struct sshkey *key = NULL; char *pkalg, *cuser, *chost; u_char *pkblob, *sig; size_t alen, blen, slen; int r, pktype, authenticated = 0; /* 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_fr(r, "parse packet"); debug_f("cuser %s chost %s pkalg %s slen %zu", cuser, chost, pkalg, slen); #ifdef DEBUG_PK debug("signature:"); sshbuf_dump_data(sig, slen, stderr); #endif pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ logit_f("unsupported public key algorithm: %s", pkalg); goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { error_fr(r, "key_from_blob"); goto done; } if (key == NULL) { error_f("cannot decode key: %s", pkalg); goto done; } if (key->type != pktype) { error_f("type mismatch for decoded key " "(received %d, expected %d)", key->type, pktype); goto done; } if (match_pattern_list(pkalg, options.hostbased_accepted_algos, 0) != 1) { logit_f("signature algorithm %s not in " "HostbasedAcceptedAlgorithms", pkalg); goto done; } if ((r = sshkey_check_cert_sigtype(key, options.ca_sign_algorithms)) != 0) { logit_fr(r, "certificate signature algorithm %s", (key->cert == NULL || key->cert->signature_type == NULL) ? "(null)" : key->cert->signature_type); goto done; } if ((r = sshkey_check_rsa_length(key, options.required_rsa_size)) != 0) { logit_r(r, "refusing %s key", sshkey_type(key)); goto done; } if (!authctxt->valid || authctxt->user == NULL) { debug2_f("disabled because of invalid user"); goto done; } if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* reconstruct packet */ if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, authctxt->user)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || (r = sshbuf_put_cstring(b, method)) != 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_fr(r, "reconstruct packet"); #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", cuser, chost); /* test for allowed key and correct signature */ authenticated = 0; if (mm_hostbased_key_allowed(ssh, authctxt->pw, cuser, chost, key) && mm_sshkey_verify(key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL) == 0) authenticated = 1; auth2_record_key(authctxt, authenticated, key); sshbuf_free(b); done: debug2_f("authenticated %d", authenticated); sshkey_free(key); free(pkalg); free(pkblob); free(cuser); free(chost); free(sig); return authenticated; } /* return 1 if given hostkey is allowed */ int 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; int len; char *fp; if (auth_key_is_revoked(key)) return 0; resolvedname = auth_get_canonical_hostname(ssh, options.use_dns); ipaddr = ssh_remote_ipaddr(ssh); debug2_f("chost %s resolvedname %s ipaddr %s", chost, resolvedname, ipaddr); if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { debug2("stripping trailing dot from chost %s", chost); chost[len - 1] = '\0'; } if (options.hostbased_uses_name_from_packet_only) { if (auth_rhosts2(pw, cuser, chost, chost) == 0) { debug2_f("auth_rhosts2 refused user \"%.100s\" " "host \"%.100s\" (from packet)", cuser, chost); return 0; } lookup = chost; } else { if (strcasecmp(resolvedname, chost) != 0) logit("userauth_hostbased mismatch: " "client sends %s, but we resolve %s to %s", chost, ipaddr, resolvedname); if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) { debug2_f("auth_rhosts2 refused " "user \"%.100s\" host \"%.100s\" addr \"%.100s\"", cuser, resolvedname, ipaddr); return 0; } lookup = resolvedname; } debug2_f("access allowed by auth_rhosts2"); if (sshkey_is_cert(key) && sshkey_cert_check_authority_now(key, 1, 0, 0, lookup, &reason)) { error("%s", reason); auth_debug_add("%s", reason); return 0; } host_status = check_key_in_hostfiles(pw, key, lookup, _PATH_SSH_SYSTEM_HOSTFILE, options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); /* backward compat if no key has been found. */ if (host_status == HOST_NEW) { host_status = check_key_in_hostfiles(pw, key, lookup, _PATH_SSH_SYSTEM_HOSTFILE2, options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE2); } if (host_status == HOST_OK) { if (sshkey_is_cert(key)) { if ((fp = sshkey_fingerprint(key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint fail"); verbose("Accepted certificate ID \"%s\" signed by " "%s CA %s from %s@%s", key->cert->key_id, sshkey_type(key->cert->signature_key), fp, cuser, lookup); } else { if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint fail"); verbose("Accepted %s public key %s from %s@%s", sshkey_type(key), fp, cuser, lookup); } free(fp); } return (host_status == HOST_OK); } Authmethod method_hostbased = { &methodcfg_hostbased, userauth_hostbased, }; openssh-10.0p1/PaxHeaders.10889/auth2-kbdint.c100644 001750 001750 0000000003614775415623 0015614xustar0030 atime=1744182234.473462024 openssh-10.0p1/auth2-kbdint.c010064400017500001750000000043721477541562300142050ustar00djmdjm/* $OpenBSD: auth2-kbdint.c,v 1.15 2024/05/17 00:30:23 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include "xmalloc.h" #include "packet.h" #include "hostfile.h" #include "auth.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "ssherr.h" /* import */ extern ServerOptions options; extern struct authmethod_cfg methodcfg_kbdint; static int userauth_kbdint(struct ssh *ssh, const char *method) { int r, authenticated = 0; char *lang, *devs; if ((r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &devs, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); debug("keyboard-interactive devs %s", devs); if (options.kbd_interactive_authentication) authenticated = auth2_challenge(ssh, devs); free(devs); free(lang); return authenticated; } Authmethod method_kbdint = { &methodcfg_kbdint, userauth_kbdint, }; openssh-10.0p1/PaxHeaders.10889/auth2-methods.c100644 001750 001750 0000000003614775415623 0016004xustar0030 atime=1744182234.473462024 openssh-10.0p1/auth2-methods.c010064400017500001750000000065351477541562300144000ustar00djmdjm/* * Copyright (c) 2012,2023 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include "log.h" #include "misc.h" #include "servconf.h" #include "xmalloc.h" #include "hostfile.h" #include "auth.h" extern ServerOptions options; /* * Configuration of enabled authentication methods. Separate from the rest of * auth2-*.c because we want to query it during server configuration validity * checking in the sshd listener process without pulling all the auth code in * too. */ /* "none" is allowed only one time and it is cleared by userauth_none() later */ int none_enabled = 1; struct authmethod_cfg methodcfg_none = { "none", NULL, &none_enabled }; struct authmethod_cfg methodcfg_pubkey = { "publickey", "publickey-hostbound-v00@openssh.com", &options.pubkey_authentication }; #ifdef GSSAPI struct authmethod_cfg methodcfg_gssapi = { "gssapi-with-mic", NULL, &options.gss_authentication }; #endif struct authmethod_cfg methodcfg_passwd = { "password", NULL, &options.password_authentication }; struct authmethod_cfg methodcfg_kbdint = { "keyboard-interactive", NULL, &options.kbd_interactive_authentication }; struct authmethod_cfg methodcfg_hostbased = { "hostbased", NULL, &options.hostbased_authentication }; static struct authmethod_cfg *authmethod_cfgs[] = { &methodcfg_none, &methodcfg_pubkey, #ifdef GSSAPI &methodcfg_gssapi, #endif &methodcfg_passwd, &methodcfg_kbdint, &methodcfg_hostbased, NULL }; /* * Check a comma-separated list of methods for validity. If need_enable is * non-zero, then also require that the methods are enabled. * Returns 0 on success or -1 if the methods list is invalid. */ int auth2_methods_valid(const char *_methods, int need_enable) { char *methods, *omethods, *method, *p; u_int i, found; int ret = -1; const struct authmethod_cfg *cfg; if (*_methods == '\0') { error("empty authentication method list"); return -1; } omethods = methods = xstrdup(_methods); while ((method = strsep(&methods, ",")) != NULL) { for (found = i = 0; !found && authmethod_cfgs[i] != NULL; i++) { cfg = authmethod_cfgs[i]; if ((p = strchr(method, ':')) != NULL) *p = '\0'; if (strcmp(method, cfg->name) != 0) continue; if (need_enable) { if (cfg->enabled == NULL || *(cfg->enabled) == 0) { error("Disabled method \"%s\" in " "AuthenticationMethods list \"%s\"", method, _methods); goto out; } } found = 1; break; } if (!found) { error("Unknown authentication method \"%s\" in list", method); goto out; } } ret = 0; out: free(omethods); return ret; } openssh-10.0p1/PaxHeaders.10889/auth2-none.c100644 001750 001750 0000000003614775415623 0015300xustar0030 atime=1744182234.473462024 openssh-10.0p1/auth2-none.c010064400017500001750000000044171477541562300136710ustar00djmdjm/* $OpenBSD: auth2-none.c,v 1.26 2024/05/17 00:30:23 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include "atomicio.h" #include "xmalloc.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "packet.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "ssh2.h" #include "ssherr.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" /* import */ extern ServerOptions options; extern struct authmethod_cfg methodcfg_none; extern int none_enabled; static int userauth_none(struct ssh *ssh, const char *method) { int r; none_enabled = 0; if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); if (options.permit_empty_passwd && options.password_authentication) return mm_auth_password(ssh, ""); return (0); } Authmethod method_none = { &methodcfg_none, userauth_none, }; openssh-10.0p1/PaxHeaders.10889/auth2-passwd.c100644 001750 001750 0000000003614775415623 0015642xustar0030 atime=1744182234.473462024 openssh-10.0p1/auth2-passwd.c010064400017500001750000000047051477541562300142330ustar00djmdjm/* $OpenBSD: auth2-passwd.c,v 1.22 2024/05/17 00:30:23 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include "packet.h" #include "ssherr.h" #include "log.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "misc.h" #include "servconf.h" /* import */ extern ServerOptions options; extern struct authmethod_cfg methodcfg_passwd; static int userauth_passwd(struct ssh *ssh, const char *method) { char *password = NULL; int authenticated = 0, r; u_char change; size_t len = 0; 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) { freezero(password, len); fatal_fr(r, "parse packet"); } if (change) logit("password change not supported"); else if (mm_auth_password(ssh, password) == 1) authenticated = 1; freezero(password, len); return authenticated; } Authmethod method_passwd = { &methodcfg_passwd, userauth_passwd, }; openssh-10.0p1/PaxHeaders.10889/auth2-pubkey.c100644 001750 001750 0000000003614775415623 0015640xustar0030 atime=1744182234.473462024 openssh-10.0p1/auth2-pubkey.c010064400017500001750000000620351477541562300142310ustar00djmdjm/* $OpenBSD: auth2-pubkey.c,v 1.122 2024/12/12 09:09:09 dtucker Exp $ */ /* * Copyright (c) 2000 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" #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #include #include #ifdef USE_SYSTEM_GLOB # include #else # include "openbsd-compat/glob.h" #endif #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "packet.h" #include "kex.h" #include "sshbuf.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "compat.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "pathnames.h" #include "uidswap.h" #include "auth-options.h" #include "canohost.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #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 struct authmethod_cfg methodcfg_pubkey; 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(struct ssh *ssh, const char *method) { Authctxt *authctxt = ssh->authctxt; struct passwd *pw = authctxt->pw; struct sshbuf *b = NULL; struct sshkey *key = NULL, *hostkey = 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 hostbound, r, pktype; int req_presence = 0, req_verify = 0, authenticated = 0; struct sshauthopt *authopts = NULL; struct sshkey_sig_details *sig_details = NULL; hostbound = strcmp(method, "publickey-hostbound-v00@openssh.com") == 0; 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_fr(r, "parse %s packet", method); /* hostbound auth includes the hostkey offered at initial KEX */ if (hostbound) { if ((r = sshpkt_getb_froms(ssh, &b)) != 0 || (r = sshkey_fromb(b, &hostkey)) != 0) fatal_fr(r, "parse %s hostkey", method); if (ssh->kex->initial_hostkey == NULL) fatal_f("internal error: initial hostkey not recorded"); if (!sshkey_equal(hostkey, ssh->kex->initial_hostkey)) fatal_f("%s packet contained wrong host key", method); sshbuf_free(b); b = NULL; } if (log_level_get() >= SYSLOG_LEVEL_DEBUG2) { char *keystring; struct sshbuf *pkbuf; if ((pkbuf = sshbuf_from(pkblob, blen)) == NULL) fatal_f("sshbuf_from failed"); if ((keystring = sshbuf_dtob64_string(pkbuf, 0)) == NULL) fatal_f("sshbuf_dtob64 failed"); debug2_f("%s user %s %s public key %s %s", authctxt->valid ? "valid" : "invalid", authctxt->user, have_sig ? "attempting" : "querying", pkalg, keystring); sshbuf_free(pkbuf); free(keystring); } pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ verbose_f("unsupported public key algorithm: %s", pkalg); goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { error_fr(r, "parse key"); goto done; } if (key == NULL) { error_f("cannot decode key: %s", pkalg); goto done; } if (key->type != pktype) { error_f("type mismatch for decoded key " "(received %d, expected %d)", key->type, pktype); goto done; } if (auth2_key_already_used(authctxt, key)) { logit("refusing previously-used %s key", sshkey_type(key)); goto done; } if (match_pattern_list(pkalg, options.pubkey_accepted_algos, 0) != 1) { logit_f("signature algorithm %s not in " "PubkeyAcceptedAlgorithms", pkalg); goto done; } if ((r = sshkey_check_cert_sigtype(key, options.ca_sign_algorithms)) != 0) { logit_fr(r, "certificate signature algorithm %s", (key->cert == NULL || key->cert->signature_type == NULL) ? "(null)" : key->cert->signature_type); goto done; } if ((r = sshkey_check_rsa_length(key, options.required_rsa_size)) != 0) { logit_r(r, "refusing %s key", sshkey_type(key)); goto done; } key_s = format_key(key); if (sshkey_is_cert(key)) ca_s = format_key(key->cert->signature_key); if (have_sig) { debug3_f("%s have %s signature for %s%s%s", method, 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_fr(r, "parse signature packet"); if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (ssh->compat & SSH_OLD_SESSIONID) { if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0) fatal_fr(r, "put old session id"); } else { if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0) fatal_fr(r, "put session id"); } if (!authctxt->valid || authctxt->user == NULL) { debug2_f("disabled because of invalid user"); goto done; } /* reconstruct packet */ xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); 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, method)) != 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_fr(r, "reconstruct %s packet", method); if (hostbound && (r = sshkey_puts(ssh->kex->initial_hostkey, b)) != 0) fatal_fr(r, "reconstruct %s packet", method); #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif /* test for correct signature */ authenticated = 0; if (mm_user_key_allowed(ssh, pw, key, 1, &authopts) && mm_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; } if (authenticated == 1 && sig_details != NULL) { auth2_record_info(authctxt, "signature count = %u", sig_details->sk_counter); debug_f("sk_counter = %u, sk_flags = 0x%02x", sig_details->sk_counter, sig_details->sk_flags); req_presence = (options.pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) || !authopts->no_require_user_presence; if (req_presence && (sig_details->sk_flags & SSH_SK_USER_PRESENCE_REQD) == 0) { error("public key %s signature for %s%s from " "%.128s port %d rejected: user presence " "(authenticator touch) requirement " "not met ", key_s, authctxt->valid ? "" : "invalid user ", authctxt->user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); authenticated = 0; goto done; } req_verify = (options.pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) || authopts->require_verify; if (req_verify && (sig_details->sk_flags & SSH_SK_USER_VERIFICATION_REQD) == 0) { error("public key %s signature for %s%s from " "%.128s port %d rejected: user " "verification requirement not met ", key_s, authctxt->valid ? "" : "invalid user ", authctxt->user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); authenticated = 0; goto done; } } auth2_record_key(authctxt, authenticated, key); } else { debug_f("%s test pkalg %s pkblob %s%s%s", method, pkalg, key_s, ca_s == NULL ? "" : " CA ", ca_s == NULL ? "" : ca_s); if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); if (!authctxt->valid || authctxt->user == NULL) { debug2_f("disabled because of invalid user"); goto done; } /* XXX fake reply and always send PK_OK ? */ /* * XXX this allows testing whether a user is allowed * to login: if you happen to have a valid pubkey this * message is sent. the message is NEVER sent at all * if a user is not allowed to login. is this an * issue? -markus */ if (mm_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_fr(r, "send packet"); authctxt->postponed = 1; } } done: if (authenticated == 1 && auth_activate_options(ssh, authopts) != 0) { debug_f("key options inconsistent with existing"); authenticated = 0; } debug2_f("authenticated %d pkalg %s", authenticated, pkalg); sshbuf_free(b); sshauthopt_free(authopts); sshkey_free(key); sshkey_free(hostkey); free(userstyle); free(pkalg); free(pkblob); free(key_s); free(ca_s); free(sig); sshkey_sig_details_free(sig_details); return authenticated; } static int match_principals_file(struct passwd *pw, char *file, struct sshkey_cert *cert, struct sshauthopt **authoptsp) { FILE *f; int r, success = 0; size_t i; glob_t gl; struct sshauthopt *opts = NULL; if (authoptsp != NULL) *authoptsp = NULL; temporarily_use_uid(pw); r = glob(file, 0, NULL, &gl); restore_uid(); if (r != 0) { if (r != GLOB_NOMATCH) { logit_f("glob \"%s\" failed", file); } return 0; } else if (gl.gl_pathc > INT_MAX) { fatal_f("too many glob results for \"%s\"", file); } else if (gl.gl_pathc > 1) { debug2_f("glob \"%s\" returned %zu matches", file, gl.gl_pathc); } for (i = 0; !success && i < gl.gl_pathc; i++) { temporarily_use_uid(pw); debug("trying authorized principals file %s", file); if ((f = auth_openprincipals(gl.gl_pathv[i], pw, options.strict_modes)) == NULL) { restore_uid(); continue; } success = auth_process_principals(f, gl.gl_pathv[i], cert, &opts); fclose(f); restore_uid(); if (!success) { sshauthopt_free(opts); opts = NULL; } } globfree(&gl); if (success && authoptsp != NULL) { *authoptsp = opts; opts = NULL; } sshauthopt_free(opts); 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 passwd *user_pw, const struct sshkey *key, const char *conn_id, const char *rdomain, 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) != 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_f("sshkey_fingerprint failed"); goto out; } if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_f("sshkey_fingerprint failed"); goto out; } if ((r = sshkey_to_base64(cert->signature_key, &catext)) != 0) { error_fr(r, "sshkey_to_base64 failed"); goto out; } if ((r = sshkey_to_base64(key, &keytext)) != 0) { error_fr(r, "sshkey_to_base64 failed"); 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], "C", conn_id, "D", rdomain, "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_f("percent_expand failed"); free(av[i]); av[i] = tmp; } /* Prepare a printable command for logs, etc. */ command = argv_assemble(ac, av); if ((pid = subprocess("AuthorizedPrincipalsCommand", command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, runas_pw, temporarily_use_uid, restore_uid)) == 0) goto out; uid_swapped = 1; temporarily_use_uid(runas_pw); ok = auth_process_principals(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; } /* Authenticate a certificate key against TrustedUserCAKeys */ static int user_cert_trusted_ca(struct passwd *pw, struct sshkey *key, const char *remote_ip, const char *remote_host, const char *conn_id, const char *rdomain, struct sshauthopt **authoptsp) { char *ca_fp, *principals_file = NULL; const char *reason; 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 (!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 ((r = sshkey_in_file(key->cert->signature_key, options.trusted_user_ca_keys, 1, 0)) != 0) { debug2_fr(r, "CA %s %s is not listed in %s", sshkey_type(key->cert->signature_key), ca_fp, options.trusted_user_ca_keys); goto out; } /* * If AuthorizedPrincipals is in use, then compare the certificate * principals against the names in that file rather than matching * against the username. */ if ((principals_file = authorized_principals_file(pw)) != NULL) { if (match_principals_file(pw, principals_file, key->cert, &principals_opts)) found_principal = 1; } /* Try querying command if specified */ if (!found_principal && match_principals_command(pw, key, conn_id, rdomain, &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_f("internal error: missing principals_opts"); if (sshkey_cert_check_authority_now(key, 0, 1, 0, use_authorized_principals ? NULL : pw->pw_name, &reason) != 0) goto fail_reason; /* 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(pw, cert_opts, 0, remote_ip, remote_host, "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(pw, principals_opts, 0, remote_ip, remote_host, "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; } } /* 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; } /* * Checks whether key is allowed in file. * returns 1 if the key is allowed or 0 otherwise. */ static int user_key_allowed2(struct passwd *pw, struct sshkey *key, char *file, const char *remote_ip, const char *remote_host, 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 = auth_check_authkeys_file(pw, f, file, key, remote_ip, remote_host, authoptsp); fclose(f); } restore_uid(); return found_key; } /* * Checks whether key is allowed in output of command. * returns 1 if the key is allowed or 0 otherwise. */ static int user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key, const char *remote_ip, const char *remote_host, const char *conn_id, const char *rdomain, struct sshauthopt **authoptsp) { 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 = NULL, *key_fp = NULL, *keytext = NULL; char uidstr[32], *tmp, *command = NULL, **av = NULL; void (*osigchld)(int); 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); runas_pw = getpwnam(username); if (runas_pw == NULL) { error("AuthorizedKeysCommandUser \"%s\" not found: %s", username, strerror(errno)); goto out; } /* Prepare AuthorizedKeysCommand */ if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_f("sshkey_fingerprint failed"); goto out; } if ((r = sshkey_to_base64(key, &keytext)) != 0) { error_fr(r, "sshkey_to_base64 failed"); goto out; } /* Turn the command into an argument vector */ if (argv_split(options.authorized_keys_command, &ac, &av, 0) != 0) { error("AuthorizedKeysCommand \"%s\" contains invalid quotes", options.authorized_keys_command); goto out; } if (ac == 0) { error("AuthorizedKeysCommand \"%s\" yielded no arguments", options.authorized_keys_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], "C", conn_id, "D", rdomain, "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_f("percent_expand failed"); free(av[i]); av[i] = tmp; } /* Prepare a printable command for logs, etc. */ command = argv_assemble(ac, av); /* * If AuthorizedKeysCommand was run without arguments * then fall back to the old behaviour of passing the * target username as a single argument. */ 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]); } if ((pid = subprocess("AuthorizedKeysCommand", command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, runas_pw, temporarily_use_uid, restore_uid)) == 0) goto out; uid_swapped = 1; temporarily_use_uid(runas_pw); ok = auth_check_authkeys_file(user_pw, f, options.authorized_keys_command, key, remote_ip, remote_host, authoptsp); fclose(f); f = NULL; if (exited_cleanly(pid, "AuthorizedKeysCommand", command, 0) != 0) goto out; /* Read completed successfully */ found_key = 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(key_fp); free(keytext); return found_key; } /* * Check whether key authenticates and authorises the user. */ int user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, int auth_attempt, struct sshauthopt **authoptsp) { u_int success = 0, i, j; char *file = NULL, *conn_id; struct sshauthopt *opts = NULL; const char *rdomain, *remote_ip, *remote_host; if (authoptsp != NULL) *authoptsp = NULL; if (auth_key_is_revoked(key)) return 0; if (sshkey_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) return 0; if ((rdomain = ssh_packet_rdomain_in(ssh)) == NULL) rdomain = ""; remote_ip = ssh_remote_ipaddr(ssh); remote_host = auth_get_canonical_hostname(ssh, options.use_dns); xasprintf(&conn_id, "%s %d %s %d", ssh_local_ipaddr(ssh), ssh_local_port(ssh), remote_ip, ssh_remote_port(ssh)); for (i = 0; !success && i < options.num_authkeys_files; i++) { int r; glob_t gl; if (strcasecmp(options.authorized_keys_files[i], "none") == 0) continue; file = expand_authorized_keys( options.authorized_keys_files[i], pw); temporarily_use_uid(pw); r = glob(file, 0, NULL, &gl); restore_uid(); if (r != 0) { if (r != GLOB_NOMATCH) { logit_f("glob \"%s\" failed", file); } free(file); file = NULL; continue; } else if (gl.gl_pathc > INT_MAX) { fatal_f("too many glob results for \"%s\"", file); } else if (gl.gl_pathc > 1) { debug2_f("glob \"%s\" returned %zu matches", file, gl.gl_pathc); } for (j = 0; !success && j < gl.gl_pathc; j++) { success = user_key_allowed2(pw, key, gl.gl_pathv[j], remote_ip, remote_host, &opts); if (!success) { sshauthopt_free(opts); opts = NULL; } } free(file); file = NULL; globfree(&gl); } if (success) goto out; if ((success = user_cert_trusted_ca(pw, key, remote_ip, remote_host, conn_id, rdomain, &opts)) != 0) goto out; sshauthopt_free(opts); opts = NULL; if ((success = user_key_command_allowed2(pw, key, remote_ip, remote_host, conn_id, rdomain, &opts)) != 0) goto out; sshauthopt_free(opts); opts = NULL; out: free(conn_id); if (success && authoptsp != NULL) { *authoptsp = opts; opts = NULL; } sshauthopt_free(opts); return success; } Authmethod method_pubkey = { &methodcfg_pubkey, userauth_pubkey, }; openssh-10.0p1/PaxHeaders.10889/auth2-pubkeyfile.c100644 001750 001750 0000000003614775415623 0016500xustar0030 atime=1744182234.493969464 openssh-10.0p1/auth2-pubkeyfile.c010064400017500001750000000333711477541562300150720ustar00djmdjm/* $OpenBSD: auth2-pubkeyfile.c,v 1.4 2023/03/05 05:34:09 dtucker Exp $ */ /* * Copyright (c) 2000 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" #include #include #include #include #include #include #include #include #include #include #include #include "ssh.h" #include "log.h" #include "misc.h" #include "sshkey.h" #include "digest.h" #include "hostfile.h" #include "auth.h" #include "auth-options.h" #include "authfile.h" #include "match.h" #include "ssherr.h" int auth_authorise_keyopts(struct passwd *pw, struct sshauthopt *opts, int allow_cert_authority, const char *remote_ip, const char *remote_host, const char *loc) { 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; } static int match_principals_option(const char *principal_list, struct sshkey_cert *cert) { char *result; u_int i; /* XXX percent_expand() sequences for authorized_principals? */ for (i = 0; i < cert->nprincipals; i++) { if ((result = match_list(cert->principals[i], principal_list, NULL)) != NULL) { debug3("matched principal from key options \"%.100s\"", result); free(result); return 1; } } 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. */ int auth_check_principals_line(char *cp, const struct sshkey_cert *cert, const char *loc, struct sshauthopt **authoptsp) { u_int i, found = 0; char *ep, *line_opts; const char *reason = NULL; struct sshauthopt *opts = NULL; 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; } if (found && authoptsp != NULL) { *authoptsp = opts; opts = NULL; } sshauthopt_free(opts); return found ? 0 : -1; } int auth_process_principals(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, nonblank = 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++) ; /* Skip blank and comment lines. */ if ((ep = strchr(cp, '#')) != NULL) *ep = '\0'; if (!*cp || *cp == '\n') continue; nonblank++; snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); if (auth_check_principals_line(cp, cert, loc, authoptsp) == 0) found_principal = 1; } debug2_f("%s: processed %lu/%lu lines", file, nonblank, linenum); free(line); 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. */ int auth_check_authkey_line(struct passwd *pw, struct sshkey *key, char *cp, const char *remote_ip, const char *remote_host, 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_f("keytype %d failed", 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, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug("%s: matching %s found: %s %s", loc, sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp); if (auth_authorise_keyopts(pw, keyopts, sshkey_is_cert(key), remote_ip, remote_host, 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(pw, certopts, 0, remote_ip, remote_host, 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_now(key, 0, 0, 0, keyopts->cert_principals == NULL ? pw->pw_name : NULL, &reason) != 0) goto fail_reason; verbose("Accepted certificate ID \"%s\" (serial %llu) " "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_f("internal error: missing options"); 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; } /* * Checks whether key is allowed in authorized_keys-format file, * returns 1 if the key is allowed or 0 otherwise. */ int auth_check_authkeys_file(struct passwd *pw, FILE *f, char *file, struct sshkey *key, const char *remote_ip, const char *remote_host, struct sshauthopt **authoptsp) { char *cp, *line = NULL, loc[256]; size_t linesize = 0; int found_key = 0; u_long linenum = 0, nonblank = 0; if (authoptsp != NULL) *authoptsp = NULL; while (getline(&line, &linesize, f) != -1) { linenum++; /* Always consume entire file */ if (found_key) continue; /* Skip leading whitespace, empty and comment lines. */ cp = line; skip_space(&cp); if (!*cp || *cp == '\n' || *cp == '#') continue; nonblank++; snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); if (auth_check_authkey_line(pw, key, cp, remote_ip, remote_host, loc, authoptsp) == 0) found_key = 1; } free(line); debug2_f("%s: processed %lu/%lu lines", file, nonblank, linenum); return found_key; } static FILE * auth_openfile(const char *file, struct passwd *pw, int strict_modes, int log_missing, char *file_type) { char line[1024]; struct stat st; int fd; FILE *f; if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) { if (errno != ENOENT) { logit("Could not open user '%s' %s '%s': %s", pw->pw_name, file_type, file, strerror(errno)); } else if (log_missing) { debug("Could not open user '%s' %s '%s': %s", pw->pw_name, file_type, file, strerror(errno)); } return NULL; } if (fstat(fd, &st) == -1) { close(fd); return NULL; } if (!S_ISREG(st.st_mode)) { logit("User '%s' %s '%s' is not a regular file", pw->pw_name, file_type, file); close(fd); return NULL; } unset_nonblock(fd); if ((f = fdopen(fd, "r")) == NULL) { close(fd); return NULL; } if (strict_modes && 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); return NULL; } return f; } FILE * auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes) { return auth_openfile(file, pw, strict_modes, 1, "authorized keys"); } FILE * auth_openprincipals(const char *file, struct passwd *pw, int strict_modes) { return auth_openfile(file, pw, strict_modes, 0, "authorized principals"); } openssh-10.0p1/PaxHeaders.10889/auth2.c100644 001750 001750 0000000003614775415623 0014343xustar0030 atime=1744182234.494958194 openssh-10.0p1/auth2.c010064400017500001750000000540201477541562300127270ustar00djmdjm/* $OpenBSD: auth2.c,v 1.170 2025/01/17 00:09:41 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include "stdlib.h" #include "atomicio.h" #include "xmalloc.h" #include "ssh2.h" #include "packet.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "servconf.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "dispatch.h" #include "pathnames.h" #include "ssherr.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "digest.h" #include "kex.h" /* import */ extern ServerOptions options; extern struct sshbuf *loginmsg; /* methods */ extern Authmethod method_none; extern Authmethod method_pubkey; extern Authmethod method_passwd; extern Authmethod method_kbdint; extern Authmethod method_hostbased; #ifdef GSSAPI extern Authmethod method_gssapi; #endif Authmethod *authmethods[] = { &method_none, &method_pubkey, #ifdef GSSAPI &method_gssapi, #endif &method_passwd, &method_kbdint, &method_hostbased, NULL }; /* protocol */ static int input_service_request(int, u_int32_t, struct ssh *); static int input_userauth_request(int, u_int32_t, struct ssh *); /* helper */ static Authmethod *authmethod_byname(const char *); static Authmethod *authmethod_lookup(Authctxt *, const char *); static char *authmethods_get(Authctxt *authctxt); #define MATCH_NONE 0 /* method or submethod mismatch */ #define MATCH_METHOD 1 /* method matches (no submethod specified) */ #define MATCH_BOTH 2 /* method and submethod match */ #define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */ static int list_starts_with(const char *, const char *, const char *); char * auth2_read_banner(void) { struct stat st; char *banner = NULL; size_t len, n; int fd; if ((fd = open(options.banner, O_RDONLY)) == -1) return (NULL); if (fstat(fd, &st) == -1) { close(fd); return (NULL); } if (st.st_size <= 0 || st.st_size > 1*1024*1024) { close(fd); return (NULL); } len = (size_t)st.st_size; /* truncate */ banner = xmalloc(len + 1); n = atomicio(read, fd, banner, len); close(fd); if (n != len) { free(banner); return (NULL); } banner[n] = '\0'; return (banner); } static void userauth_send_banner(struct ssh *ssh, const char *msg) { int r; if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_BANNER)) != 0 || (r = sshpkt_put_cstring(ssh, msg)) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */ (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); debug("%s: sent", __func__); } static void userauth_banner(struct ssh *ssh) { char *banner = NULL; if (options.banner == NULL) return; if ((banner = mm_auth2_read_banner()) == NULL) goto done; userauth_send_banner(ssh, banner); done: free(banner); } /* * loop until authctxt->success == TRUE */ void do_authentication2(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; ssh_dispatch_init(ssh, &dispatch_protocol_error); if (ssh->kex->ext_info_c) ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request); ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success); ssh->authctxt = NULL; } static int input_service_request(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *service = NULL; int r, acceptit = 0; if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; if (authctxt == NULL) fatal("input_service_request: no authctxt"); if (strcmp(service, "ssh-userauth") == 0) { if (!authctxt->success) { acceptit = 1; /* now we can handle user-auth requests */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); } } /* XXX all other service requests are denied */ if (acceptit) { if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 || (r = sshpkt_put_cstring(ssh, service)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) goto out; } else { debug("bad service request %s", service); ssh_packet_disconnect(ssh, "bad service request %s", service); } ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &dispatch_protocol_error); r = 0; out: free(service); return r; } #define MIN_FAIL_DELAY_SECONDS 0.005 #define MAX_FAIL_DELAY_SECONDS 5.0 static double user_specific_delay(const char *user) { char b[512]; size_t len = ssh_digest_bytes(SSH_DIGEST_SHA512); u_char *hash = xmalloc(len); double delay; (void)snprintf(b, sizeof b, "%llu%s", (unsigned long long)options.timing_secret, user); if (ssh_digest_memory(SSH_DIGEST_SHA512, b, strlen(b), hash, len) != 0) fatal_f("ssh_digest_memory"); /* 0-4.2 ms of delay */ delay = (double)PEEK_U32(hash) / 1000 / 1000 / 1000 / 1000; freezero(hash, len); debug3_f("user specific delay %0.3lfms", delay*1000); return MIN_FAIL_DELAY_SECONDS + delay; } static void ensure_minimum_time_since(double start, double seconds) { struct timespec ts; double elapsed = monotime_double() - start, req = seconds, remain; if (elapsed > MAX_FAIL_DELAY_SECONDS) { debug3_f("elapsed %0.3lfms exceeded the max delay " "requested %0.3lfms)", elapsed*1000, req*1000); return; } /* if we've already passed the requested time, scale up */ while ((remain = seconds - elapsed) < 0.0) seconds *= 2; ts.tv_sec = remain; ts.tv_nsec = (remain - ts.tv_sec) * 1000000000; debug3_f("elapsed %0.3lfms, delaying %0.3lfms (requested %0.3lfms)", elapsed*1000, remain*1000, req*1000); nanosleep(&ts, NULL); } static int input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; char *user = NULL, *service = NULL, *method = NULL, *style = NULL; int r, authenticated = 0; double tstart = monotime_double(); if (authctxt == NULL) fatal("input_userauth_request: no authctxt"); if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0) goto out; debug("userauth-request for user %s service %s method %s", user, service, method); debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); if ((style = strchr(user, ':')) != NULL) *style++ = 0; if (authctxt->attempt >= 1024) auth_maxtries_exceeded(ssh); if (authctxt->attempt++ == 0) { /* setup auth context */ authctxt->pw = mm_getpwnamallow(ssh, user); authctxt->user = xstrdup(user); if (authctxt->pw && strcmp(service, "ssh-connection")==0) { authctxt->valid = 1; debug2_f("setting up authctxt for %s", user); } else { authctxt->valid = 0; /* Invalid user, fake password information */ authctxt->pw = fakepw(); #ifdef SSH_AUDIT_EVENTS mm_audit_event(ssh, SSH_INVALID_USER); #endif } #ifdef USE_PAM if (options.use_pam) mm_start_pam(ssh); #endif ssh_packet_set_log_preamble(ssh, "%suser %s", authctxt->valid ? "authenticating " : "invalid ", user); setproctitle("%s [net]", authctxt->valid ? user : "unknown"); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; mm_inform_authserv(service, style); userauth_banner(ssh); if ((r = kex_server_update_ext_info(ssh)) != 0) fatal_fr(r, "kex_server_update_ext_info failed"); if (auth2_setup_methods_lists(authctxt) != 0) ssh_packet_disconnect(ssh, "no authentication methods enabled"); } else if (strcmp(user, authctxt->user) != 0 || strcmp(service, authctxt->service) != 0) { ssh_packet_disconnect(ssh, "Change of username or service " "not allowed: (%s,%s) -> (%s,%s)", authctxt->user, authctxt->service, user, service); } /* reset state */ auth2_challenge_stop(ssh); #ifdef GSSAPI /* XXX move to auth2_gssapi_stop() */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif auth2_authctxt_reset_info(authctxt); authctxt->postponed = 0; authctxt->server_caused_failure = 0; /* try to authenticate user */ m = authmethod_lookup(authctxt, method); if (m != NULL && authctxt->failures < options.max_authtries) { debug2("input_userauth_request: try method %s", method); authenticated = m->userauth(ssh, method); } if (!authctxt->authenticated && strcmp(method, "none") != 0) ensure_minimum_time_since(tstart, user_specific_delay(authctxt->user)); userauth_finish(ssh, authenticated, method, NULL); r = 0; out: free(service); free(user); free(method); return r; } void userauth_finish(struct ssh *ssh, int authenticated, const char *packet_method, const char *submethod) { Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; const char *method = packet_method; char *methods; int r, partial = 0; if (authenticated) { if (!authctxt->valid) { fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); } if (authctxt->postponed) fatal("INTERNAL ERROR: authenticated and postponed"); /* prefer primary authmethod name to possible synonym */ if ((m = authmethod_byname(method)) == NULL) fatal("INTERNAL ERROR: bad method %s", method); method = m->cfg->name; } /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(ssh, method)) { authenticated = 0; #ifdef SSH_AUDIT_EVENTS mm_audit_event(ssh, SSH_LOGIN_ROOT_DENIED); #endif } if (authenticated && options.num_auth_methods != 0) { if (!auth2_update_methods_lists(authctxt, method, submethod)) { authenticated = 0; partial = 1; } } /* Log before sending the reply */ auth_log(ssh, authenticated, partial, method, submethod); /* Update information exposed to session */ if (authenticated || partial) auth2_update_session_info(authctxt, method, submethod); if (authctxt->postponed) return; #ifdef USE_PAM if (options.use_pam && authenticated) { int r, success = mm_do_pam_account(); /* If PAM returned a message, send it to the user. */ if (sshbuf_len(loginmsg) > 0) { if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); userauth_send_banner(ssh, sshbuf_ptr(loginmsg)); if ((r = ssh_packet_write_wait(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: send PAM banner", __func__); } } if (!success) { fatal("Access denied for user %s by PAM account " "configuration", authctxt->user); } } #endif if (authenticated == 1) { /* turn off userauth */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send success packet"); /* now we can break out */ authctxt->success = 1; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); } else { /* Allow initial try of "none" auth without failure penalty */ if (!partial && !authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS mm_audit_event(ssh, SSH_LOGIN_EXCEED_MAXTRIES); #endif auth_maxtries_exceeded(ssh); } methods = authmethods_get(authctxt); debug3_f("failure partial=%d next methods=\"%s\"", partial, methods); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 || (r = sshpkt_put_cstring(ssh, methods)) != 0 || (r = sshpkt_put_u8(ssh, partial)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send failure packet"); free(methods); } } /* * Checks whether method is allowed by at least one AuthenticationMethods * methods list. Returns 1 if allowed, or no methods lists configured. * 0 otherwise. */ int auth2_method_allowed(Authctxt *authctxt, const char *method, const char *submethod) { u_int i; /* * NB. authctxt->num_auth_methods might be zero as a result of * auth2_setup_methods_lists(), so check the configuration. */ if (options.num_auth_methods == 0) return 1; for (i = 0; i < authctxt->num_auth_methods; i++) { if (list_starts_with(authctxt->auth_methods[i], method, submethod) != MATCH_NONE) return 1; } return 0; } static char * authmethods_get(Authctxt *authctxt) { struct sshbuf *b; char *list; int i, r; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (i = 0; authmethods[i] != NULL; i++) { if (strcmp(authmethods[i]->cfg->name, "none") == 0) continue; if (authmethods[i]->cfg->enabled == NULL || *(authmethods[i]->cfg->enabled) == 0) continue; if (!auth2_method_allowed(authctxt, authmethods[i]->cfg->name, NULL)) continue; if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", authmethods[i]->cfg->name)) != 0) fatal_fr(r, "buffer error"); } if ((list = sshbuf_dup_string(b)) == NULL) fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); return list; } static Authmethod * authmethod_byname(const char *name) { int i; if (name == NULL) fatal_f("NULL authentication method name"); for (i = 0; authmethods[i] != NULL; i++) { if (strcmp(name, authmethods[i]->cfg->name) == 0 || (authmethods[i]->cfg->synonym != NULL && strcmp(name, authmethods[i]->cfg->synonym) == 0)) return authmethods[i]; } debug_f("unrecognized authentication method name: %s", name); return NULL; } static Authmethod * authmethod_lookup(Authctxt *authctxt, const char *name) { Authmethod *method; if ((method = authmethod_byname(name)) == NULL) return NULL; if (method->cfg->enabled == NULL || *(method->cfg->enabled) == 0) { debug3_f("method %s not enabled", name); return NULL; } if (!auth2_method_allowed(authctxt, method->cfg->name, NULL)) { debug3_f("method %s not allowed " "by AuthenticationMethods", name); return NULL; } return method; } /* * Prune the AuthenticationMethods supplied in the configuration, removing * any methods lists that include disabled methods. Note that this might * leave authctxt->num_auth_methods == 0, even when multiple required auth * has been requested. For this reason, all tests for whether multiple is * enabled should consult options.num_auth_methods directly. */ int auth2_setup_methods_lists(Authctxt *authctxt) { u_int i; /* First, normalise away the "any" pseudo-method */ if (options.num_auth_methods == 1 && strcmp(options.auth_methods[0], "any") == 0) { free(options.auth_methods[0]); options.auth_methods[0] = NULL; options.num_auth_methods = 0; } if (options.num_auth_methods == 0) return 0; debug3_f("checking methods"); authctxt->auth_methods = xcalloc(options.num_auth_methods, sizeof(*authctxt->auth_methods)); authctxt->num_auth_methods = 0; for (i = 0; i < options.num_auth_methods; i++) { if (auth2_methods_valid(options.auth_methods[i], 1) != 0) { logit("Authentication methods list \"%s\" contains " "disabled method, skipping", options.auth_methods[i]); continue; } debug("authentication methods list %d: %s", authctxt->num_auth_methods, options.auth_methods[i]); authctxt->auth_methods[authctxt->num_auth_methods++] = xstrdup(options.auth_methods[i]); } if (authctxt->num_auth_methods == 0) { error("No AuthenticationMethods left after eliminating " "disabled methods"); return -1; } return 0; } static int list_starts_with(const char *methods, const char *method, const char *submethod) { size_t l = strlen(method); int match; const char *p; if (strncmp(methods, method, l) != 0) return MATCH_NONE; p = methods + l; match = MATCH_METHOD; if (*p == ':') { if (!submethod) return MATCH_PARTIAL; l = strlen(submethod); p += 1; if (strncmp(submethod, p, l)) return MATCH_NONE; p += l; match = MATCH_BOTH; } if (*p != ',' && *p != '\0') return MATCH_NONE; return match; } /* * Remove method from the start of a comma-separated list of methods. * Returns 0 if the list of methods did not start with that method or 1 * if it did. */ static int remove_method(char **methods, const char *method, const char *submethod) { char *omethods = *methods, *p; size_t l = strlen(method); int match; match = list_starts_with(omethods, method, submethod); if (match != MATCH_METHOD && match != MATCH_BOTH) return 0; p = omethods + l; if (submethod && match == MATCH_BOTH) p += 1 + strlen(submethod); /* include colon */ if (*p == ',') p++; *methods = xstrdup(p); free(omethods); return 1; } /* * Called after successful authentication. Will remove the successful method * from the start of each list in which it occurs. If it was the last method * in any list, then authentication is deemed successful. * Returns 1 if the method completed any authentication list or 0 otherwise. */ int auth2_update_methods_lists(Authctxt *authctxt, const char *method, const char *submethod) { u_int i, found = 0; debug3_f("updating methods list after \"%s\"", method); for (i = 0; i < authctxt->num_auth_methods; i++) { if (!remove_method(&(authctxt->auth_methods[i]), method, submethod)) continue; found = 1; if (*authctxt->auth_methods[i] == '\0') { debug2("authentication methods list %d complete", i); return 1; } debug3("authentication methods list %d remaining: \"%s\"", i, authctxt->auth_methods[i]); } /* This should not happen, but would be bad if it did */ if (!found) fatal_f("method not in AuthenticationMethods"); return 0; } /* Reset method-specific information */ void auth2_authctxt_reset_info(Authctxt *authctxt) { sshkey_free(authctxt->auth_method_key); free(authctxt->auth_method_info); authctxt->auth_method_key = NULL; authctxt->auth_method_info = NULL; } /* Record auth method-specific information for logs */ void auth2_record_info(Authctxt *authctxt, const char *fmt, ...) { va_list ap; int i; free(authctxt->auth_method_info); authctxt->auth_method_info = NULL; va_start(ap, fmt); i = vasprintf(&authctxt->auth_method_info, fmt, ap); va_end(ap); if (i == -1) fatal_f("vasprintf failed"); } /* * Records a public key used in authentication. This is used for logging * and to ensure that the same key is not subsequently accepted again for * multiple authentication. */ void auth2_record_key(Authctxt *authctxt, int authenticated, const struct sshkey *key) { struct sshkey **tmp, *dup; int r; if ((r = sshkey_from_private(key, &dup)) != 0) fatal_fr(r, "copy key"); sshkey_free(authctxt->auth_method_key); authctxt->auth_method_key = dup; if (!authenticated) return; /* If authenticated, make sure we don't accept this key again */ if ((r = sshkey_from_private(key, &dup)) != 0) fatal_fr(r, "copy key"); if (authctxt->nprev_keys >= INT_MAX || (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys, authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL) fatal_f("reallocarray failed"); authctxt->prev_keys = tmp; authctxt->prev_keys[authctxt->nprev_keys] = dup; authctxt->nprev_keys++; } /* Checks whether a key has already been previously used for authentication */ int auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key) { u_int i; char *fp; for (i = 0; i < authctxt->nprev_keys; i++) { if (sshkey_equal_public(key, authctxt->prev_keys[i])) { fp = sshkey_fingerprint(authctxt->prev_keys[i], options.fingerprint_hash, SSH_FP_DEFAULT); debug3_f("key already used: %s %s", sshkey_type(authctxt->prev_keys[i]), fp == NULL ? "UNKNOWN" : fp); free(fp); return 1; } } return 0; } /* * Updates authctxt->session_info with details of authentication. Should be * whenever an authentication method succeeds. */ void auth2_update_session_info(Authctxt *authctxt, const char *method, const char *submethod) { int r; if (authctxt->session_info == NULL) { if ((authctxt->session_info = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); } /* Append method[/submethod] */ if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s", method, submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod)) != 0) fatal_fr(r, "append method"); /* Append key if present */ if (authctxt->auth_method_key != NULL) { if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || (r = sshkey_format_text(authctxt->auth_method_key, authctxt->session_info)) != 0) fatal_fr(r, "append key"); } if (authctxt->auth_method_info != NULL) { /* Ensure no ambiguity here */ if (strchr(authctxt->auth_method_info, '\n') != NULL) fatal_f("auth_method_info contains \\n"); if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || (r = sshbuf_putf(authctxt->session_info, "%s", authctxt->auth_method_info)) != 0) { fatal_fr(r, "append method info"); } } if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) fatal_fr(r, "append"); } openssh-10.0p1/PaxHeaders.10889/authfd.c100644 001750 001750 0000000003614775415623 0014573xustar0030 atime=1744182234.494958194 openssh-10.0p1/authfd.c010064400017500001750000000471711477541562300131700ustar00djmdjm/* $OpenBSD: authfd.c,v 1.134 2023/12/18 14:46:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for connecting the local authentication agent. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation, * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "ssh.h" #include "sshbuf.h" #include "sshkey.h" #include "authfd.h" #include "cipher.h" #include "log.h" #include "atomicio.h" #include "misc.h" #include "ssherr.h" #define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */ #define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */ /* macro to check for "agent failure" message */ #define agent_failed(x) \ ((x == SSH_AGENT_FAILURE) || \ (x == SSH_COM_AGENT2_FAILURE) || \ (x == SSH2_AGENT_FAILURE)) /* Convert success/failure response from agent to a err.h status */ static int decode_reply(u_char type) { if (agent_failed(type)) return SSH_ERR_AGENT_FAILURE; else if (type == SSH_AGENT_SUCCESS) return 0; else return SSH_ERR_INVALID_FORMAT; } /* * Opens an authentication socket at the provided path and stores the file * descriptor in fdp. Returns 0 on success and an error on failure. */ int ssh_get_authentication_socket_path(const char *authsocket, int *fdp) { int sock, oerrno; struct sockaddr_un sunaddr; debug3_f("path '%s'", authsocket); memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) return SSH_ERR_SYSTEM_ERROR; /* close on exec */ if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 || connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { oerrno = errno; close(sock); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } if (fdp != NULL) *fdp = sock; else close(sock); return 0; } /* * Opens the default authentication socket and stores the file descriptor in * fdp. Returns 0 on success and an error on failure. */ int ssh_get_authentication_socket(int *fdp) { const char *authsocket; if (fdp != NULL) *fdp = -1; authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); if (authsocket == NULL || *authsocket == '\0') return SSH_ERR_AGENT_NOT_PRESENT; return ssh_get_authentication_socket_path(authsocket, fdp); } /* Communicate with agent: send request and read reply */ static int ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) { int r; size_t l, len; char buf[1024]; /* Get the length of the message, and format it in the buffer. */ len = sshbuf_len(request); POKE_U32(buf, len); /* Send the length and then the packet to the agent. */ if (atomicio(vwrite, sock, buf, 4) != 4 || atomicio(vwrite, sock, sshbuf_mutable_ptr(request), sshbuf_len(request)) != sshbuf_len(request)) return SSH_ERR_AGENT_COMMUNICATION; /* * Wait for response from the agent. First read the length of the * response packet. */ if (atomicio(read, sock, buf, 4) != 4) return SSH_ERR_AGENT_COMMUNICATION; /* Extract the length, and check it for sanity. */ len = PEEK_U32(buf); if (len > MAX_AGENT_REPLY_LEN) return SSH_ERR_INVALID_FORMAT; /* Read the rest of the response in to the buffer. */ sshbuf_reset(reply); while (len > 0) { l = len; if (l > sizeof(buf)) l = sizeof(buf); if (atomicio(read, sock, buf, l) != l) return SSH_ERR_AGENT_COMMUNICATION; if ((r = sshbuf_put(reply, buf, l)) != 0) return r; len -= l; } return 0; } /* Communicate with agent: sent request, read and decode status reply */ static int ssh_request_reply_decode(int sock, struct sshbuf *request) { struct sshbuf *reply; int r; u_char type; if ((reply = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = ssh_request_reply(sock, request, reply)) != 0 || (r = sshbuf_get_u8(reply, &type)) != 0 || (r = decode_reply(type)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(reply); return r; } /* * Closes the agent socket if it should be closed (depends on how it was * obtained). The argument must have been returned by * ssh_get_authentication_socket(). */ void ssh_close_authentication_socket(int sock) { if (getenv(SSH_AUTHSOCKET_ENV_NAME)) close(sock); } /* Lock/unlock agent */ int ssh_lock_agent(int sock, int lock, const char *password) { int r; u_char type = lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK; struct sshbuf *msg; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_cstring(msg, password)) != 0 || (r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } static int deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) { int r; char *comment = NULL; const u_char *blob; size_t blen; if ((r = sshbuf_get_string_direct(ids, &blob, &blen)) != 0 || (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) goto out; if ((r = sshkey_from_blob(blob, blen, keyp)) != 0) goto out; if (commentp != NULL) { *commentp = comment; comment = NULL; } r = 0; out: free(comment); return r; } /* * Fetch list of identities held by the agent. */ int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp) { u_char type; u_int32_t num, i; struct sshbuf *msg; struct ssh_identitylist *idl = NULL; int r; /* * Send a message to the agent requesting for a list of the * identities it can represent. */ if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REQUEST_IDENTITIES)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) goto out; /* Get message type, and verify that we got a proper answer. */ if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; if (agent_failed(type)) { r = SSH_ERR_AGENT_FAILURE; goto out; } else if (type != SSH2_AGENT_IDENTITIES_ANSWER) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* Get the number of entries in the response and check it for sanity. */ if ((r = sshbuf_get_u32(msg, &num)) != 0) goto out; if (num > MAX_AGENT_IDENTITIES) { r = SSH_ERR_INVALID_FORMAT; goto out; } if (num == 0) { r = SSH_ERR_AGENT_NO_IDENTITIES; goto out; } /* Deserialise the response into a list of keys/comments */ if ((idl = calloc(1, sizeof(*idl))) == NULL || (idl->keys = calloc(num, sizeof(*idl->keys))) == NULL || (idl->comments = calloc(num, sizeof(*idl->comments))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < num;) { if ((r = deserialise_identity2(msg, &(idl->keys[i]), &(idl->comments[i]))) != 0) { if (r == SSH_ERR_KEY_TYPE_UNKNOWN) { /* Gracefully skip unknown key types */ num--; continue; } else goto out; } i++; } idl->nkeys = num; *idlp = idl; idl = NULL; r = 0; out: sshbuf_free(msg); if (idl != NULL) ssh_free_identitylist(idl); return r; } void ssh_free_identitylist(struct ssh_identitylist *idl) { size_t i; if (idl == NULL) return; for (i = 0; i < idl->nkeys; i++) { if (idl->keys != NULL) sshkey_free(idl->keys[i]); if (idl->comments != NULL) free(idl->comments[i]); } free(idl->keys); free(idl->comments); free(idl); } /* * Check if the ssh agent has a given key. * Returns 0 if found, or a negative SSH_ERR_* error code on failure. */ int ssh_agent_has_key(int sock, const struct sshkey *key) { int r, ret = SSH_ERR_KEY_NOT_FOUND; size_t i; struct ssh_identitylist *idlist = NULL; if ((r = ssh_fetch_identitylist(sock, &idlist)) != 0) { return r; } for (i = 0; i < idlist->nkeys; i++) { if (sshkey_equal_public(idlist->keys[i], key)) { ret = 0; break; } } ssh_free_identitylist(idlist); return ret; } /* * Sends a challenge (typically from a server via ssh(1)) to the agent, * and waits for a response from the agent. * Returns true (non-zero) if the agent gave the correct answer, zero * otherwise. */ /* encode signature algorithm in flag bits, so we can keep the msg format */ static u_int agent_encode_alg(const struct sshkey *key, const char *alg) { if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) { if (strcmp(alg, "rsa-sha2-256") == 0 || strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0) return SSH_AGENT_RSA_SHA2_256; if (strcmp(alg, "rsa-sha2-512") == 0 || strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0) return SSH_AGENT_RSA_SHA2_512; } return 0; } /* ask agent to sign data, returns err.h code on error, 0 on success */ int ssh_agent_sign(int sock, const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, u_int compat) { struct sshbuf *msg; u_char *sig = NULL, type = 0; size_t len = 0; u_int flags = 0; int r = SSH_ERR_INTERNAL_ERROR; *sigp = NULL; *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; flags |= agent_encode_alg(key, alg); if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || (r = sshkey_puts(key, msg)) != 0 || (r = sshbuf_put_string(msg, data, datalen)) != 0 || (r = sshbuf_put_u32(msg, flags)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) goto out; if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; if (agent_failed(type)) { r = SSH_ERR_AGENT_FAILURE; goto out; } else if (type != SSH2_AGENT_SIGN_RESPONSE) { r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_string(msg, &sig, &len)) != 0) goto out; /* Check what we actually got back from the agent. */ if ((r = sshkey_check_sigtype(sig, len, alg)) != 0) goto out; /* success */ *sigp = sig; *lenp = len; sig = NULL; len = 0; r = 0; out: freezero(sig, len); sshbuf_free(msg); return r; } /* Encode key for a message to the agent. */ static int encode_dest_constraint_hop(struct sshbuf *m, const struct dest_constraint_hop *dch) { struct sshbuf *b; u_int i; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, dch->user)) != 0 || (r = sshbuf_put_cstring(b, dch->hostname)) != 0 || (r = sshbuf_put_string(b, NULL, 0)) != 0) /* reserved */ goto out; for (i = 0; i < dch->nkeys; i++) { if ((r = sshkey_puts(dch->keys[i], b)) != 0 || (r = sshbuf_put_u8(b, dch->key_is_ca[i] != 0)) != 0) goto out; } if ((r = sshbuf_put_stringb(m, b)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } static int encode_dest_constraint(struct sshbuf *m, const struct dest_constraint *dc) { struct sshbuf *b; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = encode_dest_constraint_hop(b, &dc->from)) != 0 || (r = encode_dest_constraint_hop(b, &dc->to)) != 0 || (r = sshbuf_put_string(b, NULL, 0)) != 0) /* reserved */ goto out; if ((r = sshbuf_put_stringb(m, b)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } static int encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign, const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints, int cert_only, struct sshkey **certs, size_t ncerts) { int r; struct sshbuf *b = NULL; size_t i; if (life != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_LIFETIME)) != 0 || (r = sshbuf_put_u32(m, life)) != 0) goto out; } if (confirm != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0) goto out; } if (maxsign != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_MAXSIGN)) != 0 || (r = sshbuf_put_u32(m, maxsign)) != 0) goto out; } if (provider != NULL) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || (r = sshbuf_put_cstring(m, "sk-provider@openssh.com")) != 0 || (r = sshbuf_put_cstring(m, provider)) != 0) goto out; } if (dest_constraints != NULL && ndest_constraints > 0) { if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < ndest_constraints; i++) { if ((r = encode_dest_constraint(b, dest_constraints[i])) != 0) goto out; } if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || (r = sshbuf_put_cstring(m, "restrict-destination-v00@openssh.com")) != 0 || (r = sshbuf_put_stringb(m, b)) != 0) goto out; sshbuf_free(b); b = NULL; } if (ncerts != 0) { if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < ncerts; i++) { if ((r = sshkey_puts(certs[i], b)) != 0) goto out; } if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || (r = sshbuf_put_cstring(m, "associated-certs-v00@openssh.com")) != 0 || (r = sshbuf_put_u8(m, cert_only != 0)) != 0 || (r = sshbuf_put_stringb(m, b)) != 0) goto out; sshbuf_free(b); b = NULL; } r = 0; out: sshbuf_free(b); return r; } /* * Adds an identity to the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, u_int life, u_int confirm, u_int maxsign, const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { struct sshbuf *msg; int r, constrained = (life || confirm || maxsign || provider || dest_constraints); u_char type; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; switch (key->type) { #ifdef WITH_OPENSSL case KEY_RSA: case KEY_RSA_CERT: case KEY_DSA: case KEY_DSA_CERT: case KEY_ECDSA: case KEY_ECDSA_CERT: case KEY_ECDSA_SK: case KEY_ECDSA_SK_CERT: #endif case KEY_ED25519: case KEY_ED25519_CERT: case KEY_ED25519_SK: case KEY_ED25519_SK_CERT: case KEY_XMSS: case KEY_XMSS_CERT: type = constrained ? SSH2_AGENTC_ADD_ID_CONSTRAINED : SSH2_AGENTC_ADD_IDENTITY; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshkey_private_serialize_maxsign(key, msg, maxsign, 0)) != 0 || (r = sshbuf_put_cstring(msg, comment)) != 0) goto out; break; default: r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (constrained && (r = encode_constraints(msg, life, confirm, maxsign, provider, dest_constraints, ndest_constraints, 0, NULL, 0)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } /* * Removes an identity from the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_remove_identity(int sock, const struct sshkey *key) { struct sshbuf *msg; int r; u_char *blob = NULL; size_t blen; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if (key->type != KEY_UNSPEC) { if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) goto out; if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REMOVE_IDENTITY)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0) goto out; } else { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: if (blob != NULL) freezero(blob, blen); sshbuf_free(msg); return r; } /* * Add/remove an token-based identity from the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_update_card(int sock, int add, const char *reader_id, const char *pin, u_int life, u_int confirm, struct dest_constraint **dest_constraints, size_t ndest_constraints, int cert_only, struct sshkey **certs, size_t ncerts) { struct sshbuf *msg; int r, constrained = (life || confirm || dest_constraints || certs); u_char type; if (add) { type = constrained ? SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED : SSH_AGENTC_ADD_SMARTCARD_KEY; } else type = SSH_AGENTC_REMOVE_SMARTCARD_KEY; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_cstring(msg, reader_id)) != 0 || (r = sshbuf_put_cstring(msg, pin)) != 0) goto out; if (constrained && (r = encode_constraints(msg, life, confirm, 0, NULL, dest_constraints, ndest_constraints, cert_only, certs, ncerts)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } /* * Removes all identities from the agent. * This call is intended only for use by ssh-add(1) and like applications. * * This supports the SSH protocol 1 message to because, when clearing all * keys from an agent, we generally want to clear both protocol v1 and v2 * keys. */ int ssh_remove_all_identities(int sock, int version) { struct sshbuf *msg; u_char type = (version == 1) ? SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : SSH2_AGENTC_REMOVE_ALL_IDENTITIES; int r; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } /* Binds a session ID to a hostkey via the initial KEX signature. */ int ssh_agent_bind_hostkey(int sock, const struct sshkey *key, const struct sshbuf *session_id, const struct sshbuf *signature, int forwarding) { struct sshbuf *msg; int r; if (key == NULL || session_id == NULL || signature == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, SSH_AGENTC_EXTENSION)) != 0 || (r = sshbuf_put_cstring(msg, "session-bind@openssh.com")) != 0 || (r = sshkey_puts(key, msg)) != 0 || (r = sshbuf_put_stringb(msg, session_id)) != 0 || (r = sshbuf_put_stringb(msg, signature)) != 0 || (r = sshbuf_put_u8(msg, forwarding ? 1 : 0)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } openssh-10.0p1/PaxHeaders.10889/authfd.h100644 001750 001750 0000000003614775415623 0014600xustar0030 atime=1744182234.494958194 openssh-10.0p1/authfd.h010064400017500001750000000101261477541562300131630ustar00djmdjm/* $OpenBSD: authfd.h,v 1.52 2023/12/18 14:46:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions to interface with the SSH_AUTHENTICATION_FD socket. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef AUTHFD_H #define AUTHFD_H struct sshbuf; struct sshkey; /* List of identities returned by ssh_fetch_identitylist() */ struct ssh_identitylist { size_t nkeys; struct sshkey **keys; char **comments; }; /* Key destination restrictions */ struct dest_constraint_hop { char *user; /* wildcards allowed */ char *hostname; /* used to matching cert principals and for display */ int is_ca; u_int nkeys; /* number of entries in *both* 'keys' and 'key_is_ca' */ struct sshkey **keys; int *key_is_ca; }; struct dest_constraint { struct dest_constraint_hop from; struct dest_constraint_hop to; }; int ssh_get_authentication_socket(int *fdp); int ssh_get_authentication_socket_path(const char *authsocket, int *fdp); void ssh_close_authentication_socket(int sock); int ssh_lock_agent(int sock, int lock, const char *password); int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp); void ssh_free_identitylist(struct ssh_identitylist *idl); int ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, u_int life, u_int confirm, u_int maxsign, const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints); int ssh_agent_has_key(int sock, const struct sshkey *key); int ssh_remove_identity(int sock, const struct sshkey *key); int ssh_update_card(int sock, int add, const char *reader_id, const char *pin, u_int life, u_int confirm, struct dest_constraint **dest_constraints, size_t ndest_constraints, int cert_only, struct sshkey **certs, size_t ncerts); int ssh_remove_all_identities(int sock, int version); int ssh_agent_sign(int sock, const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, u_int compat); int ssh_agent_bind_hostkey(int sock, const struct sshkey *key, const struct sshbuf *session_id, const struct sshbuf *signature, int forwarding); /* Messages for the authentication agent connection. */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 #define SSH_AGENTC_RSA_CHALLENGE 3 #define SSH_AGENT_RSA_RESPONSE 4 #define SSH_AGENT_FAILURE 5 #define SSH_AGENT_SUCCESS 6 #define SSH_AGENTC_ADD_RSA_IDENTITY 7 #define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 #define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* private OpenSSH extensions for SSH2 */ #define SSH2_AGENTC_REQUEST_IDENTITIES 11 #define SSH2_AGENT_IDENTITIES_ANSWER 12 #define SSH2_AGENTC_SIGN_REQUEST 13 #define SSH2_AGENT_SIGN_RESPONSE 14 #define SSH2_AGENTC_ADD_IDENTITY 17 #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 /* smartcard */ #define SSH_AGENTC_ADD_SMARTCARD_KEY 20 #define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 /* lock/unlock the agent */ #define SSH_AGENTC_LOCK 22 #define SSH_AGENTC_UNLOCK 23 /* add key with constraints */ #define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 /* generic extension mechanism */ #define SSH_AGENTC_EXTENSION 27 #define SSH_AGENT_CONSTRAIN_LIFETIME 1 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 #define SSH_AGENT_CONSTRAIN_MAXSIGN 3 #define SSH_AGENT_CONSTRAIN_EXTENSION 255 /* extended failure messages */ #define SSH2_AGENT_FAILURE 30 /* additional error code for ssh.com's ssh-agent2 */ #define SSH_COM_AGENT2_FAILURE 102 #define SSH_AGENT_OLD_SIGNATURE 0x01 #define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_512 0x04 #endif /* AUTHFD_H */ openssh-10.0p1/PaxHeaders.10889/authfile.c100644 001750 001750 0000000003614775415623 0015121xustar0030 atime=1744182234.494958194 openssh-10.0p1/authfile.c010064400017500001750000000306561477541562300135160ustar00djmdjm/* $OpenBSD: authfile.c,v 1.145 2024/09/22 12:56:21 jsg Exp $ */ /* * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include "cipher.h" #include "ssh.h" #include "log.h" #include "authfile.h" #include "misc.h" #include "atomicio.h" #include "sshkey.h" #include "sshbuf.h" #include "ssherr.h" #include "krl.h" /* Save a key blob to a file */ static int sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) { int r; mode_t omask; 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 format, const char *openssh_format_cipher, int openssh_format_rounds) { struct sshbuf *keyblob = NULL; int r; if ((keyblob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment, format, openssh_format_cipher, openssh_format_rounds)) != 0) goto out; if ((r = sshkey_save_private_blob(keyblob, filename)) != 0) goto out; r = 0; out: sshbuf_free(keyblob); return r; } /* XXX remove error() calls from here? */ int sshkey_perm_ok(int fd, const char *filename) { struct stat st; if (fstat(fd, &st) == -1) return SSH_ERR_SYSTEM_ERROR; /* * if a key owned by the user is accessed, then we check the * permissions of the file. if the key owned by a different user, * then we don't care. */ #ifdef HAVE_CYGWIN if (check_ntsec(filename)) #endif if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("Permissions 0%3.3o for '%s' are too open.", (u_int)st.st_mode & 0777, filename); 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; } int sshkey_load_private_type(int type, const char *filename, const char *passphrase, struct sshkey **keyp, char **commentp) { int fd, r; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; if ((fd = open(filename, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; r = sshkey_perm_ok(fd, filename); if (r != 0) goto out; r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp); if (r == 0 && keyp && *keyp) r = sshkey_set_filename(*keyp, filename); out: close(fd); return r; } 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 (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; /* success */ r = 0; out: sshbuf_free(buffer); return r; } /* Load a pubkey from the unencrypted envelope of a new-format private key */ static int sshkey_load_pubkey_from_private(const char *filename, struct sshkey **pubkeyp) { struct sshbuf *buffer = NULL; struct sshkey *pubkey = NULL; int r, fd; if (pubkeyp != NULL) *pubkeyp = NULL; if ((fd = open(filename, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || (r = sshkey_parse_pubkey_from_private_fileblob_type(buffer, KEY_UNSPEC, &pubkey)) != 0) goto out; if ((r = sshkey_set_filename(pubkey, filename)) != 0) goto out; /* success */ if (pubkeyp != NULL) { *pubkeyp = pubkey; pubkey = NULL; } r = 0; out: close(fd); sshbuf_free(buffer); sshkey_free(pubkey); return r; } static int sshkey_try_load_public(struct sshkey **kp, const char *filename, char **commentp) { FILE *f; char *line = NULL, *cp; size_t linesize = 0; int r; struct sshkey *k = NULL; if (kp == NULL) return SSH_ERR_INVALID_ARGUMENT; *kp = NULL; if (commentp != NULL) *commentp = NULL; if ((f = fopen(filename, "r")) == NULL) return SSH_ERR_SYSTEM_ERROR; if ((k = sshkey_new(KEY_UNSPEC)) == NULL) { fclose(f); return SSH_ERR_ALLOC_FAIL; } while (getline(&line, &linesize, f) != -1) { cp = line; switch (*cp) { case '#': case '\n': case '\0': continue; } /* Abort loading if this looks like a private key */ if (strncmp(cp, "-----BEGIN", 10) == 0 || strcmp(cp, "SSH PRIVATE KEY FILE") == 0) break; /* Skip leading whitespace. */ for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) ; if (*cp) { if ((r = sshkey_read(k, &cp)) == 0) { cp[strcspn(cp, "\r\n")] = '\0'; if (commentp) { *commentp = strdup(*cp ? cp : filename); 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 any pubkey file */ int sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) { char *pubfile = NULL; int r, oerrno; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; if ((r = sshkey_try_load_public(keyp, filename, commentp)) == 0) goto out; /* try .pub suffix */ if (asprintf(&pubfile, "%s.pub", filename) == -1) return SSH_ERR_ALLOC_FAIL; 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; /* Pretend we couldn't find the key */ r = SSH_ERR_SYSTEM_ERROR; errno = ENOENT; out: oerrno = errno; free(pubfile); errno = oerrno; return r; } /* Load the certificate associated with the named private key */ int sshkey_load_cert(const char *filename, struct sshkey **keyp) { struct sshkey *pub = NULL; char *file = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (keyp != NULL) *keyp = NULL; if (asprintf(&file, "%s-cert.pub", filename) == -1) return SSH_ERR_ALLOC_FAIL; 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) { struct sshkey *key = NULL, *cert = NULL; int r; if (keyp != NULL) *keyp = NULL; switch (type) { #ifdef WITH_OPENSSL case KEY_RSA: case KEY_DSA: case KEY_ECDSA: #endif /* WITH_OPENSSL */ case KEY_ED25519: case KEY_XMSS: case KEY_UNSPEC: break; default: return SSH_ERR_KEY_TYPE_UNKNOWN; } if ((r = sshkey_load_private_type(type, filename, passphrase, &key, NULL)) != 0 || (r = sshkey_load_cert(filename, &cert)) != 0) goto out; /* Make sure the private key matches the certificate */ if (sshkey_equal_public(key, cert) == 0) { r = SSH_ERR_KEY_CERT_MISMATCH; goto out; } if ((r = sshkey_to_certified(key)) != 0 || (r = sshkey_cert_copy(cert, key)) != 0) goto out; r = 0; if (keyp != NULL) { *keyp = key; key = NULL; } out: sshkey_free(key); sshkey_free(cert); return r; } /* * Returns success if the specified "key" is listed in the file "filename", * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. * If "strict_type" is set then the key type must match exactly, * otherwise a comparison that ignores certificate data is performed. * If "check_ca" is set and "key" is a certificate, then its CA key is * also checked and sshkey_in_file() will return success if either is found. */ int sshkey_in_file(struct sshkey *key, const char *filename, int strict_type, int check_ca) { FILE *f; 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 (getline(&line, &linesize, f) != -1) { sshkey_free(pub); pub = NULL; cp = line; /* Skip leading whitespace. */ for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) ; /* Skip comments and empty lines */ switch (*cp) { case '#': case '\n': case '\0': continue; } if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } 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; } } r = SSH_ERR_KEY_NOT_FOUND; out: free(line); sshkey_free(pub); fclose(f); return r; } /* * Checks whether the specified key is revoked, returning 0 if not, * SSH_ERR_KEY_REVOKED if it is or another error code if something * unexpected happened. * This will check both the key and, if it is a certificate, its CA key too. * "revoked_keys_file" may be a KRL or a one-per-line list of public keys. */ int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file) { int r; r = ssh_krl_file_contains_key(revoked_keys_file, key); /* If this was not a KRL to begin with then continue below */ if (r != SSH_ERR_KRL_BAD_MAGIC) return r; /* * If the file is not a KRL or we can't handle KRLs then attempt to * parse the file as a flat list of keys. */ switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) { case 0: /* Key found => revoked */ return SSH_ERR_KEY_REVOKED; case SSH_ERR_KEY_NOT_FOUND: /* Key not found => not revoked */ return 0; default: /* Some other error occurred */ return r; } } /* * 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; close(fd); goto fail; } if ((r = sshkey_write(key, f)) != 0) goto fail; fprintf(f, " %s\n", comment); if (ferror(f)) { r = SSH_ERR_SYSTEM_ERROR; goto fail; } if (fclose(f) != 0) { r = SSH_ERR_SYSTEM_ERROR; f = NULL; fail: if (f != NULL) { oerrno = errno; fclose(f); errno = oerrno; } return r; } return 0; } openssh-10.0p1/PaxHeaders.10889/authfile.h100644 001750 001750 0000000003614775415623 0015126xustar0030 atime=1744182234.494958194 openssh-10.0p1/authfile.h010064400017500001750000000046501477541562300135160ustar00djmdjm/* $OpenBSD: authfile.h,v 1.25 2020/01/25 23:02:13 djm Exp $ */ /* * Copyright (c) 2000, 2013 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 AUTHFILE_H #define AUTHFILE_H struct sshbuf; struct sshkey; /* XXX document these */ /* XXX some of these could probably be merged/retired */ int sshkey_save_private(struct sshkey *, const char *, const char *, const char *, int, const char *, int); 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 sshkey_load_private_type(int, const char *, const char *, 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 openssh-10.0p1/PaxHeaders.10889/bitmap.c100644 001750 001750 0000000003614775415623 0014574xustar0030 atime=1744182234.494958194 openssh-10.0p1/bitmap.c010064400017500001750000000106761477541562300131710ustar00djmdjm/* $OpenBSD: bitmap.c,v 1.9 2017/10/20 01:56:39 djm Exp $ */ /* * Copyright (c) 2015 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include "bitmap.h" #define BITMAP_WTYPE u_int #define BITMAP_MAX (1<<24) #define BITMAP_BYTES (sizeof(BITMAP_WTYPE)) #define BITMAP_BITS (sizeof(BITMAP_WTYPE) * 8) #define BITMAP_WMASK ((BITMAP_WTYPE)BITMAP_BITS - 1) struct bitmap { BITMAP_WTYPE *d; size_t len; /* number of words allocated */ size_t top; /* index of top word allocated */ }; struct bitmap * bitmap_new(void) { struct bitmap *ret; if ((ret = calloc(1, sizeof(*ret))) == NULL) return NULL; if ((ret->d = calloc(1, BITMAP_BYTES)) == NULL) { free(ret); return NULL; } ret->len = 1; ret->top = 0; return ret; } void bitmap_free(struct bitmap *b) { if (b != NULL && b->d != NULL) { bitmap_zero(b); free(b->d); b->d = NULL; } free(b); } void bitmap_zero(struct bitmap *b) { memset(b->d, 0, b->len * BITMAP_BYTES); b->top = 0; } int bitmap_test_bit(struct bitmap *b, u_int n) { if (b->top >= b->len) return 0; /* invalid */ if (b->len == 0 || (n / BITMAP_BITS) > b->top) return 0; return (b->d[n / BITMAP_BITS] >> (n & BITMAP_WMASK)) & 1; } static int reserve(struct bitmap *b, u_int n) { BITMAP_WTYPE *tmp; size_t nlen; if (b->top >= b->len || n > BITMAP_MAX) return -1; /* invalid */ nlen = (n / BITMAP_BITS) + 1; if (b->len < nlen) { if ((tmp = recallocarray(b->d, b->len, nlen, BITMAP_BYTES)) == NULL) return -1; b->d = tmp; b->len = nlen; } return 0; } int bitmap_set_bit(struct bitmap *b, u_int n) { int r; size_t offset; if ((r = reserve(b, n)) != 0) return r; offset = n / BITMAP_BITS; if (offset > b->top) b->top = offset; b->d[offset] |= (BITMAP_WTYPE)1 << (n & BITMAP_WMASK); return 0; } /* Resets b->top to point to the most significant bit set in b->d */ static void retop(struct bitmap *b) { if (b->top >= b->len) return; while (b->top > 0 && b->d[b->top] == 0) b->top--; } void bitmap_clear_bit(struct bitmap *b, u_int n) { size_t offset; if (b->top >= b->len || n > BITMAP_MAX) return; /* invalid */ offset = n / BITMAP_BITS; if (offset > b->top) return; b->d[offset] &= ~((BITMAP_WTYPE)1 << (n & BITMAP_WMASK)); /* The top may have changed as a result of the clear */ retop(b); } size_t bitmap_nbits(struct bitmap *b) { size_t bits; BITMAP_WTYPE w; retop(b); if (b->top >= b->len) return 0; /* invalid */ if (b->len == 0 || (b->top == 0 && b->d[0] == 0)) return 0; /* Find MSB set */ w = b->d[b->top]; bits = (b->top + 1) * BITMAP_BITS; while (!(w & ((BITMAP_WTYPE)1 << (BITMAP_BITS - 1)))) { w <<= 1; bits--; } return bits; } size_t bitmap_nbytes(struct bitmap *b) { return (bitmap_nbits(b) + 7) / 8; } int bitmap_to_string(struct bitmap *b, void *p, size_t l) { u_char *s = (u_char *)p; size_t i, j, k, need = bitmap_nbytes(b); if (l < need || b->top >= b->len) return -1; if (l > need) l = need; /* Put the bytes from LSB backwards */ for (i = k = 0; i < b->top + 1; i++) { for (j = 0; j < BITMAP_BYTES; j++) { if (k >= l) break; s[need - 1 - k++] = (b->d[i] >> (j * 8)) & 0xff; } } return 0; } int bitmap_from_string(struct bitmap *b, const void *p, size_t l) { int r; size_t i, offset, shift; const u_char *s = (const u_char *)p; if (l > BITMAP_MAX / 8) return -1; if ((r = reserve(b, l * 8)) != 0) return r; bitmap_zero(b); if (l == 0) return 0; b->top = offset = ((l + (BITMAP_BYTES - 1)) / BITMAP_BYTES) - 1; shift = ((l + (BITMAP_BYTES - 1)) % BITMAP_BYTES) * 8; for (i = 0; i < l; i++) { b->d[offset] |= (BITMAP_WTYPE)s[i] << shift; if (shift == 0) { offset--; shift = BITMAP_BITS - 8; } else shift -= 8; } retop(b); return 0; } openssh-10.0p1/PaxHeaders.10889/bitmap.h100644 001750 001750 0000000003614775415623 0014601xustar0030 atime=1744182234.494958194 openssh-10.0p1/bitmap.h010064400017500001750000000036311477541562300131670ustar00djmdjm/* $OpenBSD: bitmap.h,v 1.2 2017/10/20 01:56:39 djm Exp $ */ /* * Copyright (c) 2015 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. */ #ifndef _BITMAP_H #define _BITMAP_H #include /* Simple bit vector routines */ struct bitmap; /* Allocate a new bitmap. Returns NULL on allocation failure. */ struct bitmap *bitmap_new(void); /* Free a bitmap */ void bitmap_free(struct bitmap *b); /* Zero an existing bitmap */ void bitmap_zero(struct bitmap *b); /* Test whether a bit is set in a bitmap. */ int bitmap_test_bit(struct bitmap *b, u_int n); /* Set a bit in a bitmap. Returns 0 on success or -1 on error */ int bitmap_set_bit(struct bitmap *b, u_int n); /* Clear a bit in a bitmap */ void bitmap_clear_bit(struct bitmap *b, u_int n); /* Return the number of bits in a bitmap (i.e. the position of the MSB) */ size_t bitmap_nbits(struct bitmap *b); /* Return the number of bytes needed to represent a bitmap */ size_t bitmap_nbytes(struct bitmap *b); /* Convert a bitmap to a big endian byte string */ int bitmap_to_string(struct bitmap *b, void *p, size_t l); /* Convert a big endian byte string to a bitmap */ int bitmap_from_string(struct bitmap *b, const void *p, size_t l); #endif /* _BITMAP_H */ openssh-10.0p1/PaxHeaders.10889/buildpkg.sh.in100644 001750 001750 0000000003614775415623 0015716xustar0030 atime=1744182234.503735116 openssh-10.0p1/buildpkg.sh.in010064400017500001750000000432001477541562300143000ustar00djmdjm#!/bin/sh # # Fake Root Solaris/SVR4/SVR5 Build System - Prototype # # The following code has been provide under Public Domain License. I really # don't care what you use it for. Just as long as you don't complain to me # nor my employer if you break it. - Ben Lindstrom (mouring@eviladmin.org) # umask 022 # # Options for building the package # You can create a openssh-config.local with your customized options # REMOVE_FAKE_ROOT_WHEN_DONE=yes # # uncommenting TEST_DIR and using # configure --prefix=/var/tmp --with-privsep-path=/var/tmp/empty # and # PKGNAME=tOpenSSH should allow testing a package without interfering # with a real OpenSSH package on a system. This is not needed on systems # that support the -R option to pkgadd. #TEST_DIR=/var/tmp # leave commented out for production build PKGNAME=OpenSSH # revisions within the same version (REV=a) #REV= SYSVINIT_NAME=opensshd AWK=${AWK:="nawk"} MAKE=${MAKE:="make"} SSHDUID=67 # Default privsep uid SSHDGID=67 # Default privsep gid # uncomment these next three as needed #PERMIT_ROOT_LOGIN=no #X11_FORWARDING=yes #USR_LOCAL_IS_SYMLINK=yes # System V init run levels SYSVINITSTART=S98 SYSVINITSTOP=K30 # We will source these if they exist POST_MAKE_INSTALL_FIXES=./pkg-post-make-install-fixes.sh POST_PROTOTYPE_EDITS=./pkg-post-prototype-edit.sh # We'll be one level deeper looking for these PKG_PREINSTALL_LOCAL=../pkg-preinstall.local PKG_POSTINSTALL_LOCAL=../pkg-postinstall.local PKG_PREREMOVE_LOCAL=../pkg-preremove.local PKG_POSTREMOVE_LOCAL=../pkg-postremove.local PKG_REQUEST_LOCAL=../pkg-request.local # end of sourced files # OPENSSHD=opensshd.init OPENSSH_MANIFEST=openssh.xml OPENSSH_FMRI=svc:/site/${SYSVINIT_NAME}:default SMF_METHOD_DIR=/lib/svc/method/site SMF_MANIFEST_DIR=/var/svc/manifest/site PATH_GROUPADD_PROG=@PATH_GROUPADD_PROG@ PATH_USERADD_PROG=@PATH_USERADD_PROG@ PATH_PASSWD_PROG=@PATH_PASSWD_PROG@ # # list of system directories we do NOT want to change owner/group/perms # when installing our package SYSTEM_DIR="/etc \ /etc/init.d \ /etc/rcS.d \ /etc/rc0.d \ /etc/rc1.d \ /etc/rc2.d \ /etc/opt \ /lib \ /lib/svc \ /lib/svc/method \ /lib/svc/method/site \ /opt \ /opt/bin \ /usr \ /usr/bin \ /usr/lib \ /usr/sbin \ /usr/share \ /usr/share/man \ /usr/share/man/man1 \ /usr/share/man/man8 \ /usr/local \ /usr/local/bin \ /usr/local/etc \ /usr/local/libexec \ /usr/local/man \ /usr/local/man/man1 \ /usr/local/man/man8 \ /usr/local/sbin \ /usr/local/share \ /var \ /var/opt \ /var/run \ /var/svc \ /var/svc/manifest \ /var/svc/manifest/site \ /var/tmp \ /tmp" # We may need to build as root so we make sure PATH is set up # only set the path if it's not set already [ -d /opt/bin ] && { echo $PATH | grep ":/opt/bin" > /dev/null 2>&1 [ $? -ne 0 ] && PATH=$PATH:/opt/bin } [ -d /usr/local/bin ] && { echo $PATH | grep ":/usr/local/bin" > /dev/null 2>&1 [ $? -ne 0 ] && PATH=$PATH:/usr/local/bin } [ -d /usr/ccs/bin ] && { echo $PATH | grep ":/usr/ccs/bin" > /dev/null 2>&1 [ $? -ne 0 ] && PATH=$PATH:/usr/ccs/bin } export PATH # [ -f Makefile ] || { echo "Please run this script from your build directory" exit 1 } # we will look for openssh-config.local to override the above options [ -s ./openssh-config.local ] && . ./openssh-config.local START=`pwd` FAKE_ROOT=$START/pkg ## Fill in some details, like prefix and sysconfdir for confvar in prefix exec_prefix bindir sbindir libexecdir datadir mandir sysconfdir piddir srcdir do eval $confvar=`grep "^$confvar=" Makefile | cut -d = -f 2` done ## Are we using Solaris' SMF? DO_SMF=0 if egrep "^#define USE_SOLARIS_PROCESS_CONTRACTS" config.h > /dev/null 2>&1 then DO_SMF=1 fi ## Collect value of privsep user for confvar in SSH_PRIVSEP_USER do eval $confvar=`awk '/#define[ \t]'$confvar'/{print $3}' config.h` done ## Set privsep defaults if not defined if [ -z "$SSH_PRIVSEP_USER" ] then SSH_PRIVSEP_USER=sshd fi ## Extract common info requires for the 'info' part of the package. VERSION=`./ssh -V 2>&1 | sed -e 's/,.*//'` ARCH=`uname -m` DEF_MSG="\n" OS_VER=`uname -v` SCRIPT_SHELL=/sbin/sh UNAME_R=`uname -r` UNAME_S=`uname -s` case ${UNAME_S} in SunOS) UNAME_S=Solaris OS_VER=${UNAME_R} ARCH=`uname -p` RCS_D=yes DEF_MSG="(default: n)" ;; SCO_SV) case ${UNAME_R} in 3.2) UNAME_S=OpenServer5 OS_VER=`uname -X | grep Release | sed -e 's/^Rel.*3.2v//'` ;; 5) UNAME_S=OpenServer6 ;; esac SCRIPT_SHELL=/bin/sh RC1_D=no DEF_MSG="(default: n)" ;; esac case `basename $0` in buildpkg.sh) ## Start by faking root install echo "Faking root install..." [ -d $FAKE_ROOT ] && rm -fr $FAKE_ROOT mkdir $FAKE_ROOT ${MAKE} install-nokeys DESTDIR=$FAKE_ROOT if [ $? -gt 0 ] then echo "Fake root install failed, stopping." exit 1 fi ## Setup our run level stuff while we are at it. if [ $DO_SMF -eq 1 ] then # For Solaris' SMF, /lib/svc/method/site is the preferred place # for start/stop scripts that aren't supplied with the OS, and # similarly /var/svc/manifest/site for manifests. mkdir -p $FAKE_ROOT${TEST_DIR}${SMF_METHOD_DIR} mkdir -p $FAKE_ROOT${TEST_DIR}${SMF_MANIFEST_DIR} cp ${OPENSSHD} $FAKE_ROOT${TEST_DIR}${SMF_METHOD_DIR}/${SYSVINIT_NAME} chmod 744 $FAKE_ROOT${TEST_DIR}${SMF_METHOD_DIR}/${SYSVINIT_NAME} cat ${OPENSSH_MANIFEST} | \ sed -e "s|__SYSVINIT_NAME__|${SYSVINIT_NAME}|" \ -e "s|__SMF_METHOD_DIR__|${SMF_METHOD_DIR}|" \ > $FAKE_ROOT${TEST_DIR}${SMF_MANIFEST_DIR}/${SYSVINIT_NAME}.xml chmod 644 $FAKE_ROOT${TEST_DIR}${SMF_MANIFEST_DIR}/${SYSVINIT_NAME}.xml else mkdir -p $FAKE_ROOT${TEST_DIR}/etc/init.d cp ${OPENSSHD} $FAKE_ROOT${TEST_DIR}/etc/init.d/${SYSVINIT_NAME} chmod 744 $FAKE_ROOT${TEST_DIR}/etc/init.d/${SYSVINIT_NAME} fi [ "${PERMIT_ROOT_LOGIN}" = no ] && \ perl -p -i -e "s/#PermitRootLogin yes/PermitRootLogin no/" \ $FAKE_ROOT${sysconfdir}/sshd_config [ "${X11_FORWARDING}" = yes ] && \ perl -p -i -e "s/#X11Forwarding no/X11Forwarding yes/" \ $FAKE_ROOT${sysconfdir}/sshd_config # fix PrintMotd perl -p -i -e "s/#PrintMotd yes/PrintMotd no/" \ $FAKE_ROOT${sysconfdir}/sshd_config # We don't want to overwrite config files on multiple installs mv $FAKE_ROOT${sysconfdir}/ssh_config $FAKE_ROOT${sysconfdir}/ssh_config.default mv $FAKE_ROOT${sysconfdir}/sshd_config $FAKE_ROOT${sysconfdir}/sshd_config.default # local tweeks here [ -s "${POST_MAKE_INSTALL_FIXES}" ] && . ${POST_MAKE_INSTALL_FIXES} cd $FAKE_ROOT ## Ok, this is outright wrong, but it will work. I'm tired of pkgmk ## whining. for i in *; do PROTO_ARGS="$PROTO_ARGS $i=/$i"; done ## Build info file echo "Building pkginfo file..." 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 - https://www.openssh.com/portable.html" ARCH=$ARCH VERSION=$VERSION$REV CATEGORY="Security,application" BASEDIR=/ CLASSES="none" PSTAMP="${UNAME_S} ${OS_VER} ${ARCH} `date '+%d%b%Y %H:%M'`" _EOF ## Build empty depend file that may get updated by $POST_PROTOTYPE_EDITS echo "Building depend file..." touch depend ## Build space file echo "Building space file..." if [ $DO_SMF -eq 1 ] then # XXX Is this necessary? If not, remove space line from mk-proto.awk. touch space else cat > space << _EOF # extra space required by start/stop links added by installf # in postinstall $TEST_DIR/etc/rc0.d/${SYSVINITSTOP}${SYSVINIT_NAME} 0 1 $TEST_DIR/etc/rc2.d/${SYSVINITSTART}${SYSVINIT_NAME} 0 1 _EOF [ "$RC1_D" = no ] || \ echo "$TEST_DIR/etc/rc1.d/${SYSVINITSTOP}${SYSVINIT_NAME} 0 1" >> space [ "$RCS_D" = yes ] && \ echo "$TEST_DIR/etc/rcS.d/${SYSVINITSTOP}${SYSVINIT_NAME} 0 1" >> space fi ## Build preinstall file echo "Building preinstall file..." cat > preinstall << _EOF #! ${SCRIPT_SHELL} # _EOF # local preinstall changes here [ -s "${PKG_PREINSTALL_LOCAL}" ] && . ${PKG_PREINSTALL_LOCAL} cat >> preinstall << _EOF # if [ "\${PRE_INS_STOP}" = "yes" ] then if [ $DO_SMF -eq 1 ] then svcadm disable $OPENSSH_FMRI else ${TEST_DIR}/etc/init.d/${SYSVINIT_NAME} stop fi fi exit 0 _EOF ## Build postinstall file echo "Building postinstall file..." cat > postinstall << _EOF #! ${SCRIPT_SHELL} # [ -f \${PKG_INSTALL_ROOT}${sysconfdir}/ssh_config ] || \\ cp -p \${PKG_INSTALL_ROOT}${sysconfdir}/ssh_config.default \\ \${PKG_INSTALL_ROOT}${sysconfdir}/ssh_config [ -f \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config ] || \\ cp -p \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config.default \\ \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config # make rc?.d dirs only if we are doing a test install [ -n "${TEST_DIR}" ] && [ $DO_SMF -ne 1 ] && { [ "$RCS_D" = yes ] && mkdir -p ${TEST_DIR}/etc/rcS.d mkdir -p ${TEST_DIR}/etc/rc0.d [ "$RC1_D" = no ] || mkdir -p ${TEST_DIR}/etc/rc1.d mkdir -p ${TEST_DIR}/etc/rc2.d } if [ $DO_SMF -eq 1 ] then # Delete the existing service, if it exists, then import the # new one. if svcs $OPENSSH_FMRI > /dev/null 2>&1 then svccfg delete -f $OPENSSH_FMRI fi # NOTE, The manifest disables sshd by default. svccfg import ${TEST_DIR}${SMF_MANIFEST_DIR}/${SYSVINIT_NAME}.xml else if [ "\${USE_SYM_LINKS}" = yes ] then [ "$RCS_D" = yes ] && \\ installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rcS.d/${SYSVINITSTOP}${SYSVINIT_NAME}=../init.d/${SYSVINIT_NAME} s installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rc0.d/${SYSVINITSTOP}${SYSVINIT_NAME}=../init.d/${SYSVINIT_NAME} s [ "$RC1_D" = no ] || \\ installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rc1.d/${SYSVINITSTOP}${SYSVINIT_NAME}=../init.d/${SYSVINIT_NAME} s installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rc2.d/${SYSVINITSTART}${SYSVINIT_NAME}=../init.d/${SYSVINIT_NAME} s else [ "$RCS_D" = yes ] && \\ installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rcS.d/${SYSVINITSTOP}${SYSVINIT_NAME}=\${PKG_INSTALL_ROOT}$TEST_DIR/etc/init.d/${SYSVINIT_NAME} l installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rc0.d/${SYSVINITSTOP}${SYSVINIT_NAME}=\${PKG_INSTALL_ROOT}$TEST_DIR/etc/init.d/${SYSVINIT_NAME} l [ "$RC1_D" = no ] || \\ installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rc1.d/${SYSVINITSTOP}${SYSVINIT_NAME}=\${PKG_INSTALL_ROOT}$TEST_DIR/etc/init.d/${SYSVINIT_NAME} l installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR/etc/rc2.d/${SYSVINITSTART}${SYSVINIT_NAME}=\${PKG_INSTALL_ROOT}$TEST_DIR/etc/init.d/${SYSVINIT_NAME} l fi fi # If piddir doesn't exist we add it. (Ie. --with-pid-dir=/var/opt/ssh) [ -d $piddir ] || installf ${PKGNAME} \${PKG_INSTALL_ROOT}$TEST_DIR$piddir d 0755 root sys _EOF # local postinstall changes here [ -s "${PKG_POSTINSTALL_LOCAL}" ] && . ${PKG_POSTINSTALL_LOCAL} cat >> postinstall << _EOF installf -f ${PKGNAME} # Use chroot to handle PKG_INSTALL_ROOT if [ ! -z "\${PKG_INSTALL_ROOT}" ] then chroot="chroot \${PKG_INSTALL_ROOT}" fi # If this is a test build, we will skip the groupadd/useradd/passwd commands if [ ! -z "${TEST_DIR}" ] then chroot=echo fi echo "PrivilegeSeparation user always required." if cut -f1 -d: \${PKG_INSTALL_ROOT}/etc/passwd | egrep '^'$SSH_PRIVSEP_USER'\$' >/dev/null then echo "PrivSep user $SSH_PRIVSEP_USER already exists." SSH_PRIVSEP_GROUP=\`grep "^$SSH_PRIVSEP_USER:" \${PKG_INSTALL_ROOT}/etc/passwd | awk -F: '{print \$4}'\` SSH_PRIVSEP_GROUP=\`grep ":\$SSH_PRIVSEP_GROUP:" \${PKG_INSTALL_ROOT}/etc/group | awk -F: '{print \$1}'\` else DO_PASSWD=yes fi [ -z "\$SSH_PRIVSEP_GROUP" ] && SSH_PRIVSEP_GROUP=$SSH_PRIVSEP_USER # group required? if cut -f1 -d: \${PKG_INSTALL_ROOT}/etc/group | egrep '^'\$SSH_PRIVSEP_GROUP'\$' >/dev/null then echo "PrivSep group \$SSH_PRIVSEP_GROUP already exists." else DO_GROUP=yes fi # create group if required [ "\$DO_GROUP" = yes ] && { # Use gid of 67 if possible if cut -f3 -d: \${PKG_INSTALL_ROOT}/etc/group | egrep '^'$SSHDGID'\$' >/dev/null then : else sshdgid="-g $SSHDGID" fi echo "Creating PrivSep group \$SSH_PRIVSEP_GROUP." \$chroot ${PATH_GROUPADD_PROG} \$sshdgid \$SSH_PRIVSEP_GROUP } # Create user if required [ "\$DO_PASSWD" = yes ] && { # Use uid of 67 if possible if cut -f3 -d: \${PKG_INSTALL_ROOT}/etc/passwd | egrep '^'$SSHDUID'\$' >/dev/null then : else sshduid="-u $SSHDUID" fi echo "Creating PrivSep user $SSH_PRIVSEP_USER." \$chroot ${PATH_USERADD_PROG} -c 'SSHD PrivSep User' -s /bin/false -g $SSH_PRIVSEP_USER \$sshduid $SSH_PRIVSEP_USER \$chroot ${PATH_PASSWD_PROG} -l $SSH_PRIVSEP_USER } if [ "\${POST_INS_START}" = "yes" ] then if [ $DO_SMF -eq 1 ] then svcadm enable $OPENSSH_FMRI else ${TEST_DIR}/etc/init.d/${SYSVINIT_NAME} start fi fi exit 0 _EOF ## Build preremove file echo "Building preremove file..." cat > preremove << _EOF #! ${SCRIPT_SHELL} # if [ $DO_SMF -eq 1 ] then svcadm disable $OPENSSH_FMRI else ${TEST_DIR}/etc/init.d/${SYSVINIT_NAME} stop fi _EOF # local preremove changes here [ -s "${PKG_PREREMOVE_LOCAL}" ] && . ${PKG_PREREMOVE_LOCAL} cat >> preremove << _EOF exit 0 _EOF ## Build postremove file echo "Building postremove file..." cat > postremove << _EOF #! ${SCRIPT_SHELL} # if [ $DO_SMF -eq 1 ] then if svcs $OPENSSH_FMRI > /dev/null 2>&1 then svccfg delete -f $OPENSSH_FMRI fi fi _EOF # local postremove changes here [ -s "${PKG_POSTREMOVE_LOCAL}" ] && . ${PKG_POSTREMOVE_LOCAL} cat >> postremove << _EOF exit 0 _EOF ## Build request file echo "Building request file..." cat > request << _EOF trap 'exit 3' 15 _EOF [ -x /usr/bin/ckyorn ] || cat >> request << _EOF ckyorn() { # for some strange reason OpenServer5 has no ckyorn # We build a striped down version here DEFAULT=n PROMPT="Yes or No [yes,no,?,quit]" HELP_PROMPT=" Enter y or yes if your answer is yes; n or no if your answer is no." USAGE="usage: ckyorn [options] where options may include: -d default -h help -p prompt " if [ \$# != 0 ] then while getopts d:p:h: c do case \$c in h) HELP_PROMPT="\$OPTARG" ;; d) DEFAULT=\$OPTARG ;; p) PROMPT=\$OPTARG ;; \\?) echo "\$USAGE" 1>&2 exit 1 ;; esac done shift \`expr \$OPTIND - 1\` fi while true do echo "\${PROMPT}\\c " 1>&2 read key [ -z "\$key" ] && key=\$DEFAULT case \$key in [n,N]|[n,N][o,O]|[y,Y]|[y,Y][e,E][s,S]) echo "\${key}\\c" exit 0 ;; \\?) echo \$HELP_PROMPT 1>&2 ;; q|quit) echo "q\\c" 1>&2 exit 3 ;; esac done } _EOF if [ $DO_SMF -eq 1 ] then # This could get hairy, as the running sshd may not be under SMF. # We'll assume an earlier version of OpenSSH started via SMF. cat >> request << _EOF PRE_INS_STOP=no POST_INS_START=no # determine if should restart the daemon if [ -s ${piddir}/sshd.pid ] && \\ /usr/bin/svcs -H $OPENSSH_FMRI 2>&1 | egrep "^online" > /dev/null 2>&1 then ans=\`ckyorn -d n \\ -p "Should the running sshd daemon be restarted? ${DEF_MSG}"\` || exit \$? case \$ans in [y,Y]*) PRE_INS_STOP=yes POST_INS_START=yes ;; esac else # determine if we should start sshd ans=\`ckyorn -d n \\ -p "Start the sshd daemon after installing this package? ${DEF_MSG}"\` || exit \$? case \$ans in [y,Y]*) POST_INS_START=yes ;; esac fi # make parameters available to installation service, # and so to any other packaging scripts cat >\$1 <> request << _EOF USE_SYM_LINKS=no PRE_INS_STOP=no POST_INS_START=no # Use symbolic links? ans=\`ckyorn -d n \\ -p "Do you want symbolic links for the start/stop scripts? ${DEF_MSG}"\` || exit \$? case \$ans in [y,Y]*) USE_SYM_LINKS=yes ;; esac # determine if should restart the daemon if [ -s ${piddir}/sshd.pid -a -f ${TEST_DIR}/etc/init.d/${SYSVINIT_NAME} ] then ans=\`ckyorn -d n \\ -p "Should the running sshd daemon be restarted? ${DEF_MSG}"\` || exit \$? case \$ans in [y,Y]*) PRE_INS_STOP=yes POST_INS_START=yes ;; esac else # determine if we should start sshd ans=\`ckyorn -d n \\ -p "Start the sshd daemon after installing this package? ${DEF_MSG}"\` || exit \$? case \$ans in [y,Y]*) POST_INS_START=yes ;; esac fi # make parameters available to installation service, # and so to any other packaging scripts cat >\$1 <> request << _EOF exit 0 _EOF ## Next Build our prototype echo "Building prototype file..." cat >mk-proto.awk << _EOF BEGIN { print "i pkginfo"; print "i depend"; \\ print "i preinstall"; print "i postinstall"; \\ print "i preremove"; print "i postremove"; \\ print "i request"; print "i space"; \\ split("$SYSTEM_DIR",sys_files); } { for (dir in sys_files) { if ( \$3 != sys_files[dir] ) { if ( \$1 == "s" ) { \$5=""; \$6=""; } else { \$5="root"; \$6="sys"; } } else { \$4="?"; \$5="?"; \$6="?"; break;} } } { print; } _EOF find . | egrep -v "prototype|pkginfo|mk-proto.awk" | sort | \ pkgproto $PROTO_ARGS | ${AWK} -f mk-proto.awk > prototype # /usr/local is a symlink on some systems [ "${USR_LOCAL_IS_SYMLINK}" = yes ] && { grep -v "^d none /usr/local ? ? ?$" prototype > prototype.new mv prototype.new prototype } ## Step back a directory and now build the package. cd .. # local prototype tweeks here [ -s "${POST_PROTOTYPE_EDITS}" ] && . ${POST_PROTOTYPE_EDITS} echo "Building package.." pkgmk -d ${FAKE_ROOT} -f $FAKE_ROOT/prototype -o echo | pkgtrans -os ${FAKE_ROOT} ${START}/$PKGNAME-$VERSION$REV-$UNAME_S-$ARCH.pkg ;; justpkg.sh) rm -fr ${FAKE_ROOT}/${PKGNAME} grep -v "^PSTAMP=" $FAKE_ROOT/pkginfo > $$tmp mv $$tmp $FAKE_ROOT/pkginfo cat >> $FAKE_ROOT/pkginfo << _EOF PSTAMP="${UNAME_S} ${OS_VER} ${ARCH} `date '+%d%b%Y %H:%M'`" _EOF pkgmk -d ${FAKE_ROOT} -f $FAKE_ROOT/prototype -o echo | pkgtrans -os ${FAKE_ROOT} ${START}/$PKGNAME-$VERSION$REV-$UNAME_S-$ARCH.pkg ;; esac [ "${REMOVE_FAKE_ROOT_WHEN_DONE}" = yes ] && rm -rf $FAKE_ROOT exit 0 openssh-10.0p1/PaxHeaders.10889/m4040755 001750 001750 0000000003614775415623 0013425xustar0030 atime=1744182234.580883002 openssh-10.0p1/m4004075500017500001750000000000001477541562300120035ustar00djmdjmopenssh-10.0p1/m4/PaxHeaders.10889/openssh.m4100644 001750 001750 0000000003614775415623 0015415xustar0030 atime=1744182234.581860772 openssh-10.0p1/m4/openssh.m4010064400017500001750000000152331477541562300140040ustar00djmdjmdnl OpenSSH-specific autoconf macros dnl dnl The test program that is used to try to trigger various compiler dnl behaviours. AC_DEFUN([OSSH_COMPILER_FLAG_TEST_PROGRAM], [AC_LANG_SOURCE([[ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } ]])] ) dnl OSSH_CHECK_CFLAG_COMPILE(check_flag[, define_flag]) dnl Check that $CC accepts a flag 'check_flag'. If it is supported append dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append dnl 'check_flag'. AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{ AC_MSG_CHECKING([if $CC supports compile flag $1]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR $1" _define_flag="$2" test "x$_define_flag" = "x" && _define_flag="$1" AC_COMPILE_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" else dnl If we are compiling natively, try running the program. AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ AC_MSG_RESULT([yes]) CFLAGS="$saved_CFLAGS $_define_flag" ], [ AC_MSG_RESULT([no, fails at run time]) CFLAGS="$saved_CFLAGS" ], [ AC_MSG_RESULT([yes]) CFLAGS="$saved_CFLAGS $_define_flag" ], ) fi], [ AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" ] ) }]) dnl OSSH_CHECK_CFLAG_LINK(check_flag[, define_flag]) dnl Check that $CC accepts a flag 'check_flag'. If it is supported append dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append dnl 'check_flag'. AC_DEFUN([OSSH_CHECK_CFLAG_LINK], [{ AC_MSG_CHECKING([if $CC supports compile flag $1 and linking succeeds]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR $1" _define_flag="$2" test "x$_define_flag" = "x" && _define_flag="$1" AC_LINK_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" else dnl If we are compiling natively, try running the program. AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ AC_MSG_RESULT([yes]) CFLAGS="$saved_CFLAGS $_define_flag" ], [ AC_MSG_RESULT([no, fails at run time]) CFLAGS="$saved_CFLAGS" ], [ AC_MSG_RESULT([yes]) CFLAGS="$saved_CFLAGS $_define_flag" ], ) fi], [ AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" ] ) }]) dnl OSSH_CHECK_LDFLAG_LINK(check_flag[, define_flag]) dnl Check that $LD accepts a flag 'check_flag'. If it is supported append dnl 'define_flag' to $LDFLAGS. If 'define_flag' is not specified, then append dnl 'check_flag'. AC_DEFUN([OSSH_CHECK_LDFLAG_LINK], [{ AC_MSG_CHECKING([if $LD supports link flag $1]) saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR $1" _define_flag="$2" test "x$_define_flag" = "x" && _define_flag="$1" AC_LINK_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then AC_MSG_RESULT([no]) LDFLAGS="$saved_LDFLAGS" else dnl If we are compiling natively, try running the program. AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ AC_MSG_RESULT([yes]) LDFLAGS="$saved_LDFLAGS $_define_flag" ], [ AC_MSG_RESULT([no, fails at run time]) LDFLAGS="$saved_LDFLAGS" ], [ AC_MSG_RESULT([yes]) LDFLAGS="$saved_LDFLAGS $_define_flag" ] ) fi ], [ AC_MSG_RESULT([no]) LDFLAGS="$saved_LDFLAGS" ] ) }]) dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol) dnl Does AC_EGREP_HEADER on 'header' for the string 'field' dnl If found, set 'symbol' to be defined. Cache the result. dnl TODO: This is not foolproof, better to compile and read from there AC_DEFUN([OSSH_CHECK_HEADER_FOR_FIELD], [ # look for field '$1' in header '$2' dnl This strips characters illegal to m4 from the header filename ossh_safe=`echo "$2" | sed 'y%./+-%__p_%'` dnl ossh_varname="ossh_cv_$ossh_safe""_has_"$1 AC_MSG_CHECKING(for $1 field in $2) AC_CACHE_VAL($ossh_varname, [ AC_EGREP_HEADER($1, $2, [ dnl eval "$ossh_varname=yes" dnl ], [ dnl eval "$ossh_varname=no" dnl ]) dnl ]) ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then AC_MSG_RESULT($ossh_result) if test "x$ossh_result" = "xyes"; then AC_DEFINE($3, 1, [Define if you have $1 in $2]) fi else AC_MSG_RESULT(no) fi ]) dnl Check for socklen_t: historically on BSD it is an int, and in dnl POSIX 1g it is a type of its own, but some platforms use different dnl types for the argument to getsockopt, getpeername, etc. So we dnl have to test to find something that will work. AC_DEFUN([TYPE_SOCKLEN_T], [ AC_CHECK_TYPE([socklen_t], ,[ AC_MSG_CHECKING([for socklen_t equivalent]) AC_CACHE_VAL([curl_cv_socklen_t_equiv], [ # Systems have either "struct sockaddr *" or # "void *" as the second argument to getpeername curl_cv_socklen_t_equiv= for arg2 in "struct sockaddr" void; do for t in int size_t unsigned long "unsigned long"; do AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ #include #include int getpeername (int, $arg2 *, $t *); ]], [[ $t len; getpeername(0,0,&len); ]]) ],[ curl_cv_socklen_t_equiv="$t" break ]) done done if test "x$curl_cv_socklen_t_equiv" = x; then AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) fi ]) AC_MSG_RESULT($curl_cv_socklen_t_equiv) AC_DEFINE_UNQUOTED(socklen_t, $curl_cv_socklen_t_equiv, [type to use in place of socklen_t if not defined])], [#include #include ]) ]) openssh-10.0p1/PaxHeaders.10889/canohost.c100644 001750 001750 0000000003614775415623 0015136xustar0030 atime=1744182234.503735116 openssh-10.0p1/canohost.c010064400017500001750000000114001477541562300135150ustar00djmdjm/* $OpenBSD: canohost.c,v 1.77 2023/03/31 04:42:29 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for returning the canonical host name of the remote site. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "packet.h" #include "log.h" #include "canohost.h" #include "misc.h" void ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) { struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr; struct sockaddr_in *a4 = (struct sockaddr_in *)addr; struct in_addr inaddr; u_int16_t port; if (addr->ss_family != AF_INET6 || !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) return; debug3("Normalising mapped IPv4 in IPv6 address"); memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr)); port = a6->sin6_port; memset(a4, 0, sizeof(*a4)); a4->sin_family = AF_INET; *len = sizeof(*a4); memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr)); a4->sin_port = port; } /* * Returns the local/remote IP-address/hostname of socket as a string. * The returned string must be freed. */ static char * get_socket_address(int sock, int remote, int flags) { struct sockaddr_storage addr; socklen_t addrlen; char ntop[NI_MAXHOST]; int r; if (sock < 0) return NULL; /* Get IP address of client. */ addrlen = sizeof(addr); memset(&addr, 0, sizeof(addr)); if (remote) { if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) != 0) return NULL; } else { if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0) return NULL; } /* Work around Linux IPv6 weirdness */ if (addr.ss_family == AF_INET6) { addrlen = sizeof(struct sockaddr_in6); ipv64_normalise_mapped(&addr, &addrlen); } switch (addr.ss_family) { case AF_INET: case AF_INET6: /* Get the address in ascii. */ if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop), NULL, 0, flags)) != 0) { error_f("getnameinfo %d failed: %s", flags, ssh_gai_strerror(r)); return NULL; } return xstrdup(ntop); case AF_UNIX: /* Get the Unix domain socket path. */ return xstrdup(((struct sockaddr_un *)&addr)->sun_path); default: /* We can't look up remote Unix domain sockets. */ return NULL; } } char * get_peer_ipaddr(int sock) { char *p; if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL) return p; return xstrdup("UNKNOWN"); } char * get_local_ipaddr(int sock) { char *p; if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL) return p; return xstrdup("UNKNOWN"); } char * get_local_name(int fd) { char *host, myname[NI_MAXHOST]; /* Assume we were passed a socket */ if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL) return host; /* Handle the case where we were passed a pipe */ if (gethostname(myname, sizeof(myname)) == -1) { verbose_f("gethostname: %s", strerror(errno)); host = xstrdup("UNKNOWN"); } else { host = xstrdup(myname); } return host; } /* Returns the local/remote port for the socket. */ static int get_sock_port(int sock, int local) { struct sockaddr_storage from; socklen_t fromlen; char strport[NI_MAXSERV]; int r; if (sock < 0) return -1; /* Get IP address of client. */ fromlen = sizeof(from); memset(&from, 0, sizeof(from)); if (local) { if (getsockname(sock, (struct sockaddr *)&from, &fromlen) == -1) { error("getsockname failed: %.100s", strerror(errno)); return 0; } } else { if (getpeername(sock, (struct sockaddr *)&from, &fromlen) == -1) { debug("getpeername failed: %.100s", strerror(errno)); return -1; } } /* Work around Linux IPv6 weirdness */ if (from.ss_family == AF_INET6) fromlen = sizeof(struct sockaddr_in6); /* Non-inet sockets don't have a port number. */ if (from.ss_family != AF_INET && from.ss_family != AF_INET6) return 0; /* Return port number. */ if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, strport, sizeof(strport), NI_NUMERICSERV)) != 0) fatal_f("getnameinfo NI_NUMERICSERV failed: %s", ssh_gai_strerror(r)); return atoi(strport); } int get_peer_port(int sock) { return get_sock_port(sock, 0); } int get_local_port(int sock) { return get_sock_port(sock, 1); } openssh-10.0p1/PaxHeaders.10889/canohost.h100644 001750 001750 0000000003614775415623 0015143xustar0030 atime=1744182234.504712234 openssh-10.0p1/canohost.h010064400017500001750000000015121477541562300135250ustar00djmdjm/* $OpenBSD: canohost.h,v 1.12 2016/03/07 19:02:43 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef _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); #endif /* _CANOHOST_H */ void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *); openssh-10.0p1/PaxHeaders.10889/chacha.c100644 001750 001750 0000000003614775415623 0014527xustar0030 atime=1744182234.504712234 openssh-10.0p1/chacha.c010064400017500001750000000124421477541562300131150ustar00djmdjm/* $OpenBSD: chacha.c,v 1.2 2023/07/17 05:26:38 djm Exp $ */ /* chacha-merged.c version 20080118 D. J. Bernstein Public domain. */ #include "includes.h" #include "chacha.h" typedef unsigned char u8; typedef unsigned int u32; typedef struct chacha_ctx chacha_ctx; #define U8C(v) (v##U) #define U32C(v) (v##U) #define U8V(v) ((u8)(v) & U8C(0xFF)) #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) #define ROTL32(v, n) \ (U32V((v) << (n)) | ((v) >> (32 - (n)))) #define U8TO32_LITTLE(p) \ (((u32)((p)[0]) ) | \ ((u32)((p)[1]) << 8) | \ ((u32)((p)[2]) << 16) | \ ((u32)((p)[3]) << 24)) #define U32TO8_LITTLE(p, v) \ do { \ (p)[0] = U8V((v) ); \ (p)[1] = U8V((v) >> 8); \ (p)[2] = U8V((v) >> 16); \ (p)[3] = U8V((v) >> 24); \ } while (0) #define ROTATE(v,c) (ROTL32(v,c)) #define XOR(v,w) ((v) ^ (w)) #define PLUS(v,w) (U32V((v) + (w))) #define PLUSONE(v) (PLUS((v),1)) #define QUARTERROUND(a,b,c,d) \ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); static const char sigma[16] = "expand 32-byte k"; static const char tau[16] = "expand 16-byte k"; void chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) { const char *constants; x->input[4] = U8TO32_LITTLE(k + 0); x->input[5] = U8TO32_LITTLE(k + 4); x->input[6] = U8TO32_LITTLE(k + 8); x->input[7] = U8TO32_LITTLE(k + 12); if (kbits == 256) { /* recommended */ k += 16; constants = sigma; } else { /* kbits == 128 */ constants = tau; } x->input[8] = U8TO32_LITTLE(k + 0); x->input[9] = U8TO32_LITTLE(k + 4); x->input[10] = U8TO32_LITTLE(k + 8); x->input[11] = U8TO32_LITTLE(k + 12); x->input[0] = U8TO32_LITTLE(constants + 0); x->input[1] = U8TO32_LITTLE(constants + 4); x->input[2] = U8TO32_LITTLE(constants + 8); x->input[3] = U8TO32_LITTLE(constants + 12); } void chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) { x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); x->input[14] = U8TO32_LITTLE(iv + 0); x->input[15] = U8TO32_LITTLE(iv + 4); } void chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) { u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; u8 *ctarget = NULL; u8 tmp[64]; u_int i; if (!bytes) return; j0 = x->input[0]; j1 = x->input[1]; j2 = x->input[2]; j3 = x->input[3]; j4 = x->input[4]; j5 = x->input[5]; j6 = x->input[6]; j7 = x->input[7]; j8 = x->input[8]; j9 = x->input[9]; j10 = x->input[10]; j11 = x->input[11]; j12 = x->input[12]; j13 = x->input[13]; j14 = x->input[14]; j15 = x->input[15]; for (;;) { if (bytes < 64) { for (i = 0;i < bytes;++i) tmp[i] = m[i]; m = tmp; ctarget = c; c = tmp; } x0 = j0; x1 = j1; x2 = j2; x3 = j3; x4 = j4; x5 = j5; x6 = j6; x7 = j7; x8 = j8; x9 = j9; x10 = j10; x11 = j11; x12 = j12; x13 = j13; x14 = j14; x15 = j15; for (i = 20;i > 0;i -= 2) { QUARTERROUND( x0, x4, x8,x12) QUARTERROUND( x1, x5, x9,x13) QUARTERROUND( x2, x6,x10,x14) QUARTERROUND( x3, x7,x11,x15) QUARTERROUND( x0, x5,x10,x15) QUARTERROUND( x1, x6,x11,x12) QUARTERROUND( x2, x7, x8,x13) QUARTERROUND( x3, x4, x9,x14) } x0 = PLUS(x0,j0); x1 = PLUS(x1,j1); x2 = PLUS(x2,j2); x3 = PLUS(x3,j3); x4 = PLUS(x4,j4); x5 = PLUS(x5,j5); x6 = PLUS(x6,j6); x7 = PLUS(x7,j7); x8 = PLUS(x8,j8); x9 = PLUS(x9,j9); x10 = PLUS(x10,j10); x11 = PLUS(x11,j11); x12 = PLUS(x12,j12); x13 = PLUS(x13,j13); x14 = PLUS(x14,j14); x15 = PLUS(x15,j15); x0 = XOR(x0,U8TO32_LITTLE(m + 0)); x1 = XOR(x1,U8TO32_LITTLE(m + 4)); x2 = XOR(x2,U8TO32_LITTLE(m + 8)); x3 = XOR(x3,U8TO32_LITTLE(m + 12)); x4 = XOR(x4,U8TO32_LITTLE(m + 16)); x5 = XOR(x5,U8TO32_LITTLE(m + 20)); x6 = XOR(x6,U8TO32_LITTLE(m + 24)); x7 = XOR(x7,U8TO32_LITTLE(m + 28)); x8 = XOR(x8,U8TO32_LITTLE(m + 32)); x9 = XOR(x9,U8TO32_LITTLE(m + 36)); x10 = XOR(x10,U8TO32_LITTLE(m + 40)); x11 = XOR(x11,U8TO32_LITTLE(m + 44)); x12 = XOR(x12,U8TO32_LITTLE(m + 48)); x13 = XOR(x13,U8TO32_LITTLE(m + 52)); x14 = XOR(x14,U8TO32_LITTLE(m + 56)); x15 = XOR(x15,U8TO32_LITTLE(m + 60)); j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); /* stopping at 2^70 bytes per nonce is user's responsibility */ } U32TO8_LITTLE(c + 0,x0); U32TO8_LITTLE(c + 4,x1); U32TO8_LITTLE(c + 8,x2); U32TO8_LITTLE(c + 12,x3); U32TO8_LITTLE(c + 16,x4); U32TO8_LITTLE(c + 20,x5); U32TO8_LITTLE(c + 24,x6); U32TO8_LITTLE(c + 28,x7); U32TO8_LITTLE(c + 32,x8); U32TO8_LITTLE(c + 36,x9); U32TO8_LITTLE(c + 40,x10); U32TO8_LITTLE(c + 44,x11); U32TO8_LITTLE(c + 48,x12); U32TO8_LITTLE(c + 52,x13); U32TO8_LITTLE(c + 56,x14); U32TO8_LITTLE(c + 60,x15); if (bytes <= 64) { if (bytes < 64) { for (i = 0;i < bytes;++i) ctarget[i] = c[i]; } x->input[12] = j12; x->input[13] = j13; return; } bytes -= 64; c += 64; m += 64; } } openssh-10.0p1/PaxHeaders.10889/chacha.h100644 001750 001750 0000000003614775415623 0014534xustar0030 atime=1744182234.504712234 openssh-10.0p1/chacha.h010064400017500001750000000017421477541562300131230ustar00djmdjm/* $OpenBSD: chacha.h,v 1.5 2021/04/03 05:54:14 djm Exp $ */ /* chacha-merged.c version 20080118 D. J. Bernstein Public domain. */ #ifndef CHACHA_H #define CHACHA_H #include #include struct chacha_ctx { u_int input[16]; }; #define CHACHA_MINKEYLEN 16 #define CHACHA_NONCELEN 8 #define CHACHA_CTRLEN 8 #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) #define CHACHA_BLOCKLEN 64 void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits) __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))); void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr) __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN))) __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN))); void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m, u_char *c, u_int bytes) __attribute__((__bounded__(__buffer__, 2, 4))) __attribute__((__bounded__(__buffer__, 3, 4))); #endif /* CHACHA_H */ openssh-10.0p1/PaxHeaders.10889/channels.c100644 001750 001750 0000000003614775415623 0015113xustar0030 atime=1744182234.525218873 openssh-10.0p1/channels.c010064400017500001750000004446241477541562300135140ustar00djmdjm/* $OpenBSD: channels.c,v 1.442 2024/12/05 06:49:26 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * This file contains functions for generic socket connection forwarding. * There is also code for initiating connection forwarding for X11 connections, * arbitrary tcp/ip connections, and the authentication agent connection. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 support added by Markus Friedl. * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 1999 Dug Song. All rights reserved. * Copyright (c) 1999 Theo de Raadt. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #ifdef HAVE_POLL_H #include #endif #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "ssherr.h" #include "sshbuf.h" #include "packet.h" #include "log.h" #include "misc.h" #include "channels.h" #include "compat.h" #include "canohost.h" #include "sshkey.h" #include "authfd.h" #include "pathnames.h" #include "match.h" /* XXX remove once we're satisfied there's no lurking bugs */ /* #define DEBUG_CHANNEL_POLL 1 */ /* -- agent forwarding */ #define NUM_SOCKS 10 /* -- X11 forwarding */ /* X11 port for display :0 */ #define X11_BASE_PORT 6000 /* Maximum number of fake X11 displays to try. */ #define MAX_DISPLAYS 1000 /* Per-channel callback for pre/post IO actions */ typedef void chan_fn(struct ssh *, Channel *c); /* * Data structure for storing which hosts are permitted for forward requests. * The local sides of any remote forwards are stored in this array to prevent * a corrupt remote server from accessing arbitrary TCP/IP ports on our local * network (which might be behind a firewall). */ /* XXX: streamlocal wants a path instead of host:port */ /* Overload host_to_connect; we could just make this match Forward */ /* XXX - can we use listen_host instead of listen_path? */ struct permission { char *host_to_connect; /* Connect to 'host'. */ int port_to_connect; /* Connect to 'port'. */ char *listen_host; /* Remote side should listen address. */ char *listen_path; /* Remote side should listen path. */ int listen_port; /* Remote side should listen port. */ Channel *downstream; /* Downstream mux*/ }; /* * Stores the forwarding permission state for a single direction (local or * remote). */ struct permission_set { /* * List of all local permitted host/port pairs to allow for the * user. */ u_int num_permitted_user; struct permission *permitted_user; /* * List of all permitted host/port pairs to allow for the admin. */ u_int num_permitted_admin; struct permission *permitted_admin; /* * If this is true, all opens/listens are permitted. This is the * case on the server on which we have to trust the client anyway, * and the user could do anything after logging in. */ int all_permitted; }; /* Used to record timeouts per channel type */ struct ssh_channel_timeout { char *type_pattern; int timeout_secs; }; /* Master structure for channels state */ struct ssh_channels { /* * Pointer to an array containing all allocated channels. The array * is dynamically extended as needed. */ Channel **channels; /* * Size of the channel array. All slots of the array must always be * initialized (at least the type field); unused slots set to NULL */ u_int channels_alloc; /* * 'channel_pre*' are called just before IO to add any bits * relevant to channels in the c->io_want bitmasks. * * 'channel_post*': perform any appropriate operations for * channels which have c->io_ready events pending. */ chan_fn **channel_pre; chan_fn **channel_post; /* -- tcp forwarding */ struct permission_set local_perms; struct permission_set remote_perms; /* -- X11 forwarding */ /* Saved X11 local (client) display. */ char *x11_saved_display; /* Saved X11 authentication protocol name. */ char *x11_saved_proto; /* Saved X11 authentication data. This is the real data. */ char *x11_saved_data; u_int x11_saved_data_len; /* Deadline after which all X11 connections are refused */ time_t x11_refuse_time; /* * Fake X11 authentication data. This is what the server will be * sending us; we should replace any occurrences of this by the * real data. */ u_char *x11_fake_data; u_int x11_fake_data_len; /* AF_UNSPEC or AF_INET or AF_INET6 */ int IPv4or6; /* Channel timeouts by type */ struct ssh_channel_timeout *timeouts; size_t ntimeouts; /* Global timeout for all OPEN channels */ int global_deadline; time_t lastused; }; /* helper */ static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype); static const char *channel_rfwd_bind_host(const char *listen_host); /* non-blocking connect helpers */ static int connect_next(struct channel_connect *); static void channel_connect_ctx_free(struct channel_connect *); static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *); static int rdynamic_connect_finish(struct ssh *, Channel *); /* Setup helper */ static void channel_handler_init(struct ssh_channels *sc); /* -- channel core */ void channel_init_channels(struct ssh *ssh) { struct ssh_channels *sc; if ((sc = calloc(1, sizeof(*sc))) == NULL) fatal_f("allocation failed"); sc->channels_alloc = 10; sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); sc->IPv4or6 = AF_UNSPEC; channel_handler_init(sc); ssh->chanctxt = sc; } Channel * channel_by_id(struct ssh *ssh, int id) { Channel *c; if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) { logit_f("%d: bad id", id); return NULL; } c = ssh->chanctxt->channels[id]; if (c == NULL) { logit_f("%d: bad id: channel free", id); return NULL; } return c; } Channel * channel_by_remote_id(struct ssh *ssh, u_int remote_id) { Channel *c; u_int i; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c != NULL && c->have_remote_id && c->remote_id == remote_id) return c; } return NULL; } /* * Returns the channel if it is allowed to receive protocol messages. * Private channels, like listening sockets, may not receive messages. */ Channel * channel_lookup(struct ssh *ssh, int id) { Channel *c; if ((c = channel_by_id(ssh, id)) == NULL) return NULL; switch (c->type) { case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_MUX_PROXY: return c; } logit("Non-public channel %d, type %d.", id, c->type); return NULL; } /* * Add a timeout for open channels whose c->ctype (or c->xctype if it is set) * match type_pattern. */ void channel_add_timeout(struct ssh *ssh, const char *type_pattern, int timeout_secs) { struct ssh_channels *sc = ssh->chanctxt; if (strcmp(type_pattern, "global") == 0) { debug2_f("global channel timeout %d seconds", timeout_secs); sc->global_deadline = timeout_secs; return; } debug2_f("channel type \"%s\" timeout %d seconds", type_pattern, timeout_secs); sc->timeouts = xrecallocarray(sc->timeouts, sc->ntimeouts, sc->ntimeouts + 1, sizeof(*sc->timeouts)); sc->timeouts[sc->ntimeouts].type_pattern = xstrdup(type_pattern); sc->timeouts[sc->ntimeouts].timeout_secs = timeout_secs; sc->ntimeouts++; } /* Clears all previously-added channel timeouts */ void channel_clear_timeouts(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; size_t i; debug3_f("clearing"); for (i = 0; i < sc->ntimeouts; i++) free(sc->timeouts[i].type_pattern); free(sc->timeouts); sc->timeouts = NULL; sc->ntimeouts = 0; } static int lookup_timeout(struct ssh *ssh, const char *type) { struct ssh_channels *sc = ssh->chanctxt; size_t i; for (i = 0; i < sc->ntimeouts; i++) { if (match_pattern(type, sc->timeouts[i].type_pattern)) return sc->timeouts[i].timeout_secs; } return 0; } /* * Sets "extended type" of a channel; used by session layer to add additional * information about channel types (e.g. shell, login, subsystem) that can then * be used to select timeouts. * Will reset c->inactive_deadline as a side-effect. */ void channel_set_xtype(struct ssh *ssh, int id, const char *xctype) { Channel *c; if ((c = channel_by_id(ssh, id)) == NULL) fatal_f("missing channel %d", id); if (c->xctype != NULL) free(c->xctype); c->xctype = xstrdup(xctype); /* Type has changed, so look up inactivity deadline again */ c->inactive_deadline = lookup_timeout(ssh, c->xctype); debug2_f("labeled channel %d as %s (inactive timeout %u)", id, xctype, c->inactive_deadline); } /* * update "last used" time on a channel. * NB. nothing else should update lastused except to clear it. */ static void channel_set_used_time(struct ssh *ssh, Channel *c) { ssh->chanctxt->lastused = monotime(); if (c != NULL) c->lastused = ssh->chanctxt->lastused; } /* * Get the time at which a channel is due to time out for inactivity. * Returns 0 if the channel is not due to time out ever. */ static time_t channel_get_expiry(struct ssh *ssh, Channel *c) { struct ssh_channels *sc = ssh->chanctxt; time_t expiry = 0, channel_expiry; if (sc->lastused != 0 && sc->global_deadline != 0) expiry = sc->lastused + sc->global_deadline; if (c->lastused != 0 && c->inactive_deadline != 0) { channel_expiry = c->lastused + c->inactive_deadline; if (expiry == 0 || channel_expiry < expiry) expiry = channel_expiry; } return expiry; } /* * Register filedescriptors for a channel, used when allocating a channel or * when the channel consumer/producer is ready, e.g. shell exec'd */ static void channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, int extusage, int nonblock, int is_tty) { int val; if (rfd != -1) (void)fcntl(rfd, F_SETFD, FD_CLOEXEC); if (wfd != -1 && wfd != rfd) (void)fcntl(wfd, F_SETFD, FD_CLOEXEC); if (efd != -1 && efd != rfd && efd != wfd) (void)fcntl(efd, F_SETFD, FD_CLOEXEC); c->rfd = rfd; c->wfd = wfd; c->sock = (rfd == wfd) ? rfd : -1; c->efd = efd; c->extended_usage = extusage; if ((c->isatty = is_tty) != 0) debug2("channel %d: rfd %d isatty", c->self, c->rfd); #ifdef _AIX /* XXX: Later AIX versions can't push as much data to tty */ c->wfd_isatty = is_tty || isatty(c->wfd); #endif /* enable nonblocking mode */ c->restore_block = 0; if (nonblock == CHANNEL_NONBLOCK_STDIO) { /* * Special handling for stdio file descriptors: do not set * non-blocking mode if they are TTYs. Otherwise prepare to * restore their blocking state on exit to avoid interfering * with other programs that follow. */ if (rfd != -1 && !isatty(rfd) && (val = fcntl(rfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { c->restore_flags[0] = val; c->restore_block |= CHANNEL_RESTORE_RFD; set_nonblock(rfd); } if (wfd != -1 && !isatty(wfd) && (val = fcntl(wfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { c->restore_flags[1] = val; c->restore_block |= CHANNEL_RESTORE_WFD; set_nonblock(wfd); } if (efd != -1 && !isatty(efd) && (val = fcntl(efd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { c->restore_flags[2] = val; c->restore_block |= CHANNEL_RESTORE_EFD; set_nonblock(efd); } } else if (nonblock) { if (rfd != -1) set_nonblock(rfd); if (wfd != -1) set_nonblock(wfd); if (efd != -1) set_nonblock(efd); } /* channel might be entering a larval state, so reset global timeout */ channel_set_used_time(ssh, NULL); } /* * Allocate a new channel object and set its type and socket. */ Channel * channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, u_int window, u_int maxpack, int extusage, const char *remote_name, int nonblock) { struct ssh_channels *sc = ssh->chanctxt; u_int i, found = 0; Channel *c; int r; /* Try to find a free slot where to put the new channel. */ for (i = 0; i < sc->channels_alloc; i++) { if (sc->channels[i] == NULL) { /* Found a free slot. */ found = i; break; } } if (i >= sc->channels_alloc) { /* * There are no free slots. Take last+1 slot and expand * the array. */ found = sc->channels_alloc; if (sc->channels_alloc > CHANNELS_MAX_CHANNELS) fatal_f("internal error: channels_alloc %d too big", sc->channels_alloc); sc->channels = xrecallocarray(sc->channels, sc->channels_alloc, sc->channels_alloc + 10, sizeof(*sc->channels)); sc->channels_alloc += 10; debug2("channel: expanding %d", sc->channels_alloc); } /* Initialize and return new channel. */ c = sc->channels[found] = xcalloc(1, sizeof(Channel)); if ((c->input = sshbuf_new()) == NULL || (c->output = sshbuf_new()) == NULL || (c->extended = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_set_max_size(c->input, CHAN_INPUT_MAX)) != 0) fatal_fr(r, "sshbuf_set_max_size"); c->ostate = CHAN_OUTPUT_OPEN; c->istate = CHAN_INPUT_OPEN; channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0); c->self = found; c->type = type; c->ctype = ctype; c->local_window = window; c->local_window_max = window; c->local_maxpacket = maxpack; c->remote_name = xstrdup(remote_name); c->ctl_chan = -1; c->delayed = 1; /* prevent call to channel_post handler */ c->inactive_deadline = lookup_timeout(ssh, c->ctype); TAILQ_INIT(&c->status_confirms); debug("channel %d: new %s [%s] (inactive timeout: %u)", found, c->ctype, remote_name, c->inactive_deadline); return c; } int channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) { int ret, fd = *fdp; if (fd == -1) return 0; /* restore blocking */ if (*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) (void)fcntl(*fdp, F_SETFL, c->restore_flags[0]); else if (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) (void)fcntl(*fdp, F_SETFL, c->restore_flags[1]); else if (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0) (void)fcntl(*fdp, F_SETFL, c->restore_flags[2]); if (*fdp == c->rfd) { c->io_want &= ~SSH_CHAN_IO_RFD; c->io_ready &= ~SSH_CHAN_IO_RFD; c->rfd = -1; c->pfds[0] = -1; } if (*fdp == c->wfd) { c->io_want &= ~SSH_CHAN_IO_WFD; c->io_ready &= ~SSH_CHAN_IO_WFD; c->wfd = -1; c->pfds[1] = -1; } if (*fdp == c->efd) { c->io_want &= ~SSH_CHAN_IO_EFD; c->io_ready &= ~SSH_CHAN_IO_EFD; c->efd = -1; c->pfds[2] = -1; } if (*fdp == c->sock) { c->io_want &= ~SSH_CHAN_IO_SOCK; c->io_ready &= ~SSH_CHAN_IO_SOCK; c->sock = -1; c->pfds[3] = -1; } ret = close(fd); *fdp = -1; /* probably redundant */ return ret; } /* Close all channel fd/socket. */ static void channel_close_fds(struct ssh *ssh, Channel *c) { int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; channel_close_fd(ssh, c, &c->sock); if (rfd != sock) channel_close_fd(ssh, c, &c->rfd); if (wfd != sock && wfd != rfd) channel_close_fd(ssh, c, &c->wfd); if (efd != sock && efd != rfd && efd != wfd) channel_close_fd(ssh, c, &c->efd); } static void fwd_perm_clear(struct permission *perm) { free(perm->host_to_connect); free(perm->listen_host); free(perm->listen_path); memset(perm, 0, sizeof(*perm)); } /* Returns an printable name for the specified forwarding permission list */ static const char * fwd_ident(int who, int where) { if (who == FORWARD_ADM) { if (where == FORWARD_LOCAL) return "admin local"; else if (where == FORWARD_REMOTE) return "admin remote"; } else if (who == FORWARD_USER) { if (where == FORWARD_LOCAL) return "user local"; else if (where == FORWARD_REMOTE) return "user remote"; } fatal("Unknown forward permission list %d/%d", who, where); } /* Returns the forwarding permission list for the specified direction */ static struct permission_set * permission_set_get(struct ssh *ssh, int where) { struct ssh_channels *sc = ssh->chanctxt; switch (where) { case FORWARD_LOCAL: return &sc->local_perms; break; case FORWARD_REMOTE: return &sc->remote_perms; break; default: fatal_f("invalid forwarding direction %d", where); } } /* Returns pointers to the specified forwarding list and its element count */ static void permission_set_get_array(struct ssh *ssh, int who, int where, struct permission ***permpp, u_int **npermpp) { struct permission_set *pset = permission_set_get(ssh, where); switch (who) { case FORWARD_USER: *permpp = &pset->permitted_user; *npermpp = &pset->num_permitted_user; break; case FORWARD_ADM: *permpp = &pset->permitted_admin; *npermpp = &pset->num_permitted_admin; break; default: fatal_f("invalid forwarding client %d", who); } } /* Adds an entry to the specified forwarding list */ static int permission_set_add(struct ssh *ssh, int who, int where, const char *host_to_connect, int port_to_connect, const char *listen_host, const char *listen_path, int listen_port, Channel *downstream) { struct permission **permp; u_int n, *npermp; permission_set_get_array(ssh, who, where, &permp, &npermp); if (*npermp >= INT_MAX) fatal_f("%s overflow", fwd_ident(who, where)); *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp)); n = (*npermp)++; #define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s)) (*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect); (*permp)[n].port_to_connect = port_to_connect; (*permp)[n].listen_host = MAYBE_DUP(listen_host); (*permp)[n].listen_path = MAYBE_DUP(listen_path); (*permp)[n].listen_port = listen_port; (*permp)[n].downstream = downstream; #undef MAYBE_DUP return (int)n; } static void mux_remove_remote_forwardings(struct ssh *ssh, Channel *c) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; struct permission *perm; int r; u_int i; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (perm->downstream != c) continue; /* cancel on the server, since mux client is gone */ debug("channel %d: cleanup remote forward for %s:%u", c->self, perm->listen_host, perm->listen_port); if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(perm->listen_host))) != 0 || (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 || (r = sshpkt_send(ssh)) != 0) { fatal_fr(r, "channel %i", c->self); } fwd_perm_clear(perm); /* unregister */ } } /* Free the channel and close its fd/socket. */ void channel_free(struct ssh *ssh, Channel *c) { struct ssh_channels *sc = ssh->chanctxt; char *s; u_int i, n; Channel *other; struct channel_confirm *cc; for (n = 0, i = 0; i < sc->channels_alloc; i++) { if ((other = sc->channels[i]) == NULL) continue; n++; /* detach from mux client and prepare for closing */ if (c->type == SSH_CHANNEL_MUX_CLIENT && other->type == SSH_CHANNEL_MUX_PROXY && other->mux_ctx == c) { other->mux_ctx = NULL; other->type = SSH_CHANNEL_OPEN; other->istate = CHAN_INPUT_CLOSED; other->ostate = CHAN_OUTPUT_CLOSED; } } debug("channel %d: free: %s, nchannels %u", c->self, c->remote_name ? c->remote_name : "???", n); if (c->type == SSH_CHANNEL_MUX_CLIENT) { mux_remove_remote_forwardings(ssh, c); free(c->mux_ctx); c->mux_ctx = NULL; } else if (c->type == SSH_CHANNEL_MUX_LISTENER) { free(c->mux_ctx); c->mux_ctx = NULL; } if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) { s = channel_open_message(ssh); debug3("channel %d: status: %s", c->self, s); free(s); } channel_close_fds(ssh, c); sshbuf_free(c->input); sshbuf_free(c->output); sshbuf_free(c->extended); c->input = c->output = c->extended = NULL; free(c->remote_name); c->remote_name = NULL; free(c->path); c->path = NULL; free(c->listening_addr); c->listening_addr = NULL; free(c->xctype); c->xctype = NULL; while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { if (cc->abandon_cb != NULL) cc->abandon_cb(ssh, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); freezero(cc, sizeof(*cc)); } if (c->filter_cleanup != NULL && c->filter_ctx != NULL) c->filter_cleanup(ssh, c->self, c->filter_ctx); sc->channels[c->self] = NULL; freezero(c, sizeof(*c)); } void channel_free_all(struct ssh *ssh) { u_int i; struct ssh_channels *sc = ssh->chanctxt; for (i = 0; i < sc->channels_alloc; i++) if (sc->channels[i] != NULL) channel_free(ssh, sc->channels[i]); free(sc->channels); sc->channels = NULL; sc->channels_alloc = 0; free(sc->x11_saved_display); sc->x11_saved_display = NULL; free(sc->x11_saved_proto); sc->x11_saved_proto = NULL; free(sc->x11_saved_data); sc->x11_saved_data = NULL; sc->x11_saved_data_len = 0; free(sc->x11_fake_data); sc->x11_fake_data = NULL; sc->x11_fake_data_len = 0; } /* * Closes the sockets/fds of all channels. This is used to close extra file * descriptors after a fork. */ void channel_close_all(struct ssh *ssh) { u_int i; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) if (ssh->chanctxt->channels[i] != NULL) channel_close_fds(ssh, ssh->chanctxt->channels[i]); } /* * Stop listening to channels. */ void channel_stop_listening(struct ssh *ssh) { u_int i; Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c != NULL) { switch (c->type) { case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: channel_close_fd(ssh, c, &c->sock); channel_free(ssh, c); break; } } } } /* * Returns true if no channel has too much buffered data, and false if one or * more channel is overfull. */ int channel_not_very_much_buffered_data(struct ssh *ssh) { u_int i; u_int maxsize = ssh_packet_get_maxsize(ssh); Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_OPEN) continue; if (sshbuf_len(c->output) > maxsize) { debug2("channel %d: big output buffer %zu > %u", c->self, sshbuf_len(c->output), maxsize); return 0; } } return 1; } /* Returns true if any channel is still open. */ int channel_still_open(struct ssh *ssh) { u_int i; Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL) continue; switch (c->type) { case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_MUX_LISTENER: case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: continue; case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_PROXY: return 1; default: fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } return 0; } /* Returns true if a channel with a TTY is open. */ int channel_tty_open(struct ssh *ssh) { u_int i; Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_OPEN) continue; if (c->client_tty) return 1; } return 0; } /* Returns the id of an open channel suitable for keepaliving */ int channel_find_open(struct ssh *ssh) { u_int i; Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL || !c->have_remote_id) continue; switch (c->type) { case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_MUX_LISTENER: case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_PROXY: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: return i; default: fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } return -1; } /* Returns the state of the channel's extended usage flag */ const char * channel_format_extended_usage(const Channel *c) { if (c->efd == -1) return "closed"; switch (c->extended_usage) { case CHAN_EXTENDED_WRITE: return "write"; case CHAN_EXTENDED_READ: return "read"; case CHAN_EXTENDED_IGNORE: return "ignore"; default: return "UNKNOWN"; } } static char * channel_format_status(const Channel *c) { char *ret = NULL; xasprintf(&ret, "t%d [%s] %s%u %s%u i%u/%zu o%u/%zu e[%s]/%zu " "fd %d/%d/%d sock %d cc %d %s%u io 0x%02x/0x%02x", c->type, c->xctype != NULL ? c->xctype : c->ctype, c->have_remote_id ? "r" : "nr", c->remote_id, c->mux_ctx != NULL ? "m" : "nm", c->mux_downstream_id, c->istate, sshbuf_len(c->input), c->ostate, sshbuf_len(c->output), channel_format_extended_usage(c), sshbuf_len(c->extended), c->rfd, c->wfd, c->efd, c->sock, c->ctl_chan, c->have_ctl_child_id ? "c" : "nc", c->ctl_child_id, c->io_want, c->io_ready); return ret; } /* * Returns a message describing the currently open forwarded connections, * suitable for sending to the client. The message contains crlf pairs for * newlines. */ char * channel_open_message(struct ssh *ssh) { struct sshbuf *buf; Channel *c; u_int i; int r; char *cp, *ret; if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_putf(buf, "The following connections are open:\r\n")) != 0) fatal_fr(r, "sshbuf_putf"); for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL) continue; switch (c->type) { case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_MUX_LISTENER: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_MUX_PROXY: case SSH_CHANNEL_MUX_CLIENT: cp = channel_format_status(c); if ((r = sshbuf_putf(buf, " #%d %.300s (%s)\r\n", c->self, c->remote_name, cp)) != 0) { free(cp); fatal_fr(r, "sshbuf_putf"); } free(cp); continue; default: fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } if ((ret = sshbuf_dup_string(buf)) == NULL) fatal_f("sshbuf_dup_string"); sshbuf_free(buf); return ret; } static void open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) { int r; if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 || (r = sshpkt_put_cstring(ssh, type)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { fatal_r(r, "%s: channel %i: open", where, c->self); } } void channel_send_open(struct ssh *ssh, int id) { Channel *c = channel_lookup(ssh, id); int r; if (c == NULL) { logit("channel_send_open: %d: bad id", id); return; } debug2("channel %d: send open", id); open_preamble(ssh, __func__, c, c->ctype); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i", c->self); } void channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm) { Channel *c = channel_lookup(ssh, id); int r; if (c == NULL) { logit_f("%d: unknown channel id", id); return; } if (!c->have_remote_id) fatal_f("channel %d: no remote id", c->self); debug2("channel %d: request %s confirm %d", id, service, wantconfirm); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_cstring(ssh, service)) != 0 || (r = sshpkt_put_u8(ssh, wantconfirm)) != 0) { fatal_fr(r, "channel %i", c->self); } } void channel_register_status_confirm(struct ssh *ssh, int id, channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx) { struct channel_confirm *cc; Channel *c; if ((c = channel_lookup(ssh, id)) == NULL) fatal_f("%d: bad id", id); cc = xcalloc(1, sizeof(*cc)); cc->cb = cb; cc->abandon_cb = abandon_cb; cc->ctx = ctx; TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry); } void channel_register_open_confirm(struct ssh *ssh, int id, channel_open_fn *fn, void *ctx) { Channel *c = channel_lookup(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->open_confirm = fn; c->open_confirm_ctx = ctx; } void channel_register_cleanup(struct ssh *ssh, int id, channel_callback_fn *fn, int do_close) { Channel *c = channel_by_id(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->detach_user = fn; c->detach_close = do_close; } void channel_cancel_cleanup(struct ssh *ssh, int id) { Channel *c = channel_by_id(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->detach_user = NULL; c->detach_close = 0; } void channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn, channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx) { Channel *c = channel_lookup(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->input_filter = ifn; c->output_filter = ofn; c->filter_ctx = ctx; c->filter_cleanup = cfn; } void channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd, int extusage, int nonblock, int is_tty, u_int window_max) { Channel *c = channel_lookup(ssh, id); int r; if (c == NULL || c->type != SSH_CHANNEL_LARVAL) fatal("channel_activate for non-larval channel %d.", id); if (!c->have_remote_id) fatal_f("channel %d: no remote id", c->self); channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); c->type = SSH_CHANNEL_OPEN; channel_set_used_time(ssh, c); c->local_window = c->local_window_max = window_max; if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i", c->self); } static void channel_pre_listener(struct ssh *ssh, Channel *c) { c->io_want = SSH_CHAN_IO_SOCK_R; } static void channel_pre_connecting(struct ssh *ssh, Channel *c) { debug3("channel %d: waiting for connection", c->self); c->io_want = SSH_CHAN_IO_SOCK_W; } static void channel_pre_open(struct ssh *ssh, Channel *c) { c->io_want = 0; if (c->istate == CHAN_INPUT_OPEN && c->remote_window > 0 && sshbuf_len(c->input) < c->remote_window && sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) c->io_want |= SSH_CHAN_IO_RFD; if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (sshbuf_len(c->output) > 0) { c->io_want |= SSH_CHAN_IO_WFD; } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) debug2("channel %d: " "obuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); else chan_obuf_empty(ssh, c); } } /** XXX check close conditions, too */ if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) { if (c->extended_usage == CHAN_EXTENDED_WRITE && sshbuf_len(c->extended) > 0) c->io_want |= SSH_CHAN_IO_EFD_W; else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) && (c->extended_usage == CHAN_EXTENDED_READ || c->extended_usage == CHAN_EXTENDED_IGNORE) && sshbuf_len(c->extended) < c->remote_window) c->io_want |= SSH_CHAN_IO_EFD_R; } /* XXX: What about efd? races? */ } /* * This is a special state for X11 authentication spoofing. An opened X11 * connection (when authentication spoofing is being done) remains in this * state until the first packet has been completely read. The authentication * data in that packet is then substituted by the real data if it matches the * fake data, and the channel is put into normal mode. * XXX All this happens at the client side. * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok */ static int x11_open_helper(struct ssh *ssh, struct sshbuf *b) { struct ssh_channels *sc = ssh->chanctxt; u_char *ucp; u_int proto_len, data_len; /* Is this being called after the refusal deadline? */ if (sc->x11_refuse_time != 0 && monotime() >= sc->x11_refuse_time) { verbose("Rejected X11 connection after ForwardX11Timeout " "expired"); return -1; } /* Check if the fixed size part of the packet is in buffer. */ if (sshbuf_len(b) < 12) return 0; /* Parse the lengths of variable-length fields. */ ucp = sshbuf_mutable_ptr(b); if (ucp[0] == 0x42) { /* Byte order MSB first. */ proto_len = 256 * ucp[6] + ucp[7]; data_len = 256 * ucp[8] + ucp[9]; } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */ proto_len = ucp[6] + 256 * ucp[7]; data_len = ucp[8] + 256 * ucp[9]; } else { debug2("Initial X11 packet contains bad byte order byte: 0x%x", ucp[0]); return -1; } /* Check if the whole packet is in buffer. */ if (sshbuf_len(b) < 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) return 0; /* Check if authentication protocol matches. */ if (proto_len != strlen(sc->x11_saved_proto) || memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) { debug2("X11 connection uses different authentication protocol."); return -1; } /* Check if authentication data matches our fake data. */ if (data_len != sc->x11_fake_data_len || timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3), sc->x11_fake_data, sc->x11_fake_data_len) != 0) { debug2("X11 auth data does not match fake data."); return -1; } /* Check fake data length */ if (sc->x11_fake_data_len != sc->x11_saved_data_len) { error("X11 fake_data_len %d != saved_data_len %d", sc->x11_fake_data_len, sc->x11_saved_data_len); return -1; } /* * Received authentication protocol and data match * our fake data. Substitute the fake data with real * data. */ memcpy(ucp + 12 + ((proto_len + 3) & ~3), sc->x11_saved_data, sc->x11_saved_data_len); return 1; } void channel_force_close(struct ssh *ssh, Channel *c, int abandon) { debug3_f("channel %d: forcibly closing", c->self); if (c->istate == CHAN_INPUT_OPEN) chan_read_failed(ssh, c); if (c->istate == CHAN_INPUT_WAIT_DRAIN) { sshbuf_reset(c->input); chan_ibuf_empty(ssh, c); } if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { sshbuf_reset(c->output); chan_write_failed(ssh, c); } if (c->detach_user) c->detach_user(ssh, c->self, 1, NULL); if (c->efd != -1) channel_close_fd(ssh, c, &c->efd); if (abandon) c->type = SSH_CHANNEL_ABANDONED; /* exempt from inactivity timeouts */ c->inactive_deadline = 0; c->lastused = 0; } static void channel_pre_x11_open(struct ssh *ssh, Channel *c) { int ret = x11_open_helper(ssh, c->output); /* c->force_drain = 1; */ if (ret == 1) { c->type = SSH_CHANNEL_OPEN; channel_set_used_time(ssh, c); channel_pre_open(ssh, c); } else if (ret == -1) { logit("X11 connection rejected because of wrong " "authentication."); debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); channel_force_close(ssh, c, 0); } } static void channel_pre_mux_client(struct ssh *ssh, Channel *c) { c->io_want = 0; if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) c->io_want |= SSH_CHAN_IO_RFD; if (c->istate == CHAN_INPUT_WAIT_DRAIN) { /* clear buffer immediately (discard any partial packet) */ sshbuf_reset(c->input); chan_ibuf_empty(ssh, c); /* Start output drain. XXX just kill chan? */ chan_rcvd_oclose(ssh, c); } if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (sshbuf_len(c->output) > 0) c->io_want |= SSH_CHAN_IO_WFD; else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) chan_obuf_empty(ssh, c); } } /* try to decode a socks4 header */ static int channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output) { const u_char *p; char *host; u_int len, have, i, found, need; char username[256]; struct { u_int8_t version; u_int8_t command; u_int16_t dest_port; struct in_addr dest_addr; } s4_req, s4_rsp; int r; debug2("channel %d: decode socks4", c->self); have = sshbuf_len(input); len = sizeof(s4_req); if (have < len) return 0; p = sshbuf_ptr(input); need = 1; /* SOCKS4A uses an invalid IP address 0.0.0.x */ if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) { debug2("channel %d: socks4a request", c->self); /* ... and needs an extra string (the hostname) */ need = 2; } /* Check for terminating NUL on the string(s) */ for (found = 0, i = len; i < have; i++) { if (p[i] == '\0') { found++; if (found == need) break; } if (i > 1024) { /* the peer is probably sending garbage */ debug("channel %d: decode socks4: too long", c->self); return -1; } } if (found < need) return 0; if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 || (r = sshbuf_get(input, &s4_req.command, 1)) != 0 || (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 || (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) { debug_r(r, "channels %d: decode socks4", c->self); return -1; } have = sshbuf_len(input); p = sshbuf_ptr(input); if (memchr(p, '\0', have) == NULL) { error("channel %d: decode socks4: unterminated user", c->self); return -1; } len = strlen(p); debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); len++; /* trailing '\0' */ strlcpy(username, p, sizeof(username)); if ((r = sshbuf_consume(input, len)) != 0) fatal_fr(r, "channel %d: consume", c->self); free(c->path); c->path = NULL; if (need == 1) { /* SOCKS4: one string */ host = inet_ntoa(s4_req.dest_addr); c->path = xstrdup(host); } else { /* SOCKS4A: two strings */ have = sshbuf_len(input); p = sshbuf_ptr(input); if (memchr(p, '\0', have) == NULL) { error("channel %d: decode socks4a: host not nul " "terminated", c->self); return -1; } len = strlen(p); debug2("channel %d: decode socks4a: host %s/%d", c->self, p, len); len++; /* trailing '\0' */ if (len > NI_MAXHOST) { error("channel %d: hostname \"%.100s\" too long", c->self, p); return -1; } c->path = xstrdup(p); if ((r = sshbuf_consume(input, len)) != 0) fatal_fr(r, "channel %d: consume", c->self); } c->host_port = ntohs(s4_req.dest_port); debug2("channel %d: dynamic request: socks4 host %s port %u command %u", c->self, c->path, c->host_port, s4_req.command); if (s4_req.command != 1) { debug("channel %d: cannot handle: %s cn %d", c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command); return -1; } s4_rsp.version = 0; /* vn: 0 for reply */ s4_rsp.command = 90; /* cd: req granted */ s4_rsp.dest_port = 0; /* ignored */ s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) fatal_fr(r, "channel %d: append reply", c->self); return 1; } /* try to decode a socks5 header */ #define SSH_SOCKS5_AUTHDONE 0x1000 #define SSH_SOCKS5_NOAUTH 0x00 #define SSH_SOCKS5_IPV4 0x01 #define SSH_SOCKS5_DOMAIN 0x03 #define SSH_SOCKS5_IPV6 0x04 #define SSH_SOCKS5_CONNECT 0x01 #define SSH_SOCKS5_SUCCESS 0x00 static int channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) { /* XXX use get/put_u8 instead of trusting struct padding */ struct { u_int8_t version; u_int8_t command; u_int8_t reserved; u_int8_t atyp; } s5_req, s5_rsp; u_int16_t dest_port; char dest_addr[255+1], ntop[INET6_ADDRSTRLEN]; const u_char *p; u_int have, need, i, found, nmethods, addrlen, af; int r; debug2("channel %d: decode socks5", c->self); p = sshbuf_ptr(input); if (p[0] != 0x05) return -1; have = sshbuf_len(input); if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { /* format: ver | nmethods | methods */ if (have < 2) return 0; nmethods = p[1]; if (have < nmethods + 2) return 0; /* look for method: "NO AUTHENTICATION REQUIRED" */ for (found = 0, i = 2; i < nmethods + 2; i++) { if (p[i] == SSH_SOCKS5_NOAUTH) { found = 1; break; } } if (!found) { debug("channel %d: method SSH_SOCKS5_NOAUTH not found", c->self); return -1; } if ((r = sshbuf_consume(input, nmethods + 2)) != 0) fatal_fr(r, "channel %d: consume", c->self); /* version, method */ if ((r = sshbuf_put_u8(output, 0x05)) != 0 || (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) fatal_fr(r, "channel %d: append reply", c->self); c->flags |= SSH_SOCKS5_AUTHDONE; debug2("channel %d: socks5 auth done", c->self); return 0; /* need more */ } debug2("channel %d: socks5 post auth", c->self); if (have < sizeof(s5_req)+1) return 0; /* need more */ memcpy(&s5_req, p, sizeof(s5_req)); if (s5_req.version != 0x05 || s5_req.command != SSH_SOCKS5_CONNECT || s5_req.reserved != 0x00) { debug2("channel %d: only socks5 connect supported", c->self); return -1; } switch (s5_req.atyp){ case SSH_SOCKS5_IPV4: addrlen = 4; af = AF_INET; break; case SSH_SOCKS5_DOMAIN: addrlen = p[sizeof(s5_req)]; af = -1; break; case SSH_SOCKS5_IPV6: addrlen = 16; af = AF_INET6; break; default: debug2("channel %d: bad socks5 atyp %d", c->self, s5_req.atyp); return -1; } need = sizeof(s5_req) + addrlen + 2; if (s5_req.atyp == SSH_SOCKS5_DOMAIN) need++; if (have < need) return 0; if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) fatal_fr(r, "channel %d: consume", c->self); if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { /* host string length */ if ((r = sshbuf_consume(input, 1)) != 0) fatal_fr(r, "channel %d: consume", c->self); } if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 || (r = sshbuf_get(input, &dest_port, 2)) != 0) { debug_r(r, "channel %d: parse addr/port", c->self); return -1; } dest_addr[addrlen] = '\0'; free(c->path); c->path = NULL; if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { if (addrlen >= NI_MAXHOST) { error("channel %d: dynamic request: socks5 hostname " "\"%.100s\" too long", c->self, dest_addr); return -1; } c->path = xstrdup(dest_addr); } else { if (inet_ntop(af, dest_addr, ntop, sizeof(ntop)) == NULL) return -1; c->path = xstrdup(ntop); } c->host_port = ntohs(dest_port); debug2("channel %d: dynamic request: socks5 host %s port %u command %u", c->self, c->path, c->host_port, s5_req.command); s5_rsp.version = 0x05; s5_rsp.command = SSH_SOCKS5_SUCCESS; s5_rsp.reserved = 0; /* ignored */ s5_rsp.atyp = SSH_SOCKS5_IPV4; dest_port = 0; /* ignored */ if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 || (r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 || (r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0) fatal_fr(r, "channel %d: append reply", c->self); return 1; } Channel * channel_connect_stdio_fwd(struct ssh *ssh, const char *host_to_connect, int port_to_connect, int in, int out, int nonblock) { Channel *c; debug_f("%s:%d", host_to_connect, port_to_connect); c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "stdio-forward", nonblock); c->path = xstrdup(host_to_connect); c->host_port = port_to_connect; c->listening_port = 0; c->force_drain = 1; channel_register_fds(ssh, c, in, out, -1, 0, 1, 0); port_open_helper(ssh, c, port_to_connect == PORT_STREAMLOCAL ? "direct-streamlocal@openssh.com" : "direct-tcpip"); return c; } /* dynamic port forwarding */ static void channel_pre_dynamic(struct ssh *ssh, Channel *c) { const u_char *p; u_int have; int ret; c->io_want = 0; have = sshbuf_len(c->input); debug2("channel %d: pre_dynamic: have %d", c->self, have); /* sshbuf_dump(c->input, stderr); */ /* check if the fixed size part of the packet is in buffer. */ if (have < 3) { /* need more */ c->io_want |= SSH_CHAN_IO_RFD; return; } /* try to guess the protocol */ p = sshbuf_ptr(c->input); /* XXX sshbuf_peek_u8? */ switch (p[0]) { case 0x04: ret = channel_decode_socks4(c, c->input, c->output); break; case 0x05: ret = channel_decode_socks5(c, c->input, c->output); break; default: ret = -1; break; } if (ret < 0) { chan_mark_dead(ssh, c); } else if (ret == 0) { debug2("channel %d: pre_dynamic: need more", c->self); /* need more */ c->io_want |= SSH_CHAN_IO_RFD; if (sshbuf_len(c->output)) c->io_want |= SSH_CHAN_IO_WFD; } else { /* switch to the next state */ c->type = SSH_CHANNEL_OPENING; port_open_helper(ssh, c, "direct-tcpip"); } } /* simulate read-error */ static void rdynamic_close(struct ssh *ssh, Channel *c) { c->type = SSH_CHANNEL_OPEN; channel_force_close(ssh, c, 0); } /* reverse dynamic port forwarding */ static void channel_before_prepare_io_rdynamic(struct ssh *ssh, Channel *c) { const u_char *p; u_int have, len; int r, ret; have = sshbuf_len(c->output); debug2("channel %d: pre_rdynamic: have %d", c->self, have); /* sshbuf_dump(c->output, stderr); */ /* EOF received */ if (c->flags & CHAN_EOF_RCVD) { if ((r = sshbuf_consume(c->output, have)) != 0) fatal_fr(r, "channel %d: consume", c->self); rdynamic_close(ssh, c); return; } /* check if the fixed size part of the packet is in buffer. */ if (have < 3) return; /* try to guess the protocol */ p = sshbuf_ptr(c->output); switch (p[0]) { case 0x04: /* switch input/output for reverse forwarding */ ret = channel_decode_socks4(c, c->output, c->input); break; case 0x05: ret = channel_decode_socks5(c, c->output, c->input); break; default: ret = -1; break; } if (ret < 0) { rdynamic_close(ssh, c); } else if (ret == 0) { debug2("channel %d: pre_rdynamic: need more", c->self); /* send socks request to peer */ len = sshbuf_len(c->input); if (len > 0 && len < c->remote_window) { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_stringb(ssh, c->input)) != 0 || (r = sshpkt_send(ssh)) != 0) { fatal_fr(r, "channel %i: rdynamic", c->self); } if ((r = sshbuf_consume(c->input, len)) != 0) fatal_fr(r, "channel %d: consume", c->self); c->remote_window -= len; } } else if (rdynamic_connect_finish(ssh, c) < 0) { /* the connect failed */ rdynamic_close(ssh, c); } } /* This is our fake X11 server socket. */ static void channel_post_x11_listener(struct ssh *ssh, Channel *c) { Channel *nc; struct sockaddr_storage addr; int r, newsock, oerrno, remote_port; socklen_t addrlen; char buf[16384], *remote_ipaddr; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; debug("X11 connection requested."); addrlen = sizeof(addr); newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); if (c->single_connection) { oerrno = errno; debug2("single_connection: closing X11 listener."); channel_close_fd(ssh, c, &c->sock); chan_mark_dead(ssh, c); errno = oerrno; } if (newsock == -1) { if (errno != EINTR && errno != EWOULDBLOCK && errno != ECONNABORTED) error("accept: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } set_nodelay(newsock); remote_ipaddr = get_peer_ipaddr(newsock); remote_port = get_peer_port(newsock); snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", remote_ipaddr, remote_port); nc = channel_new(ssh, "x11-connection", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, buf, 1); open_preamble(ssh, __func__, nc, "x11"); if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 || (r = sshpkt_put_u32(ssh, remote_port)) != 0) { fatal_fr(r, "channel %i: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: send", c->self); free(remote_ipaddr); } static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype) { char *local_ipaddr = get_local_ipaddr(c->sock); int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock); char *remote_ipaddr = get_peer_ipaddr(c->sock); int remote_port = get_peer_port(c->sock); int r; if (remote_port == -1) { /* Fake addr/port to appease peers that validate it (Tectia) */ free(remote_ipaddr); remote_ipaddr = xstrdup("127.0.0.1"); remote_port = 65535; } free(c->remote_name); xasprintf(&c->remote_name, "%s: listening port %d for %.100s port %d, " "connect from %.200s port %d to %.100s port %d", rtype, c->listening_port, c->path, c->host_port, remote_ipaddr, remote_port, local_ipaddr, local_port); open_preamble(ssh, __func__, c, rtype); if (strcmp(rtype, "direct-tcpip") == 0) { /* target host, port */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || (r = sshpkt_put_u32(ssh, c->host_port)) != 0) fatal_fr(r, "channel %i: reply", c->self); } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { /* target path */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) fatal_fr(r, "channel %i: reply", c->self); } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { /* listen path */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) fatal_fr(r, "channel %i: reply", c->self); } else { /* listen address, port */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || (r = sshpkt_put_u32(ssh, local_port)) != 0) fatal_fr(r, "channel %i: reply", c->self); } if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { /* reserved for future owner/mode info */ if ((r = sshpkt_put_cstring(ssh, "")) != 0) fatal_fr(r, "channel %i: reply", c->self); } else { /* originator host and port */ if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) fatal_fr(r, "channel %i: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: send", c->self); free(remote_ipaddr); free(local_ipaddr); } void channel_set_x11_refuse_time(struct ssh *ssh, time_t refuse_time) { ssh->chanctxt->x11_refuse_time = refuse_time; } /* * This socket is listening for connections to a forwarded TCP/IP port. */ static void channel_post_port_listener(struct ssh *ssh, Channel *c) { Channel *nc; struct sockaddr_storage addr; int newsock, nextstate; socklen_t addrlen; char *rtype; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; debug("Connection to port %d forwarding to %.100s port %d requested.", c->listening_port, c->path, c->host_port); if (c->type == SSH_CHANNEL_RPORT_LISTENER) { nextstate = SSH_CHANNEL_OPENING; rtype = "forwarded-tcpip"; } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { nextstate = SSH_CHANNEL_OPENING; rtype = "forwarded-streamlocal@openssh.com"; } else if (c->host_port == PORT_STREAMLOCAL) { nextstate = SSH_CHANNEL_OPENING; rtype = "direct-streamlocal@openssh.com"; } else if (c->host_port == 0) { nextstate = SSH_CHANNEL_DYNAMIC; rtype = "dynamic-tcpip"; } else { nextstate = SSH_CHANNEL_OPENING; rtype = "direct-tcpip"; } addrlen = sizeof(addr); newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); if (newsock == -1) { if (errno != EINTR && errno != EWOULDBLOCK && errno != ECONNABORTED) error("accept: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } if (c->host_port != PORT_STREAMLOCAL) set_nodelay(newsock); nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, rtype, 1); nc->listening_port = c->listening_port; nc->host_port = c->host_port; if (c->path != NULL) nc->path = xstrdup(c->path); if (nextstate != SSH_CHANNEL_DYNAMIC) port_open_helper(ssh, nc, rtype); } /* * This is the authentication agent socket listening for connections from * clients. */ static void channel_post_auth_listener(struct ssh *ssh, Channel *c) { Channel *nc; int r, newsock; struct sockaddr_storage addr; socklen_t addrlen; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; addrlen = sizeof(addr); newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); if (newsock == -1) { error("accept from auth socket: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } nc = channel_new(ssh, "agent-connection", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, "accepted auth socket", 1); open_preamble(ssh, __func__, nc, "auth-agent@openssh.com"); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i", c->self); } static void channel_post_connecting(struct ssh *ssh, Channel *c) { int err = 0, sock, isopen, r; socklen_t sz = sizeof(err); if ((c->io_ready & SSH_CHAN_IO_SOCK_W) == 0) return; if (!c->have_remote_id) fatal_f("channel %d: no remote id", c->self); /* for rdynamic the OPEN_CONFIRMATION has been sent already */ isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH); if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) == -1) { err = errno; error("getsockopt SO_ERROR failed"); } if (err == 0) { /* Non-blocking connection completed */ debug("channel %d: connected to %s port %d", c->self, c->connect_ctx.host, c->connect_ctx.port); channel_connect_ctx_free(&c->connect_ctx); c->type = SSH_CHANNEL_OPEN; channel_set_used_time(ssh, c); if (isopen) { /* no message necessary */ } else { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i open confirm", c->self); } return; } if (err == EINTR || err == EAGAIN || err == EINPROGRESS) return; /* Non-blocking connection failed */ debug("channel %d: connection failed: %s", c->self, strerror(err)); /* Try next address, if any */ if ((sock = connect_next(&c->connect_ctx)) == -1) { /* Exhausted all addresses for this destination */ error("connect_to %.100s port %d: failed.", c->connect_ctx.host, c->connect_ctx.port); channel_connect_ctx_free(&c->connect_ctx); if (isopen) { rdynamic_close(ssh, c); } else { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_OPEN_CONNECT_FAILED)) != 0 || (r = sshpkt_put_cstring(ssh, strerror(err))) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: failure", c->self); chan_mark_dead(ssh, c); } } /* New non-blocking connection in progress */ close(c->sock); c->sock = c->rfd = c->wfd = sock; } static int channel_handle_rfd(struct ssh *ssh, Channel *c) { char buf[CHAN_RBUF]; ssize_t len; int r, force; size_t nr = 0, have, avail, maxlen = CHANNEL_MAX_READ; int pty_zeroread = 0; #ifdef PTY_ZEROREAD /* Bug on AIX: read(1) can return 0 for a non-closed fd */ pty_zeroread = c->isatty; #endif force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED; if (!force && (c->io_ready & SSH_CHAN_IO_RFD) == 0) return 1; if ((avail = sshbuf_avail(c->input)) == 0) return 1; /* Shouldn't happen */ /* * For "simple" channels (i.e. not datagram or filtered), we can * read directly to the channel buffer. */ if (!pty_zeroread && c->input_filter == NULL && !c->datagram) { /* Only OPEN channels have valid rwin */ if (c->type == SSH_CHANNEL_OPEN) { if ((have = sshbuf_len(c->input)) >= c->remote_window) return 1; /* shouldn't happen */ if (maxlen > c->remote_window - have) maxlen = c->remote_window - have; } if (maxlen > avail) maxlen = avail; if ((r = sshbuf_read(c->rfd, c->input, maxlen, &nr)) != 0) { if (errno == EINTR || (!force && (errno == EAGAIN || errno == EWOULDBLOCK))) return 1; debug2("channel %d: read failed rfd %d maxlen %zu: %s", c->self, c->rfd, maxlen, ssh_err(r)); goto rfail; } if (nr != 0) channel_set_used_time(ssh, c); return 1; } errno = 0; len = read(c->rfd, buf, sizeof(buf)); /* fixup AIX zero-length read with errno set to look more like errors */ if (pty_zeroread && len == 0 && errno != 0) len = -1; if (len == -1 && (errno == EINTR || ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) return 1; if (len < 0 || (!pty_zeroread && len == 0)) { debug2("channel %d: read<=0 rfd %d len %zd: %s", c->self, c->rfd, len, len == 0 ? "closed" : strerror(errno)); rfail: if (c->type != SSH_CHANNEL_OPEN) { debug2("channel %d: not open", c->self); chan_mark_dead(ssh, c); return -1; } else { chan_read_failed(ssh, c); } return -1; } channel_set_used_time(ssh, c); if (c->input_filter != NULL) { if (c->input_filter(ssh, c, buf, len) == -1) { debug2("channel %d: filter stops", c->self); chan_read_failed(ssh, c); } } else if (c->datagram) { if ((r = sshbuf_put_string(c->input, buf, len)) != 0) fatal_fr(r, "channel %i: put datagram", c->self); } else if ((r = sshbuf_put(c->input, buf, len)) != 0) fatal_fr(r, "channel %i: put data", c->self); return 1; } static int channel_handle_wfd(struct ssh *ssh, Channel *c) { struct termios tio; u_char *data = NULL, *buf; /* XXX const; need filter API change */ size_t dlen, olen = 0; int r, len; if ((c->io_ready & SSH_CHAN_IO_WFD) == 0) return 1; if (sshbuf_len(c->output) == 0) return 1; /* Send buffered output data to the socket. */ olen = sshbuf_len(c->output); if (c->output_filter != NULL) { if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL) { debug2("channel %d: filter stops", c->self); if (c->type != SSH_CHANNEL_OPEN) chan_mark_dead(ssh, c); else chan_write_failed(ssh, c); return -1; } } else if (c->datagram) { if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0) fatal_fr(r, "channel %i: get datagram", c->self); buf = data; } else { buf = data = sshbuf_mutable_ptr(c->output); dlen = sshbuf_len(c->output); } if (c->datagram) { /* ignore truncated writes, datagrams might get lost */ len = write(c->wfd, buf, dlen); free(data); if (len == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) return 1; if (len <= 0) goto write_fail; goto out; } #ifdef _AIX /* XXX: Later AIX versions can't push as much data to tty */ if (c->wfd_isatty) dlen = MINIMUM(dlen, 8*1024); #endif len = write(c->wfd, buf, dlen); if (len == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) return 1; if (len <= 0) { write_fail: if (c->type != SSH_CHANNEL_OPEN) { debug2("channel %d: not open", c->self); chan_mark_dead(ssh, c); return -1; } else { chan_write_failed(ssh, c); } return -1; } channel_set_used_time(ssh, c); #ifndef BROKEN_TCGETATTR_ICANON if (c->isatty && dlen >= 1 && buf[0] != '\r') { if (tcgetattr(c->wfd, &tio) == 0 && !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { /* * Simulate echo to reduce the impact of * traffic analysis. We need to match the * size of a SSH2_MSG_CHANNEL_DATA message * (4 byte channel id + buf) */ if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: ignore", c->self); } } #endif /* BROKEN_TCGETATTR_ICANON */ if ((r = sshbuf_consume(c->output, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); out: c->local_consumed += olen - sshbuf_len(c->output); return 1; } static int channel_handle_efd_write(struct ssh *ssh, Channel *c) { int r; ssize_t len; if ((c->io_ready & SSH_CHAN_IO_EFD_W) == 0) return 1; if (sshbuf_len(c->extended) == 0) return 1; len = write(c->efd, sshbuf_ptr(c->extended), sshbuf_len(c->extended)); debug2("channel %d: written %zd to efd %d", c->self, len, c->efd); if (len == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) return 1; if (len <= 0) { debug2("channel %d: closing write-efd %d", c->self, c->efd); channel_close_fd(ssh, c, &c->efd); } else { if ((r = sshbuf_consume(c->extended, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); c->local_consumed += len; channel_set_used_time(ssh, c); } return 1; } static int channel_handle_efd_read(struct ssh *ssh, Channel *c) { char buf[CHAN_RBUF]; ssize_t len; int r, force; force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED; if (!force && (c->io_ready & SSH_CHAN_IO_EFD_R) == 0) return 1; len = read(c->efd, buf, sizeof(buf)); debug2("channel %d: read %zd from efd %d", c->self, len, c->efd); if (len == -1 && (errno == EINTR || ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) return 1; if (len <= 0) { debug2("channel %d: closing read-efd %d", c->self, c->efd); channel_close_fd(ssh, c, &c->efd); return 1; } channel_set_used_time(ssh, c); if (c->extended_usage == CHAN_EXTENDED_IGNORE) debug3("channel %d: discard efd", c->self); else if ((r = sshbuf_put(c->extended, buf, len)) != 0) fatal_fr(r, "channel %i: append", c->self); return 1; } static int channel_handle_efd(struct ssh *ssh, Channel *c) { if (c->efd == -1) return 1; /** XXX handle drain efd, too */ if (c->extended_usage == CHAN_EXTENDED_WRITE) return channel_handle_efd_write(ssh, c); else if (c->extended_usage == CHAN_EXTENDED_READ || c->extended_usage == CHAN_EXTENDED_IGNORE) return channel_handle_efd_read(ssh, c); return 1; } static int channel_check_window(struct ssh *ssh, Channel *c) { int r; if (c->type == SSH_CHANNEL_OPEN && !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && ((c->local_window_max - c->local_window > c->local_maxpacket*3) || c->local_window < c->local_window_max/2) && c->local_consumed > 0) { if (!c->have_remote_id) fatal_f("channel %d: no remote id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 || (r = sshpkt_send(ssh)) != 0) { fatal_fr(r, "channel %i", c->self); } debug2("channel %d: window %d sent adjust %d", c->self, c->local_window, c->local_consumed); c->local_window += c->local_consumed; c->local_consumed = 0; } return 1; } static void channel_post_open(struct ssh *ssh, Channel *c) { channel_handle_rfd(ssh, c); channel_handle_wfd(ssh, c); channel_handle_efd(ssh, c); channel_check_window(ssh, c); } static u_int read_mux(struct ssh *ssh, Channel *c, u_int need) { char buf[CHAN_RBUF]; ssize_t len; u_int rlen; int r; if (sshbuf_len(c->input) < need) { rlen = need - sshbuf_len(c->input); len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF)); if (len == -1 && (errno == EINTR || errno == EAGAIN)) return sshbuf_len(c->input); if (len <= 0) { debug2("channel %d: ctl read<=0 rfd %d len %zd", c->self, c->rfd, len); chan_read_failed(ssh, c); return 0; } else if ((r = sshbuf_put(c->input, buf, len)) != 0) fatal_fr(r, "channel %i: append", c->self); } return sshbuf_len(c->input); } static void channel_post_mux_client_read(struct ssh *ssh, Channel *c) { u_int need; if ((c->io_ready & SSH_CHAN_IO_RFD) == 0) return; if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN) return; if (c->mux_pause) return; /* * Don't not read past the precise end of packets to * avoid disrupting fd passing. */ if (read_mux(ssh, c, 4) < 4) /* read header */ return; /* XXX sshbuf_peek_u32 */ need = PEEK_U32(sshbuf_ptr(c->input)); #define CHANNEL_MUX_MAX_PACKET (256 * 1024) if (need > CHANNEL_MUX_MAX_PACKET) { debug2("channel %d: packet too big %u > %u", c->self, CHANNEL_MUX_MAX_PACKET, need); chan_rcvd_oclose(ssh, c); return; } if (read_mux(ssh, c, need + 4) < need + 4) /* read body */ return; if (c->mux_rcb(ssh, c) != 0) { debug("channel %d: mux_rcb failed", c->self); chan_mark_dead(ssh, c); return; } } static void channel_post_mux_client_write(struct ssh *ssh, Channel *c) { ssize_t len; int r; if ((c->io_ready & SSH_CHAN_IO_WFD) == 0) return; if (sshbuf_len(c->output) == 0) return; len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output)); if (len == -1 && (errno == EINTR || errno == EAGAIN)) return; if (len <= 0) { chan_mark_dead(ssh, c); return; } if ((r = sshbuf_consume(c->output, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); } static void channel_post_mux_client(struct ssh *ssh, Channel *c) { channel_post_mux_client_read(ssh, c); channel_post_mux_client_write(ssh, c); } static void channel_post_mux_listener(struct ssh *ssh, Channel *c) { Channel *nc; struct sockaddr_storage addr; socklen_t addrlen; int newsock; uid_t euid; gid_t egid; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; debug("multiplexing control connection"); /* * Accept connection on control socket */ memset(&addr, 0, sizeof(addr)); addrlen = sizeof(addr); if ((newsock = accept(c->sock, (struct sockaddr*)&addr, &addrlen)) == -1) { error_f("accept: %s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } if (getpeereid(newsock, &euid, &egid) == -1) { error_f("getpeereid failed: %s", strerror(errno)); close(newsock); return; } if ((euid != 0) && (getuid() != euid)) { error("multiplex uid mismatch: peer euid %u != uid %u", (u_int)euid, (u_int)getuid()); close(newsock); return; } nc = channel_new(ssh, "mux-control", SSH_CHANNEL_MUX_CLIENT, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, "mux-control", 1); nc->mux_rcb = c->mux_rcb; debug3_f("new mux channel %d fd %d", nc->self, nc->sock); /* establish state */ nc->mux_rcb(ssh, nc); /* mux state transitions must not elicit protocol messages */ nc->flags |= CHAN_LOCAL; } static void channel_handler_init(struct ssh_channels *sc) { chan_fn **pre, **post; if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL || (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL) fatal_f("allocation failed"); pre[SSH_CHANNEL_OPEN] = &channel_pre_open; pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; pre[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_pre_connecting; pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; post[SSH_CHANNEL_OPEN] = &channel_post_open; post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; post[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_post_connecting; post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; sc->channel_pre = pre; sc->channel_post = post; } /* gc dead channels */ static void channel_garbage_collect(struct ssh *ssh, Channel *c) { if (c == NULL) return; if (c->detach_user != NULL) { if (!chan_is_dead(ssh, c, c->detach_close)) return; debug2("channel %d: gc: notify user", c->self); c->detach_user(ssh, c->self, 0, NULL); /* if we still have a callback */ if (c->detach_user != NULL) return; debug2("channel %d: gc: user detached", c->self); } if (!chan_is_dead(ssh, c, 1)) return; debug2("channel %d: garbage collecting", c->self); channel_free(ssh, c); } enum channel_table { CHAN_PRE, CHAN_POST }; static void channel_handler(struct ssh *ssh, int table, struct timespec *timeout) { struct ssh_channels *sc = ssh->chanctxt; chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post; u_int i, oalloc; Channel *c; time_t now; now = monotime(); for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { c = sc->channels[i]; if (c == NULL) continue; /* Try to keep IO going while rekeying */ if (ssh_packet_is_rekeying(ssh) && c->type != SSH_CHANNEL_OPEN) continue; if (c->delayed) { if (table == CHAN_PRE) c->delayed = 0; else continue; } if (ftab[c->type] != NULL) { if (table == CHAN_PRE && c->type == SSH_CHANNEL_OPEN && channel_get_expiry(ssh, c) != 0 && now >= channel_get_expiry(ssh, c)) { /* channel closed for inactivity */ verbose("channel %d: closing after %u seconds " "of inactivity", c->self, c->inactive_deadline); channel_force_close(ssh, c, 1); } else if (c->notbefore <= now) { /* Run handlers that are not paused. */ (*ftab[c->type])(ssh, c); /* inactivity timeouts must interrupt poll() */ if (timeout != NULL && c->type == SSH_CHANNEL_OPEN && channel_get_expiry(ssh, c) != 0) { ptimeout_deadline_monotime(timeout, channel_get_expiry(ssh, c)); } } else if (timeout != NULL) { /* * Arrange for poll() wakeup when channel pause * timer expires. */ ptimeout_deadline_monotime(timeout, c->notbefore); } } channel_garbage_collect(ssh, c); } } /* * Create sockets before preparing IO. * This is necessary for things that need to happen after reading * the network-input but need to be completed before IO event setup, e.g. * because they may create new channels. */ static void channel_before_prepare_io(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; Channel *c; u_int i, oalloc; for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { c = sc->channels[i]; if (c == NULL) continue; if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN) channel_before_prepare_io_rdynamic(ssh, c); } } static void dump_channel_poll(const char *func, const char *what, Channel *c, u_int pollfd_offset, struct pollfd *pfd) { #ifdef DEBUG_CHANNEL_POLL debug3("%s: channel %d: %s r%d w%d e%d s%d c->pfds [ %d %d %d %d ] " "io_want 0x%02x io_ready 0x%02x pfd[%u].fd=%d " "pfd.ev 0x%02x pfd.rev 0x%02x", func, c->self, what, c->rfd, c->wfd, c->efd, c->sock, c->pfds[0], c->pfds[1], c->pfds[2], c->pfds[3], c->io_want, c->io_ready, pollfd_offset, pfd->fd, pfd->events, pfd->revents); #endif } /* Prepare pollfd entries for a single channel */ static void channel_prepare_pollfd(Channel *c, u_int *next_pollfd, struct pollfd *pfd, u_int npfd) { u_int ev, p = *next_pollfd; if (c == NULL) return; if (p + 4 > npfd) { /* Shouldn't happen */ fatal_f("channel %d: bad pfd offset %u (max %u)", c->self, p, npfd); } c->pfds[0] = c->pfds[1] = c->pfds[2] = c->pfds[3] = -1; /* * prepare c->rfd * * This is a special case, since c->rfd might be the same as * c->wfd, c->efd and/or c->sock. Handle those here if they want * IO too. */ if (c->rfd != -1) { ev = 0; if ((c->io_want & SSH_CHAN_IO_RFD) != 0) ev |= POLLIN; /* rfd == wfd */ if (c->wfd == c->rfd) { if ((c->io_want & SSH_CHAN_IO_WFD) != 0) ev |= POLLOUT; } /* rfd == efd */ if (c->efd == c->rfd) { if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) ev |= POLLOUT; } /* rfd == sock */ if (c->sock == c->rfd) { if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) ev |= POLLOUT; } /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[0] = p; pfd[p].fd = c->rfd; pfd[p].events = ev; dump_channel_poll(__func__, "rfd", c, p, &pfd[p]); p++; } } /* prepare c->wfd if wanting IO and not already handled above */ if (c->wfd != -1 && c->rfd != c->wfd) { ev = 0; if ((c->io_want & SSH_CHAN_IO_WFD)) ev |= POLLOUT; /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[1] = p; pfd[p].fd = c->wfd; pfd[p].events = ev; dump_channel_poll(__func__, "wfd", c, p, &pfd[p]); p++; } } /* prepare c->efd if wanting IO and not already handled above */ if (c->efd != -1 && c->rfd != c->efd) { ev = 0; if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) ev |= POLLOUT; /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[2] = p; pfd[p].fd = c->efd; pfd[p].events = ev; dump_channel_poll(__func__, "efd", c, p, &pfd[p]); p++; } } /* prepare c->sock if wanting IO and not already handled above */ if (c->sock != -1 && c->rfd != c->sock) { ev = 0; if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) ev |= POLLOUT; /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[3] = p; pfd[p].fd = c->sock; pfd[p].events = 0; dump_channel_poll(__func__, "sock", c, p, &pfd[p]); p++; } } *next_pollfd = p; } /* * Allocate/prepare poll structure */ void channel_prepare_poll(struct ssh *ssh, struct pollfd **pfdp, u_int *npfd_allocp, u_int *npfd_activep, u_int npfd_reserved, struct timespec *timeout) { struct ssh_channels *sc = ssh->chanctxt; u_int i, oalloc, p, npfd = npfd_reserved; channel_before_prepare_io(ssh); /* might create a new channel */ /* clear out I/O flags from last poll */ for (i = 0; i < sc->channels_alloc; i++) { if (sc->channels[i] == NULL) continue; sc->channels[i]->io_want = sc->channels[i]->io_ready = 0; } /* Allocate 4x pollfd for each channel (rfd, wfd, efd, sock) */ if (sc->channels_alloc >= (INT_MAX / 4) - npfd_reserved) fatal_f("too many channels"); /* shouldn't happen */ npfd += sc->channels_alloc * 4; if (npfd > *npfd_allocp) { *pfdp = xrecallocarray(*pfdp, *npfd_allocp, npfd, sizeof(**pfdp)); *npfd_allocp = npfd; } *npfd_activep = npfd_reserved; oalloc = sc->channels_alloc; channel_handler(ssh, CHAN_PRE, timeout); if (oalloc != sc->channels_alloc) { /* shouldn't happen */ fatal_f("channels_alloc changed during CHAN_PRE " "(was %u, now %u)", oalloc, sc->channels_alloc); } /* Prepare pollfd */ p = npfd_reserved; for (i = 0; i < sc->channels_alloc; i++) channel_prepare_pollfd(sc->channels[i], &p, *pfdp, npfd); *npfd_activep = p; } static void fd_ready(Channel *c, int p, struct pollfd *pfds, u_int npfd, int fd, const char *what, u_int revents_mask, u_int ready) { struct pollfd *pfd = &pfds[p]; if (fd == -1) return; if (p == -1 || (u_int)p >= npfd) fatal_f("channel %d: bad pfd %d (max %u)", c->self, p, npfd); dump_channel_poll(__func__, what, c, p, pfd); if (pfd->fd != fd) { fatal("channel %d: inconsistent %s fd=%d pollfd[%u].fd %d " "r%d w%d e%d s%d", c->self, what, fd, p, pfd->fd, c->rfd, c->wfd, c->efd, c->sock); } if ((pfd->revents & POLLNVAL) != 0) { fatal("channel %d: invalid %s pollfd[%u].fd %d r%d w%d e%d s%d", c->self, what, p, pfd->fd, c->rfd, c->wfd, c->efd, c->sock); } if ((pfd->revents & (revents_mask|POLLHUP|POLLERR)) != 0) c->io_ready |= ready & c->io_want; } /* * After poll, perform any appropriate operations for channels which have * events pending. */ void channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd) { struct ssh_channels *sc = ssh->chanctxt; u_int i; int p; Channel *c; #ifdef DEBUG_CHANNEL_POLL for (p = 0; p < (int)npfd; p++) { if (pfd[p].revents == 0) continue; debug_f("pfd[%u].fd %d rev 0x%04x", p, pfd[p].fd, pfd[p].revents); } #endif /* Convert pollfd into c->io_ready */ for (i = 0; i < sc->channels_alloc; i++) { c = sc->channels[i]; if (c == NULL) continue; /* if rfd is shared with efd/sock then wfd should be too */ if (c->rfd != -1 && c->wfd != -1 && c->rfd != c->wfd && (c->rfd == c->efd || c->rfd == c->sock)) { /* Shouldn't happen */ fatal_f("channel %d: unexpected fds r%d w%d e%d s%d", c->self, c->rfd, c->wfd, c->efd, c->sock); } c->io_ready = 0; /* rfd, potentially shared with wfd, efd and sock */ if (c->rfd != -1 && (p = c->pfds[0]) != -1) { fd_ready(c, p, pfd, npfd, c->rfd, "rfd", POLLIN, SSH_CHAN_IO_RFD); if (c->rfd == c->wfd) { fd_ready(c, p, pfd, npfd, c->wfd, "wfd/r", POLLOUT, SSH_CHAN_IO_WFD); } if (c->rfd == c->efd) { fd_ready(c, p, pfd, npfd, c->efd, "efdr/r", POLLIN, SSH_CHAN_IO_EFD_R); fd_ready(c, p, pfd, npfd, c->efd, "efdw/r", POLLOUT, SSH_CHAN_IO_EFD_W); } if (c->rfd == c->sock) { fd_ready(c, p, pfd, npfd, c->sock, "sockr/r", POLLIN, SSH_CHAN_IO_SOCK_R); fd_ready(c, p, pfd, npfd, c->sock, "sockw/r", POLLOUT, SSH_CHAN_IO_SOCK_W); } dump_channel_poll(__func__, "rfd", c, p, pfd); } /* wfd */ if (c->wfd != -1 && c->wfd != c->rfd && (p = c->pfds[1]) != -1) { fd_ready(c, p, pfd, npfd, c->wfd, "wfd", POLLOUT, SSH_CHAN_IO_WFD); dump_channel_poll(__func__, "wfd", c, p, pfd); } /* efd */ if (c->efd != -1 && c->efd != c->rfd && (p = c->pfds[2]) != -1) { fd_ready(c, p, pfd, npfd, c->efd, "efdr", POLLIN, SSH_CHAN_IO_EFD_R); fd_ready(c, p, pfd, npfd, c->efd, "efdw", POLLOUT, SSH_CHAN_IO_EFD_W); dump_channel_poll(__func__, "efd", c, p, pfd); } /* sock */ if (c->sock != -1 && c->sock != c->rfd && (p = c->pfds[3]) != -1) { fd_ready(c, p, pfd, npfd, c->sock, "sockr", POLLIN, SSH_CHAN_IO_SOCK_R); fd_ready(c, p, pfd, npfd, c->sock, "sockw", POLLOUT, SSH_CHAN_IO_SOCK_W); dump_channel_poll(__func__, "sock", c, p, pfd); } } channel_handler(ssh, CHAN_POST, NULL); } /* * Enqueue data for channels with open or draining c->input. * Returns non-zero if a packet was enqueued. */ static int channel_output_poll_input_open(struct ssh *ssh, Channel *c) { size_t len, plen; const u_char *pkt; int r; if ((len = sshbuf_len(c->input)) == 0) { if (c->istate == CHAN_INPUT_WAIT_DRAIN) { /* * input-buffer is empty and read-socket shutdown: * tell peer, that we will not send more data: * send IEOF. * hack for extended data: delay EOF if EFD still * in use. */ if (CHANNEL_EFD_INPUT_ACTIVE(c)) debug2("channel %d: " "ibuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); else chan_ibuf_empty(ssh, c); } return 0; } if (!c->have_remote_id) fatal_f("channel %d: no remote id", c->self); if (c->datagram) { /* Check datagram will fit; drop if not */ if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0) fatal_fr(r, "channel %i: get datagram", c->self); /* * XXX this does tail-drop on the datagram queue which is * usually suboptimal compared to head-drop. Better to have * backpressure at read time? (i.e. read + discard) */ if (plen > c->remote_window || plen > c->remote_maxpacket) { debug("channel %d: datagram too big", c->self); return 0; } /* Enqueue it */ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_string(ssh, pkt, plen)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: send datagram", c->self); c->remote_window -= plen; return 1; } /* Enqueue packet for buffered data. */ if (len > c->remote_window) len = c->remote_window; if (len > c->remote_maxpacket) len = c->remote_maxpacket; if (len == 0) return 0; if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: send data", c->self); if ((r = sshbuf_consume(c->input, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); c->remote_window -= len; return 1; } /* * Enqueue data for channels with open c->extended in read mode. * Returns non-zero if a packet was enqueued. */ static int channel_output_poll_extended_read(struct ssh *ssh, Channel *c) { size_t len; int r; if ((len = sshbuf_len(c->extended)) == 0) return 0; debug2("channel %d: rwin %u elen %zu euse %d", c->self, c->remote_window, sshbuf_len(c->extended), c->extended_usage); if (len > c->remote_window) len = c->remote_window; if (len > c->remote_maxpacket) len = c->remote_maxpacket; if (len == 0) return 0; if (!c->have_remote_id) fatal_f("channel %d: no remote id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 || (r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: data", c->self); if ((r = sshbuf_consume(c->extended, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); c->remote_window -= len; debug2("channel %d: sent ext data %zu", c->self, len); return 1; } /* * If there is data to send to the connection, enqueue some of it now. * Returns non-zero if data was enqueued. */ int channel_output_poll(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; Channel *c; u_int i; int ret = 0; for (i = 0; i < sc->channels_alloc; i++) { c = sc->channels[i]; if (c == NULL) continue; /* * We are only interested in channels that can have buffered * incoming data. */ if (c->type != SSH_CHANNEL_OPEN) continue; if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { /* XXX is this true? */ debug3("channel %d: will not send data after close", c->self); continue; } /* Get the amount of buffered data for this channel. */ if (c->istate == CHAN_INPUT_OPEN || c->istate == CHAN_INPUT_WAIT_DRAIN) ret |= channel_output_poll_input_open(ssh, c); /* Send extended data, i.e. stderr */ if (!(c->flags & CHAN_EOF_SENT) && c->extended_usage == CHAN_EXTENDED_READ) ret |= channel_output_poll_extended_read(ssh, c); } return ret; } /* -- mux proxy support */ /* * When multiplexing channel messages for mux clients we have to deal * with downstream messages from the mux client and upstream messages * from the ssh server: * 1) Handling downstream messages is straightforward and happens * in channel_proxy_downstream(): * - We forward all messages (mostly) unmodified to the server. * - However, in order to route messages from upstream to the correct * downstream client, we have to replace the channel IDs used by the * mux clients with a unique channel ID because the mux clients might * use conflicting channel IDs. * - so we inspect and change both SSH2_MSG_CHANNEL_OPEN and * SSH2_MSG_CHANNEL_OPEN_CONFIRMATION messages, create a local * SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID * with the newly allocated channel ID. * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY * channels and processed by channel_proxy_upstream(). The local channel ID * is then translated back to the original mux client ID. * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE * messages so we can clean up SSH_CHANNEL_MUX_PROXY channels. * 4) The SSH_CHANNEL_MUX_PROXY channels also need to closed when the * downstream mux client are removed. * 5) Handling SSH2_MSG_CHANNEL_OPEN messages from the upstream server * requires more work, because they are not addressed to a specific * channel. E.g. client_request_forwarded_tcpip() needs to figure * out whether the request is addressed to the local client or a * specific downstream client based on the listen-address/port. * 6) Agent and X11-Forwarding have a similar problem and are currently * not supported as the matching session/channel cannot be identified * easily. */ /* * receive packets from downstream mux clients: * channel callback fired on read from mux client, creates * SSH_CHANNEL_MUX_PROXY channels and translates channel IDs * on channel creation. */ int channel_proxy_downstream(struct ssh *ssh, Channel *downstream) { Channel *c = NULL; struct sshbuf *original = NULL, *modified = NULL; const u_char *cp; char *ctype = NULL, *listen_host = NULL; u_char type; size_t have; int ret = -1, r; u_int id, remote_id, listen_port; /* sshbuf_dump(downstream->input, stderr); */ if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have)) != 0) { error_fr(r, "parse"); return -1; } if (have < 2) { error_f("short message"); return -1; } type = cp[1]; /* skip padlen + type */ cp += 2; have -= 2; if (ssh_packet_log_type(type)) debug3_f("channel %u: down->up: type %u", downstream->self, type); switch (type) { case SSH2_MSG_CHANNEL_OPEN: if ((original = sshbuf_from(cp, have)) == NULL || (modified = sshbuf_new()) == NULL) { error_f("alloc"); goto out; } if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 || (r = sshbuf_get_u32(original, &id)) != 0) { error_fr(r, "parse"); goto out; } c = channel_new(ssh, "mux-proxy", SSH_CHANNEL_MUX_PROXY, -1, -1, -1, 0, 0, 0, ctype, 1); c->mux_ctx = downstream; /* point to mux client */ c->mux_downstream_id = id; /* original downstream id */ if ((r = sshbuf_put_cstring(modified, ctype)) != 0 || (r = sshbuf_put_u32(modified, c->self)) != 0 || (r = sshbuf_putb(modified, original)) != 0) { error_fr(r, "compose"); channel_free(ssh, c); goto out; } break; case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: /* * Almost the same as SSH2_MSG_CHANNEL_OPEN, except then we * need to parse 'remote_id' instead of 'ctype'. */ if ((original = sshbuf_from(cp, have)) == NULL || (modified = sshbuf_new()) == NULL) { error_f("alloc"); goto out; } if ((r = sshbuf_get_u32(original, &remote_id)) != 0 || (r = sshbuf_get_u32(original, &id)) != 0) { error_fr(r, "parse"); goto out; } c = channel_new(ssh, "mux-proxy", SSH_CHANNEL_MUX_PROXY, -1, -1, -1, 0, 0, 0, "mux-down-connect", 1); c->mux_ctx = downstream; /* point to mux client */ c->mux_downstream_id = id; c->remote_id = remote_id; c->have_remote_id = 1; if ((r = sshbuf_put_u32(modified, remote_id)) != 0 || (r = sshbuf_put_u32(modified, c->self)) != 0 || (r = sshbuf_putb(modified, original)) != 0) { error_fr(r, "compose"); channel_free(ssh, c); goto out; } break; case SSH2_MSG_GLOBAL_REQUEST: if ((original = sshbuf_from(cp, have)) == NULL) { error_f("alloc"); goto out; } if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) { error_fr(r, "parse"); goto out; } if (strcmp(ctype, "tcpip-forward") != 0) { error_f("unsupported request %s", ctype); goto out; } if ((r = sshbuf_get_u8(original, NULL)) != 0 || (r = sshbuf_get_cstring(original, &listen_host, NULL)) != 0 || (r = sshbuf_get_u32(original, &listen_port)) != 0) { error_fr(r, "parse"); goto out; } if (listen_port > 65535) { error_f("tcpip-forward for %s: bad port %u", listen_host, listen_port); goto out; } /* Record that connection to this host/port is permitted. */ permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "", -1, listen_host, NULL, (int)listen_port, downstream); break; case SSH2_MSG_CHANNEL_CLOSE: if (have < 4) break; remote_id = PEEK_U32(cp); if ((c = channel_by_remote_id(ssh, remote_id)) != NULL) { if (c->flags & CHAN_CLOSE_RCVD) channel_free(ssh, c); else c->flags |= CHAN_CLOSE_SENT; } break; } if (modified) { if ((r = sshpkt_start(ssh, type)) != 0 || (r = sshpkt_putb(ssh, modified)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_fr(r, "send"); goto out; } } else { if ((r = sshpkt_start(ssh, type)) != 0 || (r = sshpkt_put(ssh, cp, have)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_fr(r, "send"); goto out; } } ret = 0; out: free(ctype); free(listen_host); sshbuf_free(original); sshbuf_free(modified); return ret; } /* * receive packets from upstream server and de-multiplex packets * to correct downstream: * implemented as a helper for channel input handlers, * replaces local (proxy) channel ID with downstream channel ID. */ int channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) { struct sshbuf *b = NULL; Channel *downstream; const u_char *cp = NULL; size_t len; int r; /* * When receiving packets from the peer we need to check whether we * need to forward the packets to the mux client. In this case we * restore the original channel id and keep track of CLOSE messages, * so we can cleanup the channel. */ if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY) return 0; if ((downstream = c->mux_ctx) == NULL) return 0; switch (type) { case SSH2_MSG_CHANNEL_CLOSE: case SSH2_MSG_CHANNEL_DATA: case SSH2_MSG_CHANNEL_EOF: case SSH2_MSG_CHANNEL_EXTENDED_DATA: case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: case SSH2_MSG_CHANNEL_OPEN_FAILURE: case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_SUCCESS: case SSH2_MSG_CHANNEL_FAILURE: case SSH2_MSG_CHANNEL_REQUEST: break; default: debug2_f("channel %u: unsupported type %u", c->self, type); return 0; } if ((b = sshbuf_new()) == NULL) { error_f("alloc reply"); goto out; } /* get remaining payload (after id) */ cp = sshpkt_ptr(ssh, &len); if (cp == NULL) { error_f("no packet"); goto out; } /* translate id and send to muxclient */ if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */ (r = sshbuf_put_u8(b, type)) != 0 || (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 || (r = sshbuf_put(b, cp, len)) != 0 || (r = sshbuf_put_stringb(downstream->output, b)) != 0) { error_fr(r, "compose muxclient"); goto out; } /* sshbuf_dump(b, stderr); */ if (ssh_packet_log_type(type)) debug3_f("channel %u: up->down: type %u", c->self, type); out: /* update state */ switch (type) { case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: /* record remote_id for SSH2_MSG_CHANNEL_CLOSE */ if (cp && len > 4) { c->remote_id = PEEK_U32(cp); c->have_remote_id = 1; } break; case SSH2_MSG_CHANNEL_CLOSE: if (c->flags & CHAN_CLOSE_SENT) channel_free(ssh, c); else c->flags |= CHAN_CLOSE_RCVD; break; } sshbuf_free(b); return 1; } /* -- protocol input */ /* Parse a channel ID from the current packet */ static int channel_parse_id(struct ssh *ssh, const char *where, const char *what) { u_int32_t id; int r; if ((r = sshpkt_get_u32(ssh, &id)) != 0) { error_r(r, "%s: parse id", where); ssh_packet_disconnect(ssh, "Invalid %s message", what); } if (id > INT_MAX) { error_r(r, "%s: bad channel id %u", where, id); ssh_packet_disconnect(ssh, "Invalid %s channel id", what); } return (int)id; } /* Lookup a channel from an ID in the current packet */ static Channel * channel_from_packet_id(struct ssh *ssh, const char *where, const char *what) { int id = channel_parse_id(ssh, where, what); Channel *c; if ((c = channel_lookup(ssh, id)) == NULL) { ssh_packet_disconnect(ssh, "%s packet referred to nonexistent channel %d", what, id); } return c; } int channel_input_data(int type, u_int32_t seq, struct ssh *ssh) { const u_char *data; size_t data_len, win_len; Channel *c = channel_from_packet_id(ssh, __func__, "data"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; /* Ignore any data for non-open channels (might happen on close) */ if (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_RDYNAMIC_OPEN && c->type != SSH_CHANNEL_RDYNAMIC_FINISH && c->type != SSH_CHANNEL_X11_OPEN) return 0; /* Get the data. */ if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "channel %i: get data", c->self); win_len = data_len; if (c->datagram) win_len += 4; /* string length header */ /* * The sending side reduces its window as it sends data, so we * must 'fake' consumption of the data in order to ensure that window * updates are sent back. Otherwise the connection might deadlock. */ if (c->ostate != CHAN_OUTPUT_OPEN) { c->local_window -= win_len; c->local_consumed += win_len; return 0; } if (win_len > c->local_maxpacket) { logit("channel %d: rcvd big packet %zu, maxpack %u", c->self, win_len, c->local_maxpacket); return 0; } if (win_len > c->local_window) { c->local_window_exceeded += win_len - c->local_window; logit("channel %d: rcvd too much data %zu, win %u/%u " "(excess %u)", c->self, win_len, c->local_window, c->local_window_max, c->local_window_exceeded); c->local_window = 0; /* Allow 10% grace before bringing the hammer down */ if (c->local_window_exceeded > (c->local_window_max / 10)) { ssh_packet_disconnect(ssh, "channel %d: peer ignored " "channel window", c->self); } } else { c->local_window -= win_len; c->local_window_exceeded = 0; } if (c->datagram) { if ((r = sshbuf_put_string(c->output, data, data_len)) != 0) fatal_fr(r, "channel %i: append datagram", c->self); } else if ((r = sshbuf_put(c->output, data, data_len)) != 0) fatal_fr(r, "channel %i: append data", c->self); return 0; } int channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) { const u_char *data; size_t data_len; u_int32_t tcode; Channel *c = channel_from_packet_id(ssh, __func__, "extended data"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPEN) { logit("channel %d: ext data for non open", c->self); return 0; } if (c->flags & CHAN_EOF_RCVD) { if (ssh->compat & SSH_BUG_EXTEOF) debug("channel %d: accepting ext data after eof", c->self); else ssh_packet_disconnect(ssh, "Received extended_data " "after EOF on channel %d.", c->self); } if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) { error_fr(r, "parse tcode"); ssh_packet_disconnect(ssh, "Invalid extended_data message"); } if (c->efd == -1 || c->extended_usage != CHAN_EXTENDED_WRITE || tcode != SSH2_EXTENDED_DATA_STDERR) { logit("channel %d: bad ext data", c->self); return 0; } if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid extended_data message"); } if (data_len > c->local_window) { logit("channel %d: rcvd too much extended_data %zu, win %u", c->self, data_len, c->local_window); return 0; } debug2("channel %d: rcvd ext data %zu", c->self, data_len); /* XXX sshpkt_getb? */ if ((r = sshbuf_put(c->extended, data, data_len)) != 0) error_fr(r, "append"); c->local_window -= data_len; return 0; } int channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); int r; if ((r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid ieof message"); } if (channel_proxy_upstream(c, type, seq, ssh)) return 0; chan_rcvd_ieof(ssh, c); /* XXX force input close */ if (c->force_drain && c->istate == CHAN_INPUT_OPEN) { debug("channel %d: FORCE input drain", c->self); c->istate = CHAN_INPUT_WAIT_DRAIN; if (sshbuf_len(c->input) == 0) chan_ibuf_empty(ssh, c); } return 0; } int channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid oclose message"); } chan_rcvd_oclose(ssh, c); return 0; } int channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation"); u_int32_t remote_window, remote_maxpacket; int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) ssh_packet_disconnect(ssh, "Received open confirmation for " "non-opening channel %d.", c->self); /* * Record the remote channel number and mark that the channel * is now open. */ if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 || (r = sshpkt_get_u32(ssh, &remote_window)) != 0 || (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "window/maxpacket"); ssh_packet_disconnect(ssh, "Invalid open confirmation message"); } c->have_remote_id = 1; c->remote_window = remote_window; c->remote_maxpacket = remote_maxpacket; c->type = SSH_CHANNEL_OPEN; if (c->open_confirm) { debug2_f("channel %d: callback start", c->self); c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); debug2_f("channel %d: callback done", c->self); } channel_set_used_time(ssh, c); debug2("channel %d: open confirm rwindow %u rmax %u", c->self, c->remote_window, c->remote_maxpacket); return 0; } static char * reason2txt(int reason) { switch (reason) { case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED: return "administratively prohibited"; case SSH2_OPEN_CONNECT_FAILED: return "connect failed"; case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE: return "unknown channel type"; case SSH2_OPEN_RESOURCE_SHORTAGE: return "resource shortage"; } return "unknown reason"; } int channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "open failure"); u_int32_t reason; char *msg = NULL; int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) ssh_packet_disconnect(ssh, "Received open failure for " "non-opening channel %d.", c->self); if ((r = sshpkt_get_u32(ssh, &reason)) != 0) { error_fr(r, "parse reason"); ssh_packet_disconnect(ssh, "Invalid open failure message"); } /* skip language */ if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || (r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse msg/lang"); ssh_packet_disconnect(ssh, "Invalid open failure message"); } logit("channel %d: open failed: %s%s%s", c->self, reason2txt(reason), msg ? ": ": "", msg ? msg : ""); free(msg); if (c->open_confirm) { debug2_f("channel %d: callback start", c->self); c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx); debug2_f("channel %d: callback done", c->self); } /* Schedule the channel for cleanup/deletion. */ chan_mark_dead(ssh, c); return 0; } int channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) { int id = channel_parse_id(ssh, __func__, "window adjust"); Channel *c; u_int32_t adjust; u_int new_rwin; int r; if ((c = channel_lookup(ssh, id)) == NULL) { logit("Received window adjust for non-open channel %d.", id); return 0; } if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse adjust"); ssh_packet_disconnect(ssh, "Invalid window adjust message"); } debug2("channel %d: rcvd adjust %u", c->self, adjust); if ((new_rwin = c->remote_window + adjust) < c->remote_window) { fatal("channel %d: adjust %u overflows remote window %u", c->self, adjust, c->remote_window); } c->remote_window = new_rwin; return 0; } int channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) { int id = channel_parse_id(ssh, __func__, "status confirm"); Channel *c; struct channel_confirm *cc; /* Reset keepalive timeout */ ssh_packet_set_alive_timeouts(ssh, 0); debug2_f("type %d id %d", type, id); if ((c = channel_lookup(ssh, id)) == NULL) { logit_f("%d: unknown", id); return 0; } if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (sshpkt_get_end(ssh) != 0) ssh_packet_disconnect(ssh, "Invalid status confirm message"); if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) return 0; cc->cb(ssh, type, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); freezero(cc, sizeof(*cc)); return 0; } /* -- tcp forwarding */ void channel_set_af(struct ssh *ssh, int af) { ssh->chanctxt->IPv4or6 = af; } /* * Determine whether or not a port forward listens to loopback, the * specified address or wildcard. On the client, a specified bind * address will always override gateway_ports. On the server, a * gateway_ports of 1 (``yes'') will override the client's specification * and force a wildcard bind, whereas a value of 2 (``clientspecified'') * will bind to whatever address the client asked for. * * Special-case listen_addrs are: * * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR * "" (empty string), "*" -> wildcard v4/v6 * "localhost" -> loopback v4/v6 * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set */ static const char * channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp, int is_client, struct ForwardOptions *fwd_opts) { const char *addr = NULL; int wildcard = 0; if (listen_addr == NULL) { /* No address specified: default to gateway_ports setting */ if (fwd_opts->gateway_ports) wildcard = 1; } else if (fwd_opts->gateway_ports || is_client) { if (((ssh->compat & SSH_OLD_FORWARD_ADDR) && strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || (!is_client && fwd_opts->gateway_ports == 1)) { wildcard = 1; /* * Notify client if they requested a specific listen * address and it was overridden. */ if (*listen_addr != '\0' && strcmp(listen_addr, "0.0.0.0") != 0 && strcmp(listen_addr, "*") != 0) { ssh_packet_send_debug(ssh, "Forwarding listen address " "\"%s\" overridden by server " "GatewayPorts", listen_addr); } } else if (strcmp(listen_addr, "localhost") != 0 || strcmp(listen_addr, "127.0.0.1") == 0 || strcmp(listen_addr, "::1") == 0) { /* * Accept explicit localhost address when * GatewayPorts=yes. The "localhost" hostname is * deliberately skipped here so it will listen on all * available local address families. */ addr = listen_addr; } } else if (strcmp(listen_addr, "127.0.0.1") == 0 || strcmp(listen_addr, "::1") == 0) { /* * If a specific IPv4/IPv6 localhost address has been * requested then accept it even if gateway_ports is in * effect. This allows the client to prefer IPv4 or IPv6. */ addr = listen_addr; } if (wildcardp != NULL) *wildcardp = wildcard; return addr; } static int channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, struct Forward *fwd, int *allocated_listen_port, struct ForwardOptions *fwd_opts) { Channel *c; int sock, r, success = 0, wildcard = 0, is_client; struct addrinfo hints, *ai, *aitop; const char *host, *addr; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; in_port_t *lport_p; is_client = (type == SSH_CHANNEL_PORT_LISTENER); if (is_client && fwd->connect_path != NULL) { host = fwd->connect_path; } else { host = (type == SSH_CHANNEL_RPORT_LISTENER) ? fwd->listen_host : fwd->connect_host; if (host == NULL) { error("No forward host name."); return 0; } if (strlen(host) >= NI_MAXHOST) { error("Forward host name too long."); return 0; } } /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard, is_client, fwd_opts); debug3_f("type %d wildcard %d addr %s", type, wildcard, (addr == NULL) ? "NULL" : addr); /* * getaddrinfo returns a loopback address if the hostname is * set to NULL and hints.ai_flags is not AI_PASSIVE */ memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_flags = wildcard ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", fwd->listen_port); if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { if (addr == NULL) { /* This really shouldn't happen */ ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s", ssh_gai_strerror(r)); } else { error_f("getaddrinfo(%.64s): %s", addr, ssh_gai_strerror(r)); } return 0; } if (allocated_listen_port != NULL) *allocated_listen_port = 0; for (ai = aitop; ai; ai = ai->ai_next) { switch (ai->ai_family) { case AF_INET: lport_p = &((struct sockaddr_in *)ai->ai_addr)-> sin_port; break; case AF_INET6: lport_p = &((struct sockaddr_in6 *)ai->ai_addr)-> sin6_port; break; default: continue; } /* * If allocating a port for -R forwards, then use the * same port for all address families. */ if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && allocated_listen_port != NULL && *allocated_listen_port > 0) *lport_p = htons(*allocated_listen_port); if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { error_f("getnameinfo failed"); continue; } /* Create a port to listen for the host. */ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { /* this is no error since kernel may not support ipv6 */ verbose("socket [%s]:%s: %.100s", ntop, strport, strerror(errno)); continue; } set_reuseaddr(sock); if (ai->ai_family == AF_INET6) sock_set_v6only(sock); debug("Local forwarding listening on %s port %s.", ntop, strport); /* Bind the socket to the address. */ if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { /* * address can be in if use ipv6 address is * already bound */ if (!ai->ai_next) error("bind [%s]:%s: %.100s", ntop, strport, strerror(errno)); else verbose("bind [%s]:%s: %.100s", ntop, strport, strerror(errno)); close(sock); continue; } /* Start listening for connections on the socket. */ if (listen(sock, SSH_LISTEN_BACKLOG) == -1) { error("listen [%s]:%s: %.100s", ntop, strport, strerror(errno)); close(sock); continue; } /* * fwd->listen_port == 0 requests a dynamically allocated port - * record what we got. */ if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && allocated_listen_port != NULL && *allocated_listen_port == 0) { *allocated_listen_port = get_local_port(sock); debug("Allocated listen port %d", *allocated_listen_port); } /* Allocate a channel number for the socket. */ c = channel_new(ssh, "port-listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "port listener", 1); c->path = xstrdup(host); c->host_port = fwd->connect_port; c->listening_addr = addr == NULL ? NULL : xstrdup(addr); if (fwd->listen_port == 0 && allocated_listen_port != NULL && !(ssh->compat & SSH_BUG_DYNAMIC_RPORT)) c->listening_port = *allocated_listen_port; else c->listening_port = fwd->listen_port; success = 1; } if (success == 0) error_f("cannot listen to port: %d", fwd->listen_port); freeaddrinfo(aitop); return success; } static int channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type, struct Forward *fwd, struct ForwardOptions *fwd_opts) { struct sockaddr_un sunaddr; const char *path; Channel *c; int port, sock; mode_t omask; switch (type) { case SSH_CHANNEL_UNIX_LISTENER: if (fwd->connect_path != NULL) { if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) { error("Local connecting path too long: %s", fwd->connect_path); return 0; } path = fwd->connect_path; port = PORT_STREAMLOCAL; } else { if (fwd->connect_host == NULL) { error("No forward host name."); return 0; } if (strlen(fwd->connect_host) >= NI_MAXHOST) { error("Forward host name too long."); return 0; } path = fwd->connect_host; port = fwd->connect_port; } break; case SSH_CHANNEL_RUNIX_LISTENER: path = fwd->listen_path; port = PORT_STREAMLOCAL; break; default: error_f("unexpected channel type %d", type); return 0; } if (fwd->listen_path == NULL) { error("No forward path name."); return 0; } if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) { error("Local listening path too long: %s", fwd->listen_path); return 0; } debug3_f("type %d path %s", type, fwd->listen_path); /* Start a Unix domain listener. */ omask = umask(fwd_opts->streamlocal_bind_mask); sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG, fwd_opts->streamlocal_bind_unlink); umask(omask); if (sock < 0) return 0; debug("Local forwarding listening on path %s.", fwd->listen_path); /* Allocate a channel number for the socket. */ c = channel_new(ssh, "unix-listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "unix listener", 1); c->path = xstrdup(path); c->host_port = port; c->listening_port = PORT_STREAMLOCAL; c->listening_addr = xstrdup(fwd->listen_path); return 1; } static int channel_cancel_rport_listener_tcpip(struct ssh *ssh, const char *host, u_short port) { u_int i; int found = 0; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) continue; if (strcmp(c->path, host) == 0 && c->listening_port == port) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } static int channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path) { u_int i; int found = 0; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER) continue; if (c->path == NULL) continue; if (strcmp(c->path, path) == 0) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } int channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd) { if (fwd->listen_path != NULL) { return channel_cancel_rport_listener_streamlocal(ssh, fwd->listen_path); } else { return channel_cancel_rport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port); } } static int channel_cancel_lport_listener_tcpip(struct ssh *ssh, const char *lhost, u_short lport, int cport, struct ForwardOptions *fwd_opts) { u_int i; int found = 0; const char *addr = channel_fwd_bind_addr(ssh, lhost, NULL, 1, fwd_opts); for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER) continue; if (c->listening_port != lport) continue; if (cport == CHANNEL_CANCEL_PORT_STATIC) { /* skip dynamic forwardings */ if (c->host_port == 0) continue; } else { if (c->host_port != cport) continue; } if ((c->listening_addr == NULL && addr != NULL) || (c->listening_addr != NULL && addr == NULL)) continue; if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } static int channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path) { u_int i; int found = 0; if (path == NULL) { error_f("no path specified."); return 0; } for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER) continue; if (c->listening_addr == NULL) continue; if (strcmp(c->listening_addr, path) == 0) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } int channel_cancel_lport_listener(struct ssh *ssh, struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) { if (fwd->listen_path != NULL) { return channel_cancel_lport_listener_streamlocal(ssh, fwd->listen_path); } else { return channel_cancel_lport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port, cport, fwd_opts); } } /* protocol local port fwd, used by ssh */ int channel_setup_local_fwd_listener(struct ssh *ssh, struct Forward *fwd, struct ForwardOptions *fwd_opts) { if (fwd->listen_path != NULL) { return channel_setup_fwd_listener_streamlocal(ssh, SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); } else { return channel_setup_fwd_listener_tcpip(ssh, SSH_CHANNEL_PORT_LISTENER, fwd, NULL, fwd_opts); } } /* Matches a remote forwarding permission against a requested forwarding */ static int remote_open_match(struct permission *allowed_open, struct Forward *fwd) { int ret; char *lhost; /* XXX add ACLs for streamlocal */ if (fwd->listen_path != NULL) return 1; if (fwd->listen_host == NULL || allowed_open->listen_host == NULL) return 0; if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT && allowed_open->listen_port != fwd->listen_port) return 0; /* Match hostnames case-insensitively */ lhost = xstrdup(fwd->listen_host); lowercase(lhost); ret = match_pattern(lhost, allowed_open->listen_host); free(lhost); return ret; } /* Checks whether a requested remote forwarding is permitted */ static int check_rfwd_permission(struct ssh *ssh, struct Forward *fwd) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->remote_perms; u_int i, permit, permit_adm = 1; struct permission *perm; /* XXX apply GatewayPorts override before checking? */ permit = pset->all_permitted; if (!permit) { for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (remote_open_match(perm, fwd)) { permit = 1; break; } } } if (pset->num_permitted_admin > 0) { permit_adm = 0; for (i = 0; i < pset->num_permitted_admin; i++) { perm = &pset->permitted_admin[i]; if (remote_open_match(perm, fwd)) { permit_adm = 1; break; } } } return permit && permit_adm; } /* protocol v2 remote port fwd, used by sshd */ int channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd, int *allocated_listen_port, struct ForwardOptions *fwd_opts) { if (!check_rfwd_permission(ssh, fwd)) { ssh_packet_send_debug(ssh, "port forwarding refused"); if (fwd->listen_path != NULL) /* XXX always allowed, see remote_open_match() */ logit("Received request from %.100s port %d to " "remote forward to path \"%.100s\", " "but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_path); else if(fwd->listen_host != NULL) logit("Received request from %.100s port %d to " "remote forward to host %.100s port %d, " "but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_host, fwd->listen_port ); else logit("Received request from %.100s port %d to remote " "forward, but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); return 0; } if (fwd->listen_path != NULL) { return channel_setup_fwd_listener_streamlocal(ssh, SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); } else { return channel_setup_fwd_listener_tcpip(ssh, SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, fwd_opts); } } /* * Translate the requested rfwd listen host to something usable for * this server. */ static const char * channel_rfwd_bind_host(const char *listen_host) { if (listen_host == NULL) { return "localhost"; } else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) { return ""; } else return listen_host; } /* * Initiate forwarding of connections to port "port" on remote host through * the secure channel to host:port from local side. * Returns handle (index) for updating the dynamic listen port with * channel_update_permission(). */ int channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) { int r, success = 0, idx = -1; const char *host_to_connect, *listen_host, *listen_path; int port_to_connect, listen_port; /* Send the forward request to the remote side. */ if (fwd->listen_path != NULL) { if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "streamlocal-forward@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "request streamlocal"); } else { if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(fwd->listen_host))) != 0 || (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "request tcpip-forward"); } /* Assume that server accepts the request */ success = 1; if (success) { /* Record that connection to this host/port is permitted. */ host_to_connect = listen_host = listen_path = NULL; port_to_connect = listen_port = 0; if (fwd->connect_path != NULL) { host_to_connect = fwd->connect_path; port_to_connect = PORT_STREAMLOCAL; } else { host_to_connect = fwd->connect_host; port_to_connect = fwd->connect_port; } if (fwd->listen_path != NULL) { listen_path = fwd->listen_path; listen_port = PORT_STREAMLOCAL; } else { listen_host = fwd->listen_host; listen_port = fwd->listen_port; } idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, host_to_connect, port_to_connect, listen_host, listen_path, listen_port, NULL); } return idx; } static int open_match(struct permission *allowed_open, const char *requestedhost, int requestedport) { if (allowed_open->host_to_connect == NULL) return 0; if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT && allowed_open->port_to_connect != requestedport) return 0; if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST) != 0 && strcmp(allowed_open->host_to_connect, requestedhost) != 0) return 0; return 1; } /* * Note that in the listen host/port case * we don't support FWD_PERMIT_ANY_PORT and * need to translate between the configured-host (listen_host) * and what we've sent to the remote server (channel_rfwd_bind_host) */ static int open_listen_match_tcpip(struct permission *allowed_open, const char *requestedhost, u_short requestedport, int translate) { const char *allowed_host; if (allowed_open->host_to_connect == NULL) return 0; if (allowed_open->listen_port != requestedport) return 0; if (!translate && allowed_open->listen_host == NULL && requestedhost == NULL) return 1; allowed_host = translate ? channel_rfwd_bind_host(allowed_open->listen_host) : allowed_open->listen_host; if (allowed_host == NULL || requestedhost == NULL || strcmp(allowed_host, requestedhost) != 0) return 0; return 1; } static int open_listen_match_streamlocal(struct permission *allowed_open, const char *requestedpath) { if (allowed_open->host_to_connect == NULL) return 0; if (allowed_open->listen_port != PORT_STREAMLOCAL) return 0; if (allowed_open->listen_path == NULL || strcmp(allowed_open->listen_path, requestedpath) != 0) return 0; return 1; } /* * Request cancellation of remote forwarding of connection host:port from * local side. */ static int channel_request_rforward_cancel_tcpip(struct ssh *ssh, const char *host, u_short port) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; int r; u_int i; struct permission *perm = NULL; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_tcpip(perm, host, port, 0)) break; perm = NULL; } if (perm == NULL) { debug_f("requested forward not found"); return -1; } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 || (r = sshpkt_put_u32(ssh, port)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send cancel"); fwd_perm_clear(perm); /* unregister */ return 0; } /* * Request cancellation of remote forwarding of Unix domain socket * path from local side. */ static int channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; int r; u_int i; struct permission *perm = NULL; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_streamlocal(perm, path)) break; perm = NULL; } if (perm == NULL) { debug_f("requested forward not found"); return -1; } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "cancel-streamlocal-forward@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, path)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send cancel"); fwd_perm_clear(perm); /* unregister */ return 0; } /* * Request cancellation of remote forwarding of a connection from local side. */ int channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd) { if (fwd->listen_path != NULL) { return channel_request_rforward_cancel_streamlocal(ssh, fwd->listen_path); } else { return channel_request_rforward_cancel_tcpip(ssh, fwd->listen_host, fwd->listen_port ? fwd->listen_port : fwd->allocated_port); } } /* * Permits opening to any host/port if permitted_user[] is empty. This is * usually called by the server, because the user could connect to any port * anyway, and the server has no way to know but to trust the client anyway. */ void channel_permit_all(struct ssh *ssh, int where) { struct permission_set *pset = permission_set_get(ssh, where); if (pset->num_permitted_user == 0) pset->all_permitted = 1; } /* * Permit the specified host/port for forwarding. */ void channel_add_permission(struct ssh *ssh, int who, int where, char *host, int port) { int local = where == FORWARD_LOCAL; struct permission_set *pset = permission_set_get(ssh, where); debug("allow %s forwarding to host %s port %d", fwd_ident(who, where), host, port); /* * Remote forwards set listen_host/port, local forwards set * host/port_to_connect. */ permission_set_add(ssh, who, where, local ? host : 0, local ? port : 0, local ? NULL : host, NULL, local ? 0 : port, NULL); pset->all_permitted = 0; } /* * Administratively disable forwarding. */ void channel_disable_admin(struct ssh *ssh, int where) { channel_clear_permission(ssh, FORWARD_ADM, where); permission_set_add(ssh, FORWARD_ADM, where, NULL, 0, NULL, NULL, 0, NULL); } /* * Clear a list of permitted opens. */ void channel_clear_permission(struct ssh *ssh, int who, int where) { struct permission **permp; u_int *npermp; permission_set_get_array(ssh, who, where, &permp, &npermp); *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp)); *npermp = 0; } /* * Update the listen port for a dynamic remote forward, after * the actual 'newport' has been allocated. If 'newport' < 0 is * passed then they entry will be invalidated. */ void channel_update_permission(struct ssh *ssh, int idx, int newport) { struct permission_set *pset = &ssh->chanctxt->local_perms; if (idx < 0 || (u_int)idx >= pset->num_permitted_user) { debug_f("index out of range: %d num_permitted_user %d", idx, pset->num_permitted_user); return; } debug("%s allowed port %d for forwarding to host %s port %d", newport > 0 ? "Updating" : "Removing", newport, pset->permitted_user[idx].host_to_connect, pset->permitted_user[idx].port_to_connect); if (newport <= 0) fwd_perm_clear(&pset->permitted_user[idx]); else { pset->permitted_user[idx].listen_port = (ssh->compat & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; } } /* Try to start non-blocking connect to next host in cctx list */ static int connect_next(struct channel_connect *cctx) { int sock, saved_errno; struct sockaddr_un *sunaddr; char ntop[NI_MAXHOST]; char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))]; for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { switch (cctx->ai->ai_family) { case AF_UNIX: /* unix:pathname instead of host:port */ sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr; strlcpy(ntop, "unix", sizeof(ntop)); strlcpy(strport, sunaddr->sun_path, sizeof(strport)); break; case AF_INET: case AF_INET6: if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { error_f("getnameinfo failed"); continue; } break; default: continue; } debug_f("start for host %.100s ([%.100s]:%s)", cctx->host, ntop, strport); if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, cctx->ai->ai_protocol)) == -1) { if (cctx->ai->ai_next == NULL) error("socket: %.100s", strerror(errno)); else verbose("socket: %.100s", strerror(errno)); continue; } if (set_nonblock(sock) == -1) fatal_f("set_nonblock(%d)", sock); if (connect(sock, cctx->ai->ai_addr, cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) { debug_f("host %.100s ([%.100s]:%s): %.100s", cctx->host, ntop, strport, strerror(errno)); saved_errno = errno; close(sock); errno = saved_errno; continue; /* fail -- try next */ } if (cctx->ai->ai_family != AF_UNIX) set_nodelay(sock); debug_f("connect host %.100s ([%.100s]:%s) in progress, fd=%d", cctx->host, ntop, strport, sock); cctx->ai = cctx->ai->ai_next; return sock; } return -1; } static void channel_connect_ctx_free(struct channel_connect *cctx) { free(cctx->host); if (cctx->aitop) { if (cctx->aitop->ai_family == AF_UNIX) free(cctx->aitop); else freeaddrinfo(cctx->aitop); } memset(cctx, 0, sizeof(*cctx)); } /* * Return connecting socket to remote host:port or local socket path, * passing back the failure reason if appropriate. */ static int connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype, char *ctype, char *rname, struct channel_connect *cctx, int *reason, const char **errmsg) { struct addrinfo hints; int gaierr; int sock = -1; char strport[NI_MAXSERV]; if (port == PORT_STREAMLOCAL) { struct sockaddr_un *sunaddr; struct addrinfo *ai; if (strlen(name) > sizeof(sunaddr->sun_path)) { error("%.100s: %.100s", name, strerror(ENAMETOOLONG)); return -1; } /* * Fake up a struct addrinfo for AF_UNIX connections. * channel_connect_ctx_free() must check ai_family * and use free() not freeaddirinfo() for AF_UNIX. */ ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr)); memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr)); ai->ai_addr = (struct sockaddr *)(ai + 1); ai->ai_addrlen = sizeof(*sunaddr); ai->ai_family = AF_UNIX; ai->ai_socktype = socktype; ai->ai_protocol = PF_UNSPEC; sunaddr = (struct sockaddr_un *)ai->ai_addr; sunaddr->sun_family = AF_UNIX; strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path)); cctx->aitop = ai; } else { memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_socktype = socktype; snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop)) != 0) { if (errmsg != NULL) *errmsg = ssh_gai_strerror(gaierr); if (reason != NULL) *reason = SSH2_OPEN_CONNECT_FAILED; error("connect_to %.100s: unknown host (%s)", name, ssh_gai_strerror(gaierr)); return -1; } } cctx->host = xstrdup(name); cctx->port = port; cctx->ai = cctx->aitop; if ((sock = connect_next(cctx)) == -1) { error("connect to %.100s port %d failed: %s", name, port, strerror(errno)); return -1; } return sock; } /* Return CONNECTING channel to remote host:port or local socket path */ static Channel * connect_to(struct ssh *ssh, const char *host, int port, char *ctype, char *rname) { struct channel_connect cctx; Channel *c; int sock; memset(&cctx, 0, sizeof(cctx)); sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, &cctx, NULL, NULL); if (sock == -1) { channel_connect_ctx_free(&cctx); return NULL; } c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); c->host_port = port; c->path = xstrdup(host); c->connect_ctx = cctx; return c; } /* * returns either the newly connected channel or the downstream channel * that needs to deal with this connection. */ Channel * channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host, u_short listen_port, char *ctype, char *rname) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; u_int i; struct permission *perm; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_tcpip(perm, listen_host, listen_port, 1)) { if (perm->downstream) return perm->downstream; if (perm->port_to_connect == 0) return rdynamic_connect_prepare(ssh, ctype, rname); return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); } } error("WARNING: Server requests forwarding for unknown listen_port %d", listen_port); return NULL; } Channel * channel_connect_by_listen_path(struct ssh *ssh, const char *path, char *ctype, char *rname) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; u_int i; struct permission *perm; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_streamlocal(perm, path)) { return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); } } error("WARNING: Server requests forwarding for unknown path %.100s", path); return NULL; } /* Check if connecting to that port is permitted and connect. */ Channel * channel_connect_to_port(struct ssh *ssh, const char *host, u_short port, char *ctype, char *rname, int *reason, const char **errmsg) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; struct channel_connect cctx; Channel *c; u_int i, permit, permit_adm = 1; int sock; struct permission *perm; permit = pset->all_permitted; if (!permit) { for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_match(perm, host, port)) { permit = 1; break; } } } if (pset->num_permitted_admin > 0) { permit_adm = 0; for (i = 0; i < pset->num_permitted_admin; i++) { perm = &pset->permitted_admin[i]; if (open_match(perm, host, port)) { permit_adm = 1; break; } } } if (!permit || !permit_adm) { logit("Received request from %.100s port %d to connect to " "host %.100s port %d, but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), host, port); if (reason != NULL) *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; return NULL; } memset(&cctx, 0, sizeof(cctx)); sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, &cctx, reason, errmsg); if (sock == -1) { channel_connect_ctx_free(&cctx); return NULL; } c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); c->host_port = port; c->path = xstrdup(host); c->connect_ctx = cctx; return c; } /* Check if connecting to that path is permitted and connect. */ Channel * channel_connect_to_path(struct ssh *ssh, const char *path, char *ctype, char *rname) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; u_int i, permit, permit_adm = 1; struct permission *perm; permit = pset->all_permitted; if (!permit) { for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_match(perm, path, PORT_STREAMLOCAL)) { permit = 1; break; } } } if (pset->num_permitted_admin > 0) { permit_adm = 0; for (i = 0; i < pset->num_permitted_admin; i++) { perm = &pset->permitted_admin[i]; if (open_match(perm, path, PORT_STREAMLOCAL)) { permit_adm = 1; break; } } } if (!permit || !permit_adm) { logit("Received request to connect to path %.100s, " "but the request was denied.", path); return NULL; } return connect_to(ssh, path, PORT_STREAMLOCAL, ctype, rname); } void channel_send_window_changes(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; struct winsize ws; int r; u_int i; for (i = 0; i < sc->channels_alloc; i++) { if (sc->channels[i] == NULL || !sc->channels[i]->client_tty || sc->channels[i]->type != SSH_CHANNEL_OPEN) continue; if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ, &ws) == -1) continue; channel_request_start(ssh, i, "window-change", 0); if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %u; send window-change", i); } } /* Return RDYNAMIC_OPEN channel: channel allows SOCKS, but is not connected */ static Channel * rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname) { Channel *c; int r; c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN, -1, -1, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); c->host_port = 0; c->path = NULL; /* * We need to open the channel before we have a FD, * so that we can get SOCKS header from peer. */ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) fatal_fr(r, "channel %i; confirm", c->self); return c; } /* Return CONNECTING socket to remote host:port or local socket path */ static int rdynamic_connect_finish(struct ssh *ssh, Channel *c) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; struct permission *perm; struct channel_connect cctx; u_int i, permit_adm = 1; int sock; if (pset->num_permitted_admin > 0) { permit_adm = 0; for (i = 0; i < pset->num_permitted_admin; i++) { perm = &pset->permitted_admin[i]; if (open_match(perm, c->path, c->host_port)) { permit_adm = 1; break; } } } if (!permit_adm) { debug_f("requested forward not permitted"); return -1; } memset(&cctx, 0, sizeof(cctx)); sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL, NULL, &cctx, NULL, NULL); if (sock == -1) channel_connect_ctx_free(&cctx); else { /* similar to SSH_CHANNEL_CONNECTING but we've already sent the open */ c->type = SSH_CHANNEL_RDYNAMIC_FINISH; c->connect_ctx = cctx; channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0); } return sock; } /* -- X11 forwarding */ /* * Creates an internet domain socket for listening for X11 connections. * Returns 0 and a suitable display number for the DISPLAY variable * stored in display_numberp , or -1 if an error occurs. */ int x11_create_display_inet(struct ssh *ssh, int x11_display_offset, int x11_use_localhost, int single_connection, u_int *display_numberp, int **chanids) { Channel *nc = NULL; int display_number, sock, port; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr, n, num_socks = 0, socks[NUM_SOCKS]; if (chanids == NULL || x11_display_offset < 0 || x11_display_offset > UINT16_MAX - X11_BASE_PORT - MAX_DISPLAYS) return -1; for (display_number = x11_display_offset; display_number < MAX_DISPLAYS; display_number++) { port = X11_BASE_PORT + display_number; memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr)); return -1; } for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { if ((errno != EINVAL) && (errno != EAFNOSUPPORT) #ifdef EPFNOSUPPORT && (errno != EPFNOSUPPORT) #endif ) { error("socket: %.100s", strerror(errno)); freeaddrinfo(aitop); return -1; } else { debug("x11_create_display_inet: Socket family %d not supported", ai->ai_family); continue; } } if (ai->ai_family == AF_INET6) sock_set_v6only(sock); if (x11_use_localhost) set_reuseaddr(sock); if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { debug2_f("bind port %d: %.100s", port, strerror(errno)); close(sock); for (n = 0; n < num_socks; n++) close(socks[n]); num_socks = 0; break; } socks[num_socks++] = sock; if (num_socks == NUM_SOCKS) break; } freeaddrinfo(aitop); if (num_socks > 0) break; } if (display_number >= MAX_DISPLAYS) { error("Failed to allocate internet-domain X11 display socket."); return -1; } /* Start listening for connections on the socket. */ for (n = 0; n < num_socks; n++) { sock = socks[n]; if (listen(sock, SSH_LISTEN_BACKLOG) == -1) { error("listen: %.100s", strerror(errno)); close(sock); return -1; } } /* Allocate a channel for each socket. */ *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); for (n = 0; n < num_socks; n++) { sock = socks[n]; nc = channel_new(ssh, "x11-listener", SSH_CHANNEL_X11_LISTENER, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "X11 inet listener", 1); nc->single_connection = single_connection; (*chanids)[n] = nc->self; } (*chanids)[n] = -1; /* Return the display number for the DISPLAY environment variable. */ *display_numberp = display_number; return 0; } static int connect_local_xsocket_path(const char *pathname) { int sock; struct sockaddr_un addr; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { error("socket: %.100s", strerror(errno)); return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) return sock; close(sock); error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); return -1; } static int connect_local_xsocket(u_int dnr) { char buf[1024]; snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr); return connect_local_xsocket_path(buf); } #ifdef __APPLE__ static int is_path_to_xsocket(const char *display, char *path, size_t pathlen) { struct stat sbuf; if (strlcpy(path, display, pathlen) >= pathlen) { error("%s: display path too long", __func__); return 0; } if (display[0] != '/') return 0; if (stat(path, &sbuf) == 0) { return 1; } else { char *dot = strrchr(path, '.'); if (dot != NULL) { *dot = '\0'; if (stat(path, &sbuf) == 0) { return 1; } } } return 0; } #endif int x11_connect_display(struct ssh *ssh) { u_int display_number; const char *display; char buf[1024], *cp; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr, sock = 0; /* Try to open a socket for the local X server. */ display = getenv("DISPLAY"); if (!display) { error("DISPLAY not set."); return -1; } /* * Now we decode the value of the DISPLAY variable and make a * connection to the real X server. */ #ifdef __APPLE__ /* Check if display is a path to a socket (as set by launchd). */ { char path[PATH_MAX]; if (is_path_to_xsocket(display, path, sizeof(path))) { debug("x11_connect_display: $DISPLAY is launchd"); /* Create a socket. */ sock = connect_local_xsocket_path(path); if (sock < 0) return -1; /* OK, we now have a connection to the display. */ return sock; } } #endif /* * Check if it is a unix domain socket. Unix domain displays are in * one of the following formats: unix:d[.s], :d[.s], ::d[.s] */ if (strncmp(display, "unix:", 5) == 0 || display[0] == ':') { /* Connect to the unix domain socket. */ if (sscanf(strrchr(display, ':') + 1, "%u", &display_number) != 1) { error("Could not parse display number from DISPLAY: " "%.100s", display); return -1; } /* Create a socket. */ sock = connect_local_xsocket(display_number); if (sock < 0) return -1; /* OK, we now have a connection to the display. */ return sock; } /* * Connect to an inet socket. The DISPLAY value is supposedly * hostname:d[.s], where hostname may also be numeric IP address. */ strlcpy(buf, display, sizeof(buf)); cp = strchr(buf, ':'); if (!cp) { error("Could not find ':' in DISPLAY: %.100s", display); return -1; } *cp = 0; /* * buf now contains the host name. But first we parse the * display number. */ if (sscanf(cp + 1, "%u", &display_number) != 1 || display_number > UINT16_MAX - X11_BASE_PORT) { error("Could not parse display number from DISPLAY: %.100s", display); return -1; } /* Look up the host address */ memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%u", X11_BASE_PORT + display_number); if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { error("%.100s: unknown host. (%s)", buf, ssh_gai_strerror(gaierr)); return -1; } for (ai = aitop; ai; ai = ai->ai_next) { /* Create a socket. */ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { debug2("socket: %.100s", strerror(errno)); continue; } /* Connect it to the display. */ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { debug2("connect %.100s port %u: %.100s", buf, X11_BASE_PORT + display_number, strerror(errno)); close(sock); continue; } /* Success */ break; } freeaddrinfo(aitop); if (!ai) { error("connect %.100s port %u: %.100s", buf, X11_BASE_PORT + display_number, strerror(errno)); return -1; } set_nodelay(sock); return sock; } /* * Requests forwarding of X11 connections, generates fake authentication * data, and enables authentication spoofing. * This should be called in the client only. */ void x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id, const char *disp, const char *proto, const char *data, int want_reply) { struct ssh_channels *sc = ssh->chanctxt; u_int data_len = (u_int) strlen(data) / 2; u_int i, value; const char *cp; char *new_data; int r, screen_number; if (sc->x11_saved_display == NULL) sc->x11_saved_display = xstrdup(disp); else if (strcmp(disp, sc->x11_saved_display) != 0) { error("x11_request_forwarding_with_spoofing: different " "$DISPLAY already forwarded"); return; } cp = strchr(disp, ':'); if (cp) cp = strchr(cp, '.'); if (cp) screen_number = (u_int)strtonum(cp + 1, 0, 400, NULL); else screen_number = 0; if (sc->x11_saved_proto == NULL) { /* Save protocol name. */ sc->x11_saved_proto = xstrdup(proto); /* Extract real authentication data. */ sc->x11_saved_data = xmalloc(data_len); for (i = 0; i < data_len; i++) { if (sscanf(data + 2 * i, "%2x", &value) != 1) { fatal("x11_request_forwarding: bad " "authentication data: %.100s", data); } sc->x11_saved_data[i] = value; } sc->x11_saved_data_len = data_len; /* Generate fake data of the same length. */ sc->x11_fake_data = xmalloc(data_len); arc4random_buf(sc->x11_fake_data, data_len); sc->x11_fake_data_len = data_len; } /* Convert the fake data into hex. */ new_data = tohex(sc->x11_fake_data, data_len); /* Send the request packet. */ channel_request_start(ssh, client_session_id, "x11-req", want_reply); if ((r = sshpkt_put_u8(ssh, 0)) != 0 || /* bool: single connection */ (r = sshpkt_put_cstring(ssh, proto)) != 0 || (r = sshpkt_put_cstring(ssh, new_data)) != 0 || (r = sshpkt_put_u32(ssh, screen_number)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send x11-req"); free(new_data); } /* * Returns whether an x11 channel was used recently (less than a second ago) */ int x11_channel_used_recently(struct ssh *ssh) { u_int i; Channel *c; time_t lastused = 0; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL || c->ctype == NULL || c->lastused == 0 || strcmp(c->ctype, "x11-connection") != 0) continue; lastused = c->lastused; } return lastused != 0 && monotime() > lastused + 1; } openssh-10.0p1/PaxHeaders.10889/channels.h100644 001750 001750 0000000003414775415623 0015116xustar0028 atime=1744182234.5261955 openssh-10.0p1/channels.h010064400017500001750000000361471477541562300135160ustar00djmdjm/* $OpenBSD: channels.h,v 1.158 2024/10/13 22:20:06 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CHANNEL_H #define CHANNEL_H /* Definitions for channel types. */ #define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */ #define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */ #define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */ #define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */ #define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */ #define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */ #define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */ #define SSH_CHANNEL_LARVAL 10 /* larval session */ #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ #define SSH_CHANNEL_CONNECTING 12 #define SSH_CHANNEL_DYNAMIC 13 #define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */ #define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ #define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux client */ #define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ #define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ #define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ #define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-client */ #define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */ #define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */ #define SSH_CHANNEL_MAX_TYPE 23 #define CHANNEL_CANCEL_PORT_STATIC -1 /* nonblocking flags for channel_new */ #define CHANNEL_NONBLOCK_LEAVE 0 /* don't modify non-blocking state */ #define CHANNEL_NONBLOCK_SET 1 /* set non-blocking state */ #define CHANNEL_NONBLOCK_STDIO 2 /* set non-blocking and restore on close */ /* c->restore_block mask flags */ #define CHANNEL_RESTORE_RFD 0x01 #define CHANNEL_RESTORE_WFD 0x02 #define CHANNEL_RESTORE_EFD 0x04 /* TCP forwarding */ #define FORWARD_DENY 0 #define FORWARD_REMOTE (1) #define FORWARD_LOCAL (1<<1) #define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) #define FORWARD_ADM 0x100 #define FORWARD_USER 0x101 struct ssh; struct Channel; typedef struct Channel Channel; typedef void channel_open_fn(struct ssh *, int, int, void *); typedef void channel_callback_fn(struct ssh *, int, int, void *); typedef int channel_infilter_fn(struct ssh *, struct Channel *, char *, int); typedef void channel_filter_cleanup_fn(struct ssh *, int, void *); typedef u_char *channel_outfilter_fn(struct ssh *, struct Channel *, u_char **, size_t *); /* Channel success/failure callbacks */ typedef void channel_confirm_cb(struct ssh *, int, struct Channel *, void *); typedef void channel_confirm_abandon_cb(struct ssh *, struct Channel *, void *); struct channel_confirm { TAILQ_ENTRY(channel_confirm) entry; channel_confirm_cb *cb; channel_confirm_abandon_cb *abandon_cb; void *ctx; }; TAILQ_HEAD(channel_confirms, channel_confirm); /* Context for non-blocking connects */ struct channel_connect { char *host; int port; struct addrinfo *ai, *aitop; }; /* Callbacks for mux channels back into client-specific code */ typedef int mux_callback_fn(struct ssh *, struct Channel *); /* * NB. channel IDs on the wire and in c->remote_id are uint32, but local * channel IDs (e.g. c->self) only ever use the int32 subset of this range, * because we use local channel ID -1 for housekeeping. Remote channels have * a dedicated "have_remote_id" flag to indicate their validity. */ struct Channel { int type; /* channel type/state */ int self; /* my own channel identifier */ uint32_t remote_id; /* channel identifier for remote peer */ int have_remote_id; /* non-zero if remote_id is valid */ u_int istate; /* input from channel (state of receive half) */ u_int ostate; /* output to channel (state of transmit half) */ int flags; /* close sent/rcvd */ int rfd; /* read fd */ int wfd; /* write fd */ int efd; /* extended fd */ int sock; /* sock fd */ u_int io_want; /* bitmask of SSH_CHAN_IO_* */ u_int io_ready; /* bitmask of SSH_CHAN_IO_* */ int pfds[4]; /* pollfd entries for rfd/wfd/efd/sock */ int ctl_chan; /* control channel (multiplexed connections) */ uint32_t ctl_child_id; /* child session for mux controllers */ int have_ctl_child_id;/* non-zero if ctl_child_id is valid */ int isatty; /* rfd is a tty */ #ifdef _AIX int wfd_isatty; /* wfd is a tty */ #endif int client_tty; /* (client) TTY has been requested */ int force_drain; /* force close on iEOF */ time_t notbefore; /* Pause IO until deadline (time_t) */ int delayed; /* post-IO handlers for newly created * channels are delayed until the first call * to a matching pre-IO handler. * this way post-IO handlers are not * accidentally called if a FD gets reused */ int restore_block; /* fd mask to restore blocking status */ int restore_flags[3];/* flags to restore */ struct sshbuf *input; /* data read from socket, to be sent over * encrypted connection */ struct sshbuf *output; /* data received over encrypted connection for * send on socket */ struct sshbuf *extended; char *path; /* path for unix domain sockets, or host name for forwards */ int listening_port; /* port being listened for forwards */ char *listening_addr; /* addr being listened for forwards */ int host_port; /* remote port to connect for forwards */ char *remote_name; /* remote hostname */ u_int remote_window; u_int remote_maxpacket; u_int local_window; u_int local_window_exceeded; u_int local_window_max; u_int local_consumed; u_int local_maxpacket; int extended_usage; int single_connection; char *ctype; /* const type - NB. not freed on channel_free */ char *xctype; /* extended type */ /* callback */ channel_open_fn *open_confirm; void *open_confirm_ctx; channel_callback_fn *detach_user; int detach_close; struct channel_confirms status_confirms; /* filter */ channel_infilter_fn *input_filter; channel_outfilter_fn *output_filter; void *filter_ctx; channel_filter_cleanup_fn *filter_cleanup; /* keep boundaries */ int datagram; /* non-blocking connect */ /* XXX make this a pointer so the structure can be opaque */ struct channel_connect connect_ctx; /* multiplexing protocol hook, called for each packet received */ mux_callback_fn *mux_rcb; void *mux_ctx; int mux_pause; int mux_downstream_id; /* Inactivity timeouts */ /* Last traffic seen for OPEN channels */ time_t lastused; /* Inactivity timeout deadline in seconds (0 = no timeout) */ int inactive_deadline; }; #define CHAN_EXTENDED_IGNORE 0 #define CHAN_EXTENDED_READ 1 #define CHAN_EXTENDED_WRITE 2 /* default window/packet sizes for tcp/x11-fwd-channel */ #define CHAN_SES_PACKET_DEFAULT (32*1024) #define CHAN_SES_WINDOW_DEFAULT (64*CHAN_SES_PACKET_DEFAULT) #define CHAN_TCP_PACKET_DEFAULT (32*1024) #define CHAN_TCP_WINDOW_DEFAULT (64*CHAN_TCP_PACKET_DEFAULT) #define CHAN_X11_PACKET_DEFAULT (16*1024) #define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) /* possible input states */ #define CHAN_INPUT_OPEN 0 #define CHAN_INPUT_WAIT_DRAIN 1 #define CHAN_INPUT_WAIT_OCLOSE 2 #define CHAN_INPUT_CLOSED 3 /* possible output states */ #define CHAN_OUTPUT_OPEN 0 #define CHAN_OUTPUT_WAIT_DRAIN 1 #define CHAN_OUTPUT_WAIT_IEOF 2 #define CHAN_OUTPUT_CLOSED 3 #define CHAN_CLOSE_SENT 0x01 #define CHAN_CLOSE_RCVD 0x02 #define CHAN_EOF_SENT 0x04 #define CHAN_EOF_RCVD 0x08 #define CHAN_LOCAL 0x10 /* file descriptor events */ #define SSH_CHAN_IO_RFD 0x01 #define SSH_CHAN_IO_WFD 0x02 #define SSH_CHAN_IO_EFD_R 0x04 #define SSH_CHAN_IO_EFD_W 0x08 #define SSH_CHAN_IO_EFD (SSH_CHAN_IO_EFD_R|SSH_CHAN_IO_EFD_W) #define SSH_CHAN_IO_SOCK_R 0x10 #define SSH_CHAN_IO_SOCK_W 0x20 #define SSH_CHAN_IO_SOCK (SSH_CHAN_IO_SOCK_R|SSH_CHAN_IO_SOCK_W) /* Read buffer size */ #define CHAN_RBUF (16*1024) /* Maximum size for direct reads to buffers */ #define CHANNEL_MAX_READ CHAN_SES_PACKET_DEFAULT /* Maximum channel input buffer size */ #define CHAN_INPUT_MAX (16*1024*1024) /* Hard limit on number of channels */ #define CHANNELS_MAX_CHANNELS (16*1024) /* check whether 'efd' is still in use */ #define CHANNEL_EFD_INPUT_ACTIVE(c) \ (c->extended_usage == CHAN_EXTENDED_READ && \ (c->efd != -1 || \ sshbuf_len(c->extended) > 0)) #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ (c->extended_usage == CHAN_EXTENDED_WRITE && \ c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ sshbuf_len(c->extended) > 0)) /* Add channel management structures to SSH transport instance */ void channel_init_channels(struct ssh *ssh); /* channel management */ Channel *channel_by_id(struct ssh *, int); Channel *channel_by_remote_id(struct ssh *, u_int); Channel *channel_lookup(struct ssh *, int); Channel *channel_new(struct ssh *, char *, int, int, int, int, u_int, u_int, int, const char *, int); void channel_set_fds(struct ssh *, int, int, int, int, int, int, int, u_int); void channel_free(struct ssh *, Channel *); void channel_free_all(struct ssh *); void channel_stop_listening(struct ssh *); void channel_force_close(struct ssh *, Channel *, int); void channel_set_xtype(struct ssh *, int, const char *); void channel_send_open(struct ssh *, int); void channel_request_start(struct ssh *, int, char *, int); void channel_register_cleanup(struct ssh *, int, channel_callback_fn *, int); void channel_register_open_confirm(struct ssh *, int, channel_open_fn *, void *); void channel_register_filter(struct ssh *, int, channel_infilter_fn *, channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); void channel_register_status_confirm(struct ssh *, int, channel_confirm_cb *, channel_confirm_abandon_cb *, void *); void channel_cancel_cleanup(struct ssh *, int); int channel_close_fd(struct ssh *, Channel *, int *); void channel_send_window_changes(struct ssh *); /* channel inactivity timeouts */ void channel_add_timeout(struct ssh *, const char *, int); void channel_clear_timeouts(struct ssh *); /* mux proxy support */ int channel_proxy_downstream(struct ssh *, Channel *mc); int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *); /* protocol handler */ int channel_input_data(int, u_int32_t, struct ssh *); int channel_input_extended_data(int, u_int32_t, struct ssh *); int channel_input_ieof(int, u_int32_t, struct ssh *); int channel_input_oclose(int, u_int32_t, struct ssh *); int channel_input_open_confirmation(int, u_int32_t, struct ssh *); int channel_input_open_failure(int, u_int32_t, struct ssh *); int channel_input_window_adjust(int, u_int32_t, struct ssh *); int channel_input_status_confirm(int, u_int32_t, struct ssh *); /* file descriptor handling (read/write) */ struct pollfd; struct timespec; void channel_prepare_poll(struct ssh *, struct pollfd **, u_int *, u_int *, u_int, struct timespec *); void channel_after_poll(struct ssh *, struct pollfd *, u_int); int channel_output_poll(struct ssh *); int channel_not_very_much_buffered_data(struct ssh *); void channel_close_all(struct ssh *); int channel_still_open(struct ssh *); int channel_tty_open(struct ssh *); const char *channel_format_extended_usage(const Channel *); char *channel_open_message(struct ssh *); int channel_find_open(struct ssh *); /* tcp forwarding */ struct Forward; struct ForwardOptions; void channel_set_af(struct ssh *, int af); void channel_permit_all(struct ssh *, int); void channel_add_permission(struct ssh *, int, int, char *, int); void channel_clear_permission(struct ssh *, int, int); void channel_disable_admin(struct ssh *, int); void channel_update_permission(struct ssh *, int, int); Channel *channel_connect_to_port(struct ssh *, const char *, u_short, char *, char *, int *, const char **); Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *); Channel *channel_connect_stdio_fwd(struct ssh *, const char*, int, int, int, int); Channel *channel_connect_by_listen_address(struct ssh *, const char *, u_short, char *, char *); Channel *channel_connect_by_listen_path(struct ssh *, const char *, char *, char *); int channel_request_remote_forwarding(struct ssh *, struct Forward *); int channel_setup_local_fwd_listener(struct ssh *, struct Forward *, struct ForwardOptions *); int channel_request_rforward_cancel(struct ssh *, struct Forward *); int channel_setup_remote_fwd_listener(struct ssh *, struct Forward *, int *, struct ForwardOptions *); int channel_cancel_rport_listener(struct ssh *, struct Forward *); int channel_cancel_lport_listener(struct ssh *, struct Forward *, int, struct ForwardOptions *); int permitopen_port(const char *); /* x11 forwarding */ void channel_set_x11_refuse_time(struct ssh *, time_t); int x11_connect_display(struct ssh *); int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); void x11_request_forwarding_with_spoofing(struct ssh *, int, const char *, const char *, const char *, int); int x11_channel_used_recently(struct ssh *ssh); /* channel close */ int chan_is_dead(struct ssh *, Channel *, int); void chan_mark_dead(struct ssh *, Channel *); /* channel events */ void chan_rcvd_oclose(struct ssh *, Channel *); void chan_rcvd_eow(struct ssh *, Channel *); void chan_read_failed(struct ssh *, Channel *); void chan_ibuf_empty(struct ssh *, Channel *); void chan_rcvd_ieof(struct ssh *, Channel *); void chan_write_failed(struct ssh *, Channel *); void chan_obuf_empty(struct ssh *, Channel *); #endif openssh-10.0p1/PaxHeaders.10889/cipher-aes.c100644 001750 001750 0000000003414775415623 0015336xustar0028 atime=1744182234.5261955 openssh-10.0p1/cipher-aes.c010064400017500001750000000110331477541562300137210ustar00djmdjm/* * 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" /* compatibility with old or broken OpenSSL versions */ #include "openbsd-compat/openssl-compat.h" #ifdef USE_BUILTIN_RIJNDAEL #include #include #include #include #include "rijndael.h" #include "xmalloc.h" #include "log.h" #define RIJNDAEL_BLOCKSIZE 16 struct ssh_rijndael_ctx { rijndael_ctx r_ctx; u_char r_iv[RIJNDAEL_BLOCKSIZE]; }; static int ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc) { struct ssh_rijndael_ctx *c; if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { c = xmalloc(sizeof(*c)); EVP_CIPHER_CTX_set_app_data(ctx, c); } if (key != NULL) { if (enc == -1) enc = ctx->encrypt; rijndael_set_key(&c->r_ctx, (u_char *)key, 8*EVP_CIPHER_CTX_key_length(ctx), enc); } if (iv != NULL) memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE); return (1); } static int ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len) { struct ssh_rijndael_ctx *c; u_char buf[RIJNDAEL_BLOCKSIZE]; u_char *cprev, *cnow, *plain, *ivp; int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; if (len == 0) return (1); if (len % RIJNDAEL_BLOCKSIZE) fatal("ssh_rijndael_cbc: bad len %d", len); if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { error("ssh_rijndael_cbc: no context"); return (0); } if (ctx->encrypt) { cnow = dest; plain = (u_char *)src; cprev = c->r_iv; for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, cnow+=RIJNDAEL_BLOCKSIZE) { for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) buf[j] = plain[j] ^ cprev[j]; rijndael_encrypt(&c->r_ctx, buf, cnow); cprev = cnow; } memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE); } else { cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); plain = dest+len-RIJNDAEL_BLOCKSIZE; memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE); for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE, plain-=RIJNDAEL_BLOCKSIZE) { rijndael_decrypt(&c->r_ctx, cnow, plain); ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE; for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) plain[j] ^= ivp[j]; } memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE); } return (1); } static int ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) { struct ssh_rijndael_ctx *c; if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { memset(c, 0, sizeof(*c)); free(c); EVP_CIPHER_CTX_set_app_data(ctx, NULL); } return (1); } void ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) { struct ssh_rijndael_ctx *c; if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) fatal("ssh_rijndael_iv: no context"); if (doset) memcpy(c->r_iv, iv, len); else memcpy(iv, c->r_iv, len); } const EVP_CIPHER * evp_rijndael(void) { static EVP_CIPHER rijndal_cbc; memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER)); rijndal_cbc.nid = NID_undef; rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE; rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE; rijndal_cbc.key_len = 16; rijndal_cbc.init = ssh_rijndael_init; rijndal_cbc.cleanup = ssh_rijndael_cleanup; rijndal_cbc.do_cipher = ssh_rijndael_cbc; #ifndef SSH_OLD_EVP rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; #endif return (&rijndal_cbc); } #endif /* USE_BUILTIN_RIJNDAEL */ openssh-10.0p1/PaxHeaders.10889/cipher-aesctr.c100644 001750 001750 0000000003414775415623 0016047xustar0028 atime=1744182234.5261955 openssh-10.0p1/cipher-aesctr.c010064400017500001750000000040741477541562300144410ustar00djmdjm/* $OpenBSD: cipher-aesctr.c,v 1.2 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. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #ifndef WITH_OPENSSL #include "cipher-aesctr.h" /* * increment counter 'ctr', * the counter is of size 'len' bytes and stored in network-byte-order. * (LSB at ctr[len-1], MSB at ctr[0]) */ static inline void aesctr_inc(u8 *ctr, u32 len) { ssize_t i; #ifndef CONSTANT_TIME_INCREMENT for (i = len - 1; i >= 0; i--) if (++ctr[i]) /* continue on overflow */ return; #else u8 x, add = 1; for (i = len - 1; i >= 0; i--) { ctr[i] += add; /* constant time for: x = ctr[i] ? 1 : 0 */ x = ctr[i]; x = (x | (x >> 4)) & 0xf; x = (x | (x >> 2)) & 0x3; x = (x | (x >> 1)) & 0x1; add *= (x^1); } #endif } void aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits) { x->rounds = rijndaelKeySetupEnc(x->ek, k, kbits); } void aesctr_ivsetup(aesctr_ctx *x,const u8 *iv) { memcpy(x->ctr, iv, AES_BLOCK_SIZE); } void aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes) { u32 n = 0; u8 buf[AES_BLOCK_SIZE]; while ((bytes--) > 0) { if (n == 0) { rijndaelEncrypt(x->ek, x->rounds, x->ctr, buf); aesctr_inc(x->ctr, AES_BLOCK_SIZE); } *(c++) = *(m++) ^ buf[n]; n = (n + 1) % AES_BLOCK_SIZE; } } #endif /* !WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/cipher-aesctr.h100644 001750 001750 0000000003414775415623 0016054xustar0028 atime=1744182234.5261955 openssh-10.0p1/cipher-aesctr.h010064400017500001750000000024631477541562300144460ustar00djmdjm/* $OpenBSD: cipher-aesctr.h,v 1.1 2014/04/29 15:39:33 markus Exp $ */ /* * Copyright (c) 2014 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. */ #ifndef OPENSSH_AESCTR_H #define OPENSSH_AESCTR_H #include "rijndael.h" #define AES_BLOCK_SIZE 16 typedef struct aesctr_ctx { int rounds; /* keylen-dependent #rounds */ u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ u8 ctr[AES_BLOCK_SIZE]; /* counter */ } aesctr_ctx; void aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits); void aesctr_ivsetup(aesctr_ctx *x,const u8 *iv); void aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes); #endif openssh-10.0p1/PaxHeaders.10889/cipher-chachapoly-libcrypto.c100644 001750 001750 0000000003614775415623 0020710xustar0030 atime=1744182234.527171727 openssh-10.0p1/cipher-chachapoly-libcrypto.c010064400017500001750000000116511477541562300172770ustar00djmdjm/* $OpenBSD: cipher-chachapoly-libcrypto.c,v 1.2 2023/07/17 05:26:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef WITH_OPENSSL #include "openbsd-compat/openssl-compat.h" #endif #if defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20) #include #include /* needed for log.h */ #include #include /* needed for misc.h */ #include #include "log.h" #include "sshbuf.h" #include "ssherr.h" #include "cipher-chachapoly.h" struct chachapoly_ctx { EVP_CIPHER_CTX *main_evp, *header_evp; }; struct chachapoly_ctx * chachapoly_new(const u_char *key, u_int keylen) { struct chachapoly_ctx *ctx; if (keylen != (32 + 32)) /* 2 x 256 bit keys */ return NULL; if ((ctx = calloc(1, sizeof(*ctx))) == NULL) return NULL; if ((ctx->main_evp = EVP_CIPHER_CTX_new()) == NULL || (ctx->header_evp = EVP_CIPHER_CTX_new()) == NULL) goto fail; if (!EVP_CipherInit(ctx->main_evp, EVP_chacha20(), key, NULL, 1)) goto fail; if (!EVP_CipherInit(ctx->header_evp, EVP_chacha20(), key + 32, NULL, 1)) goto fail; if (EVP_CIPHER_CTX_iv_length(ctx->header_evp) != 16) goto fail; return ctx; fail: chachapoly_free(ctx); return NULL; } void chachapoly_free(struct chachapoly_ctx *cpctx) { if (cpctx == NULL) return; EVP_CIPHER_CTX_free(cpctx->main_evp); EVP_CIPHER_CTX_free(cpctx->header_evp); freezero(cpctx, sizeof(*cpctx)); } /* * chachapoly_crypt() operates as following: * En/decrypt with header key 'aadlen' bytes from 'src', storing result * to 'dest'. The ciphertext here is treated as additional authenticated * data for MAC calculation. * En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use * POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication * tag. This tag is written on encryption and verified on decryption. */ int chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt) { u_char seqbuf[16]; /* layout: u64 counter || u64 seqno */ int r = SSH_ERR_INTERNAL_ERROR; u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; /* * Run ChaCha20 once to generate the Poly1305 key. The IV is the * packet sequence number. */ memset(seqbuf, 0, sizeof(seqbuf)); POKE_U64(seqbuf + 8, seqnr); memset(poly_key, 0, sizeof(poly_key)); if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) || EVP_Cipher(ctx->main_evp, poly_key, poly_key, sizeof(poly_key)) < 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* If decrypting, check tag before anything else */ if (!do_encrypt) { const u_char *tag = src + aadlen + len; poly1305_auth(expected_tag, src, aadlen + len, poly_key); if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) { r = SSH_ERR_MAC_INVALID; goto out; } } /* Crypt additional data */ if (aadlen) { if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 1) || EVP_Cipher(ctx->header_evp, dest, src, aadlen) < 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } } /* Set Chacha's block counter to 1 */ seqbuf[0] = 1; if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) || EVP_Cipher(ctx->main_evp, dest + aadlen, src + aadlen, len) < 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* If encrypting, calculate and append tag */ if (do_encrypt) { poly1305_auth(dest + aadlen + len, dest, aadlen + len, poly_key); } r = 0; out: explicit_bzero(expected_tag, sizeof(expected_tag)); explicit_bzero(seqbuf, sizeof(seqbuf)); explicit_bzero(poly_key, sizeof(poly_key)); return r; } /* Decrypt and extract the encrypted packet length */ int chachapoly_get_length(struct chachapoly_ctx *ctx, u_int *plenp, u_int seqnr, const u_char *cp, u_int len) { u_char buf[4], seqbuf[16]; if (len < 4) return SSH_ERR_MESSAGE_INCOMPLETE; memset(seqbuf, 0, sizeof(seqbuf)); POKE_U64(seqbuf + 8, seqnr); if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 0)) return SSH_ERR_LIBCRYPTO_ERROR; if (EVP_Cipher(ctx->header_evp, buf, (u_char *)cp, sizeof(buf)) < 0) return SSH_ERR_LIBCRYPTO_ERROR; *plenp = PEEK_U32(buf); return 0; } #endif /* defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20) */ openssh-10.0p1/PaxHeaders.10889/cipher-chachapoly.c100644 001750 001750 0000000003614775415623 0016703xustar0030 atime=1744182234.527171727 openssh-10.0p1/cipher-chachapoly.c010064400017500001750000000102241477541562300152650ustar00djmdjm/* $OpenBSD: cipher-chachapoly.c,v 1.10 2023/07/17 05:26:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef WITH_OPENSSL #include "openbsd-compat/openssl-compat.h" #endif #if !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20) #include #include /* needed for log.h */ #include #include /* needed for misc.h */ #include "log.h" #include "sshbuf.h" #include "ssherr.h" #include "cipher-chachapoly.h" 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 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 ctx; } void chachapoly_free(struct chachapoly_ctx *cpctx) { 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[8]; const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */ u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; int r = SSH_ERR_INTERNAL_ERROR; /* * Run ChaCha20 once to generate the Poly1305 key. The IV is the * packet sequence number. */ memset(poly_key, 0, sizeof(poly_key)); POKE_U64(seqbuf, seqnr); chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL); chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key)); /* 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) { chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen); } /* Set Chacha's block counter to 1 */ chacha_ivsetup(&ctx->main_ctx, seqbuf, one); chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen, dest + aadlen, len); /* 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[8]; if (len < 4) return SSH_ERR_MESSAGE_INCOMPLETE; POKE_U64(seqbuf, seqnr); chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4); *plenp = PEEK_U32(buf); return 0; } #endif /* !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20) */ openssh-10.0p1/PaxHeaders.10889/cipher-chachapoly.h100644 001750 001750 0000000003614775415623 0016710xustar0030 atime=1744182234.527171727 openssh-10.0p1/cipher-chachapoly.h010064400017500001750000000031071477541562300152740ustar00djmdjm/* $OpenBSD: cipher-chachapoly.h,v 1.5 2020/04/03 04:27:03 djm Exp $ */ /* * Copyright (c) Damien Miller 2013 * * 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 CHACHA_POLY_AEAD_H #define CHACHA_POLY_AEAD_H #include #include "chacha.h" #include "poly1305.h" #define CHACHA_KEYLEN 32 /* Only 256 bit keys used here */ 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_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); int chachapoly_get_length(struct chachapoly_ctx *cpctx, u_int *plenp, u_int seqnr, const u_char *cp, u_int len) __attribute__((__bounded__(__buffer__, 4, 5))); #endif /* CHACHA_POLY_AEAD_H */ openssh-10.0p1/PaxHeaders.10889/cipher.c100644 001750 001750 0000000003614775415623 0014572xustar0030 atime=1744182234.527171727 openssh-10.0p1/cipher.c010064400017500001750000000316461477541562300131670ustar00djmdjm/* $OpenBSD: cipher.c,v 1.124 2025/03/14 09:49:49 tb Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * Copyright (c) 1999 Niels Provos. All rights reserved. * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include "cipher.h" #include "misc.h" #include "sshbuf.h" #include "ssherr.h" #include "digest.h" #include "openbsd-compat/openssl-compat.h" #ifndef WITH_OPENSSL #define EVP_CIPHER_CTX void #endif struct sshcipher_ctx { int plaintext; int encrypt; EVP_CIPHER_CTX *evp; struct chachapoly_ctx *cp_ctx; struct aesctr_ctx ac_ctx; /* XXX union with evp? */ const struct sshcipher *cipher; }; struct sshcipher { char *name; u_int block_size; u_int key_len; u_int iv_len; /* defaults to block_size */ u_int auth_len; u_int flags; #define CFLAG_CBC (1<<0) #define CFLAG_CHACHAPOLY (1<<1) #define CFLAG_AESCTR (1<<2) #define CFLAG_NONE (1<<3) #define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */ #ifdef WITH_OPENSSL const EVP_CIPHER *(*evptype)(void); #else void *ignored; #endif }; static const struct sshcipher ciphers[] = { #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, #endif { "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc }, { "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc }, { "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr }, { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr }, { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, { "aes128-gcm@openssh.com", 16, 16, 12, 16, 0, EVP_aes_128_gcm }, { "aes256-gcm@openssh.com", 16, 32, 12, 16, 0, EVP_aes_256_gcm }, #else { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL }, { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL }, { "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL }, #endif { "chacha20-poly1305@openssh.com", 8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL }, { "none", 8, 0, 0, 0, CFLAG_NONE, NULL }, { NULL, 0, 0, 0, 0, 0, NULL } }; /*--*/ /* Returns a comma-separated list of supported ciphers. */ char * cipher_alg_list(char sep, int auth_only) { char *tmp, *ret = NULL; size_t nlen, rlen = 0; const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) { if ((c->flags & CFLAG_INTERNAL) != 0) continue; if (auth_only && c->auth_len == 0) continue; if (ret != NULL) ret[rlen++] = sep; nlen = strlen(c->name); if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { free(ret); return NULL; } ret = tmp; memcpy(ret + rlen, c->name, nlen + 1); rlen += nlen; } return ret; } const char * compression_alg_list(int compression) { #ifdef WITH_ZLIB return compression ? "zlib@openssh.com,none" : "none,zlib@openssh.com"; #else return "none"; #endif } u_int cipher_blocksize(const struct sshcipher *c) { return (c->block_size); } u_int cipher_keylen(const struct sshcipher *c) { return (c->key_len); } u_int cipher_seclen(const struct sshcipher *c) { if (strcmp("3des-cbc", c->name) == 0) return 14; return cipher_keylen(c); } u_int cipher_authlen(const struct sshcipher *c) { return (c->auth_len); } u_int cipher_ivlen(const struct sshcipher *c) { /* * Default is cipher block size, except for chacha20+poly1305 that * needs no IV. XXX make iv_len == -1 default? */ return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ? c->iv_len : c->block_size; } u_int cipher_is_cbc(const struct sshcipher *c) { return (c->flags & CFLAG_CBC) != 0; } u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *cc) { return cc->plaintext; } const struct sshcipher * cipher_by_name(const char *name) { const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) if (strcmp(c->name, name) == 0) return c; return NULL; } #define CIPHER_SEP "," int ciphers_valid(const char *names) { const struct sshcipher *c; char *cipher_list, *cp; char *p; if (names == NULL || strcmp(names, "") == 0) return 0; if ((cipher_list = cp = strdup(names)) == NULL) return 0; for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) { free(cipher_list); return 0; } } free(cipher_list); return 1; } const char * cipher_warning_message(const struct sshcipher_ctx *cc) { if (cc == NULL || cc->cipher == NULL) return NULL; /* XXX repurpose for CBC warning */ return NULL; } int cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, int do_encrypt) { struct sshcipher_ctx *cc = NULL; int ret = SSH_ERR_INTERNAL_ERROR; #ifdef WITH_OPENSSL const EVP_CIPHER *type; int klen; #endif *ccp = NULL; if ((cc = calloc(1, sizeof(*cc))) == NULL) return SSH_ERR_ALLOC_FAIL; cc->plaintext = (cipher->flags & CFLAG_NONE) != 0; cc->encrypt = do_encrypt; if (keylen < cipher->key_len || (iv != NULL && ivlen < cipher_ivlen(cipher))) { ret = SSH_ERR_INVALID_ARGUMENT; goto out; } cc->cipher = cipher; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { cc->cp_ctx = chachapoly_new(key, keylen); ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT; goto out; } if ((cc->cipher->flags & CFLAG_NONE) != 0) { ret = 0; goto out; } #ifndef WITH_OPENSSL if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); aesctr_ivsetup(&cc->ac_ctx, iv); ret = 0; goto out; } ret = SSH_ERR_INVALID_ARGUMENT; goto out; #else /* WITH_OPENSSL */ type = (*cipher->evptype)(); if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv, (do_encrypt == CIPHER_ENCRYPT)) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (cipher_authlen(cipher) && EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (u_char *)iv) <= 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } klen = EVP_CIPHER_CTX_key_length(cc->evp); if (klen > 0 && keylen != (u_int)klen) { if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } } if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ret = 0; #endif /* WITH_OPENSSL */ out: if (ret == 0) { /* success */ *ccp = cc; } else { if (cc != NULL) { #ifdef WITH_OPENSSL EVP_CIPHER_CTX_free(cc->evp); #endif /* WITH_OPENSSL */ freezero(cc, sizeof(*cc)); } } return ret; } /* * cipher_crypt() operates as following: * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'. * These bytes are treated as additional authenticated data for * authenticated encryption modes. * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. * This tag is written on encryption and verified on decryption. * Both 'aadlen' and 'authlen' can be set to 0. */ int cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { return chachapoly_crypt(cc->cp_ctx, seqnr, dest, src, len, aadlen, authlen, cc->encrypt); } if ((cc->cipher->flags & CFLAG_NONE) != 0) { memcpy(dest, src, aadlen + len); return 0; } #ifndef WITH_OPENSSL if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { if (aadlen) memcpy(dest, src, aadlen); aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, dest + aadlen, len); return 0; } return SSH_ERR_INVALID_ARGUMENT; #else if (authlen) { u_char lastiv[1]; if (authlen != cipher_authlen(cc->cipher)) return SSH_ERR_INVALID_ARGUMENT; /* increment IV */ if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv) <= 0) return SSH_ERR_LIBCRYPTO_ERROR; /* set tag on decryption */ if (!cc->encrypt && EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG, authlen, (u_char *)src + aadlen + len) <= 0) return SSH_ERR_LIBCRYPTO_ERROR; } if (aadlen) { if (authlen && EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0) return SSH_ERR_LIBCRYPTO_ERROR; memcpy(dest, src, aadlen); } if (len % cc->cipher->block_size) return SSH_ERR_INVALID_ARGUMENT; if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen, len) < 0) return SSH_ERR_LIBCRYPTO_ERROR; if (authlen) { /* compute tag (on encrypt) or verify tag (on decrypt) */ if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0) return cc->encrypt ? SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID; if (cc->encrypt && EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG, authlen, dest + aadlen + len) <= 0) return SSH_ERR_LIBCRYPTO_ERROR; } return 0; #endif } /* Extract the packet length, including any decryption necessary beforehand */ int cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, const u_char *cp, u_int len) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return chachapoly_get_length(cc->cp_ctx, plenp, seqnr, cp, len); if (len < 4) return SSH_ERR_MESSAGE_INCOMPLETE; *plenp = PEEK_U32(cp); return 0; } void cipher_free(struct sshcipher_ctx *cc) { if (cc == NULL) return; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { chachapoly_free(cc->cp_ctx); cc->cp_ctx = NULL; } else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); #ifdef WITH_OPENSSL EVP_CIPHER_CTX_free(cc->evp); cc->evp = NULL; #endif freezero(cc, sizeof(*cc)); } int cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len) { #ifdef WITH_OPENSSL const struct sshcipher *c = cc->cipher; int evplen; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { if (len != 0) return SSH_ERR_INVALID_ARGUMENT; return 0; } if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { if (len != sizeof(cc->ac_ctx.ctr)) return SSH_ERR_INVALID_ARGUMENT; memcpy(iv, cc->ac_ctx.ctr, len); return 0; } if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; #ifdef WITH_OPENSSL evplen = EVP_CIPHER_CTX_iv_length(cc->evp); if (evplen == 0) return 0; else if (evplen < 0) return SSH_ERR_LIBCRYPTO_ERROR; if ((size_t)evplen != len) return SSH_ERR_INVALID_ARGUMENT; if (cipher_authlen(c)) { if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, len, iv) <= 0) return SSH_ERR_LIBCRYPTO_ERROR; } else if (EVP_CIPHER_CTX_get_iv(cc->evp, iv, len) <= 0) return SSH_ERR_LIBCRYPTO_ERROR; #endif return 0; } int cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len) { #ifdef WITH_OPENSSL const struct sshcipher *c = cc->cipher; int evplen = 0; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return 0; if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; #ifdef WITH_OPENSSL evplen = EVP_CIPHER_CTX_iv_length(cc->evp); if (evplen <= 0) return SSH_ERR_LIBCRYPTO_ERROR; if ((size_t)evplen != len) return SSH_ERR_INVALID_ARGUMENT; if (cipher_authlen(c)) { /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv) <= 0) return SSH_ERR_LIBCRYPTO_ERROR; } else if (!EVP_CIPHER_CTX_set_iv(cc->evp, iv, evplen)) return SSH_ERR_LIBCRYPTO_ERROR; #endif return 0; } openssh-10.0p1/PaxHeaders.10889/cipher.h100644 001750 001750 0000000003614775415623 0014577xustar0030 atime=1744182234.527171727 openssh-10.0p1/cipher.h010064400017500001750000000062411477541562300131650ustar00djmdjm/* $OpenBSD: cipher.h,v 1.56 2023/10/10 06:49:54 tb Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CIPHER_H #define CIPHER_H #include #ifdef WITH_OPENSSL #include #endif #include "cipher-chachapoly.h" #include "cipher-aesctr.h" #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 struct sshcipher; struct sshcipher_ctx; const struct sshcipher *cipher_by_name(const char *); const char *cipher_warning_message(const struct sshcipher_ctx *); int ciphers_valid(const char *); char *cipher_alg_list(char, int); const char *compression_alg_list(int); int cipher_init(struct sshcipher_ctx **, const struct sshcipher *, const u_char *, u_int, const u_char *, u_int, int); int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *, u_int, u_int, u_int); int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int, const u_char *, u_int); void cipher_free(struct sshcipher_ctx *); u_int cipher_blocksize(const struct sshcipher *); u_int cipher_keylen(const struct sshcipher *); u_int cipher_seclen(const struct sshcipher *); u_int cipher_authlen(const struct sshcipher *); u_int cipher_ivlen(const struct sshcipher *); u_int cipher_is_cbc(const struct sshcipher *); u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *); int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, size_t); int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *, size_t); #endif /* CIPHER_H */ openssh-10.0p1/PaxHeaders.10889/cleanup.c100644 001750 001750 0000000003614775415623 0014747xustar0030 atime=1744182234.527171727 openssh-10.0p1/cleanup.c010064400017500001750000000020131477541562300133260ustar00djmdjm/* $OpenBSD: cleanup.c,v 1.5 2006/08/03 03:34:42 deraadt Exp $ */ /* * Copyright (c) 2003 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" #include #include #include #include "log.h" /* default implementation */ void cleanup_exit(int i) { _exit(i); } openssh-10.0p1/PaxHeaders.10889/clientloop.c100644 001750 001750 0000000003614775415623 0015470xustar0030 atime=1744182234.531078306 openssh-10.0p1/clientloop.c010064400017500001750000002436431477541562300140670ustar00djmdjm/* $OpenBSD: clientloop.c,v 1.410 2024/12/03 22:30:03 jsg Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * The main loop for the interactive session (client side). * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * Copyright (c) 1999 Theo de Raadt. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * SSH2 support added by Markus Friedl. * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "packet.h" #include "sshbuf.h" #include "compat.h" #include "channels.h" #include "dispatch.h" #include "sshkey.h" #include "cipher.h" #include "kex.h" #include "myproposal.h" #include "log.h" #include "misc.h" #include "readconf.h" #include "clientloop.h" #include "sshconnect.h" #include "authfd.h" #include "atomicio.h" #include "sshpty.h" #include "match.h" #include "msg.h" #include "ssherr.h" #include "hostfile.h" /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" /* Uncertainty (in percent) of keystroke timing intervals */ #define SSH_KEYSTROKE_TIMING_FUZZ 10 /* import options */ extern Options options; /* Control socket */ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */ /* * Name of the host we are connecting to. This is the name given on the * command line, or the Hostname specified for the user-supplied name in a * configuration file. */ extern char *host; /* * If this field is not NULL, the ForwardAgent socket is this path and different * instead of SSH_AUTH_SOCK. */ extern char *forward_agent_sock_path; /* * Flag to indicate that we have received a window change signal which has * not yet been processed. This will cause a message indicating the new * window size to be sent to the server a little later. This is volatile * because this is updated in a signal handler. */ static volatile sig_atomic_t received_window_change_signal = 0; static volatile sig_atomic_t received_signal = 0; /* Time when backgrounded control master using ControlPersist should exit */ static time_t control_persist_exit_time = 0; /* Common data for the client loop code. */ volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ static int last_was_cr; /* Last character was a newline. */ static int exit_status; /* Used to store the command exit status. */ static int connection_in; /* Connection to server (input). */ static int connection_out; /* Connection to server (output). */ static int need_rekeying; /* Set to non-zero if rekeying is requested. */ static int session_closed; /* In SSH2: login session closed. */ static time_t x11_refuse_time; /* If >0, refuse x11 opens after this time. */ static time_t server_alive_time; /* Time to do server_alive_check */ static int hostkeys_update_complete; static int session_setup_complete; static void client_init_dispatch(struct ssh *ssh); int session_ident = -1; /* Track escape per proto2 channel */ struct escape_filter_ctx { int escape_pending; int escape_char; }; /* Context for channel confirmation replies */ struct channel_reply_ctx { const char *request_type; int id; enum confirm_action action; }; /* Global request success/failure callbacks */ /* XXX move to struct ssh? */ struct global_confirm { TAILQ_ENTRY(global_confirm) entry; global_confirm_cb *cb; void *ctx; int ref_count; }; TAILQ_HEAD(global_confirms, global_confirm); static struct global_confirms global_confirms = TAILQ_HEAD_INITIALIZER(global_confirms); static void quit_message(const char *fmt, ...) __attribute__((__format__ (printf, 1, 2))); static void quit_message(const char *fmt, ...) { char *msg, *fmt2; va_list args; xasprintf(&fmt2, "%s\r\n", fmt); va_start(args, fmt); xvasprintf(&msg, fmt2, args); va_end(args); (void)atomicio(vwrite, STDERR_FILENO, msg, strlen(msg)); free(msg); free(fmt2); quit_pending = 1; } /* * Signal handler for the window change signal (SIGWINCH). This just sets a * flag indicating that the window has changed. */ static void window_change_handler(int sig) { received_window_change_signal = 1; } /* * Signal handler for signals that cause the program to terminate. These * signals must be trapped to restore terminal modes. */ static void signal_handler(int sig) { received_signal = sig; quit_pending = 1; } /* * Sets control_persist_exit_time to the absolute time when the * backgrounded control master should exit due to expiry of the * ControlPersist timeout. Sets it to 0 if we are not a backgrounded * control master process, or if there is no ControlPersist timeout. */ static void set_control_persist_exit_time(struct ssh *ssh) { if (muxserver_sock == -1 || !options.control_persist || options.control_persist_timeout == 0) { /* not using a ControlPersist timeout */ control_persist_exit_time = 0; } else if (channel_still_open(ssh)) { /* some client connections are still open */ if (control_persist_exit_time > 0) debug2_f("cancel scheduled exit"); control_persist_exit_time = 0; } else if (control_persist_exit_time <= 0) { /* a client connection has recently closed */ control_persist_exit_time = monotime() + (time_t)options.control_persist_timeout; debug2_f("schedule exit in %d seconds", options.control_persist_timeout); } /* else we are already counting down to the timeout */ } #define SSH_X11_VALID_DISPLAY_CHARS ":/.-_" static int client_x11_display_valid(const char *display) { size_t i, dlen; if (display == NULL) return 0; dlen = strlen(display); for (i = 0; i < dlen; i++) { if (!isalnum((u_char)display[i]) && strchr(SSH_X11_VALID_DISPLAY_CHARS, display[i]) == NULL) { debug("Invalid character '%c' in DISPLAY", display[i]); return 0; } } return 1; } #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" #define X11_TIMEOUT_SLACK 60 int client_x11_get_proto(struct ssh *ssh, const char *display, const char *xauth_path, u_int trusted, u_int timeout, char **_proto, char **_data) { char *cmd, line[512], xdisplay[512]; char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; static char proto[512], data[512]; FILE *f; int got_data = 0, generated = 0, do_unlink = 0, r; struct stat st; u_int now, x11_timeout_real; *_proto = proto; *_data = data; proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0'; if (!client_x11_display_valid(display)) { if (display != NULL) logit("DISPLAY \"%s\" invalid; disabling X11 forwarding", display); return -1; } if (xauth_path != NULL && stat(xauth_path, &st) == -1) { debug("No xauth program."); xauth_path = NULL; } if (xauth_path != NULL) { /* * Handle FamilyLocal case where $DISPLAY does * not match an authorization entry. For this we * just try "xauth list unix:displaynum.screennum". * XXX: "localhost" match to determine FamilyLocal * is not perfect. */ if (strncmp(display, "localhost:", 10) == 0) { if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s", display + 10)) < 0 || (size_t)r >= sizeof(xdisplay)) { error_f("display name too long"); return -1; } display = xdisplay; } if (trusted == 0) { /* * Generate an untrusted X11 auth cookie. * * The authentication cookie should briefly outlive * ssh's willingness to forward X11 connections to * avoid nasty fail-open behaviour in the X server. */ mktemp_proto(xauthdir, sizeof(xauthdir)); if (mkdtemp(xauthdir) == NULL) { error_f("mkdtemp: %s", strerror(errno)); return -1; } do_unlink = 1; if ((r = snprintf(xauthfile, sizeof(xauthfile), "%s/xauthfile", xauthdir)) < 0 || (size_t)r >= sizeof(xauthfile)) { error_f("xauthfile path too long"); rmdir(xauthdir); return -1; } if (timeout == 0) { /* auth doesn't time out */ xasprintf(&cmd, "%s -f %s generate %s %s " "untrusted 2>%s", xauth_path, xauthfile, display, SSH_X11_PROTO, _PATH_DEVNULL); } else { /* Add some slack to requested expiry */ if (timeout < UINT_MAX - X11_TIMEOUT_SLACK) x11_timeout_real = timeout + X11_TIMEOUT_SLACK; else { /* Don't overflow on long timeouts */ x11_timeout_real = UINT_MAX; } xasprintf(&cmd, "%s -f %s generate %s %s " "untrusted timeout %u 2>%s", xauth_path, xauthfile, display, SSH_X11_PROTO, x11_timeout_real, _PATH_DEVNULL); } debug2_f("xauth command: %s", cmd); if (timeout != 0 && x11_refuse_time == 0) { now = monotime() + 1; if (SSH_TIME_T_MAX - timeout < now) x11_refuse_time = SSH_TIME_T_MAX; else x11_refuse_time = now + timeout; channel_set_x11_refuse_time(ssh, x11_refuse_time); } if (system(cmd) == 0) generated = 1; free(cmd); } /* * When in untrusted mode, we read the cookie only if it was * successfully generated as an untrusted one in the step * above. */ if (trusted || generated) { xasprintf(&cmd, "%s %s%s list %s 2>" _PATH_DEVNULL, xauth_path, generated ? "-f " : "" , generated ? xauthfile : "", display); debug2("x11_get_proto: %s", cmd); f = popen(cmd, "r"); if (f && fgets(line, sizeof(line), f) && sscanf(line, "%*s %511s %511s", proto, data) == 2) got_data = 1; if (f) pclose(f); free(cmd); } } if (do_unlink) { unlink(xauthfile); rmdir(xauthdir); } /* Don't fall back to fake X11 data for untrusted forwarding */ if (!trusted && !got_data) { error("Warning: untrusted X11 forwarding setup failed: " "xauth key data not generated"); return -1; } /* * If we didn't get authentication data, just make up some * data. The forwarding code will check the validity of the * response anyway, and substitute this data. The X11 * server, however, will ignore this fake data and use * whatever authentication mechanisms it was using otherwise * for the local connection. */ if (!got_data) { u_int8_t rnd[16]; u_int i; logit("Warning: No xauth data; " "using fake authentication data for X11 forwarding."); strlcpy(proto, SSH_X11_PROTO, sizeof proto); arc4random_buf(rnd, sizeof(rnd)); for (i = 0; i < sizeof(rnd); i++) { snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rnd[i]); } } return 0; } /* * Checks if the client window has changed, and sends a packet about it to * the server if so. The actual change is detected elsewhere (by a software * interrupt on Unix); this just checks the flag and sends a message if * appropriate. */ static void client_check_window_change(struct ssh *ssh) { if (!received_window_change_signal) return; received_window_change_signal = 0; debug2_f("changed"); channel_send_window_changes(ssh); } static int client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) { struct global_confirm *gc; if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) return 0; if (gc->cb != NULL) gc->cb(ssh, type, seq, gc->ctx); if (--gc->ref_count <= 0) { TAILQ_REMOVE(&global_confirms, gc, entry); freezero(gc, sizeof(*gc)); } ssh_packet_set_alive_timeouts(ssh, 0); return 0; } static void schedule_server_alive_check(void) { if (options.server_alive_interval > 0) server_alive_time = monotime() + options.server_alive_interval; } static void server_alive_check(struct ssh *ssh) { int r; if (ssh_packet_inc_alive_timeouts(ssh) > options.server_alive_count_max) { logit("Timeout, server %s not responding.", host); cleanup_exit(255); } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0 || /* boolean: want reply */ (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); /* Insert an empty placeholder to maintain ordering */ client_register_global_confirm(NULL, NULL); schedule_server_alive_check(); } /* Try to send a dummy keystroke */ static int send_chaff(struct ssh *ssh) { int r; if (ssh->kex == NULL || (ssh->kex->flags & KEX_HAS_PING) == 0) return 0; /* XXX probabilistically send chaff? */ /* * a SSH2_MSG_CHANNEL_DATA payload is 9 bytes: * 4 bytes channel ID + 4 bytes string length + 1 byte string data * simulate that here. */ if ((r = sshpkt_start(ssh, SSH2_MSG_PING)) != 0 || (r = sshpkt_put_cstring(ssh, "PING!")) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); return 1; } /* Sets the next interval to send a keystroke or chaff packet */ static void set_next_interval(const struct timespec *now, struct timespec *next_interval, u_int interval_ms, int starting) { struct timespec tmp; long long interval_ns, fuzz_ns; static long long rate_fuzz; interval_ns = interval_ms * (1000LL * 1000); fuzz_ns = (interval_ns * SSH_KEYSTROKE_TIMING_FUZZ) / 100; /* Center fuzz around requested interval */ if (fuzz_ns > INT_MAX) fuzz_ns = INT_MAX; if (fuzz_ns > interval_ns) { /* Shouldn't happen */ fatal_f("internal error: fuzz %u%% %lldns > interval %lldns", SSH_KEYSTROKE_TIMING_FUZZ, fuzz_ns, interval_ns); } /* * Randomise the keystroke/chaff intervals in two ways: * 1. Each interval has some random jitter applied to make the * interval-to-interval time unpredictable. * 2. The overall interval rate is also randomly perturbed for each * chaffing session to make the average rate unpredictable. */ if (starting) rate_fuzz = arc4random_uniform(fuzz_ns); interval_ns -= fuzz_ns; interval_ns += arc4random_uniform(fuzz_ns) + rate_fuzz; tmp.tv_sec = interval_ns / (1000 * 1000 * 1000); tmp.tv_nsec = interval_ns % (1000 * 1000 * 1000); timespecadd(now, &tmp, next_interval); } /* * Performs keystroke timing obfuscation. Returns non-zero if the * output fd should be polled. */ static int obfuscate_keystroke_timing(struct ssh *ssh, struct timespec *timeout, int channel_did_enqueue) { static int active; static struct timespec next_interval, chaff_until; struct timespec now, tmp; int just_started = 0, had_keystroke = 0; static unsigned long long nchaff; char *stop_reason = NULL; long long n; monotime_ts(&now); if (options.obscure_keystroke_timing_interval <= 0) return 1; /* disabled in config */ if (!channel_tty_open(ssh) || quit_pending) { /* Stop if no channels left of we're waiting for one to close */ stop_reason = "no active channels"; } else if (ssh_packet_is_rekeying(ssh)) { /* Stop if we're rekeying */ stop_reason = "rekeying started"; } else if (!ssh_packet_interactive_data_to_write(ssh) && ssh_packet_have_data_to_write(ssh)) { /* Stop if the output buffer has more than a few keystrokes */ stop_reason = "output buffer filling"; } else if (active && channel_did_enqueue && ssh_packet_have_data_to_write(ssh)) { /* Still in active mode and have a keystroke queued. */ had_keystroke = 1; } else if (active) { if (timespeccmp(&now, &chaff_until, >=)) { /* Stop if there have been no keystrokes for a while */ stop_reason = "chaff time expired"; } else if (timespeccmp(&now, &next_interval, >=) && !ssh_packet_have_data_to_write(ssh)) { /* If due to send but have no data, then send chaff */ if (send_chaff(ssh)) nchaff++; } } if (stop_reason != NULL) { if (active) { debug3_f("stopping: %s (%llu chaff packets sent)", stop_reason, nchaff); active = 0; } return 1; } /* * If we're in interactive mode, and only have a small amount * of outbound data, then we assume that the user is typing * interactively. In this case, start quantising outbound packets to * fixed time intervals to hide inter-keystroke timing. */ if (!active && ssh_packet_interactive_data_to_write(ssh) && channel_did_enqueue && ssh_packet_have_data_to_write(ssh)) { debug3_f("starting: interval ~%dms", options.obscure_keystroke_timing_interval); just_started = had_keystroke = active = 1; nchaff = 0; set_next_interval(&now, &next_interval, options.obscure_keystroke_timing_interval, 1); } /* Don't hold off if obfuscation inactive */ if (!active) return 1; if (had_keystroke) { /* * Arrange to send chaff packets for a random interval after * the last keystroke was sent. */ ms_to_timespec(&tmp, SSH_KEYSTROKE_CHAFF_MIN_MS + arc4random_uniform(SSH_KEYSTROKE_CHAFF_RNG_MS)); timespecadd(&now, &tmp, &chaff_until); } ptimeout_deadline_monotime_tsp(timeout, &next_interval); if (just_started) return 1; /* Don't arm output fd for poll until the timing interval has elapsed... */ if (timespeccmp(&now, &next_interval, <)) /* ...unless there's x11 communication happening */ return x11_channel_used_recently(ssh); /* Calculate number of intervals missed since the last check */ n = (now.tv_sec - next_interval.tv_sec) * 1000LL * 1000 * 1000; n += now.tv_nsec - next_interval.tv_nsec; n /= options.obscure_keystroke_timing_interval * 1000LL * 1000; n = (n < 0) ? 1 : n + 1; /* Advance to the next interval */ set_next_interval(&now, &next_interval, options.obscure_keystroke_timing_interval * n, 0); return 1; } /* * Waits until the client can do something (some data becomes available on * one of the file descriptors). */ static void client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp, u_int *npfd_allocp, u_int *npfd_activep, int channel_did_enqueue, sigset_t *sigsetp, int *conn_in_readyp, int *conn_out_readyp) { struct timespec timeout; int ret, oready; u_int p; *conn_in_readyp = *conn_out_readyp = 0; /* Prepare channel poll. First two pollfd entries are reserved */ ptimeout_init(&timeout); channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2, &timeout); if (*npfd_activep < 2) fatal_f("bad npfd %u", *npfd_activep); /* shouldn't happen */ /* channel_prepare_poll could have closed the last channel */ if (session_closed && !channel_still_open(ssh) && !ssh_packet_have_data_to_write(ssh)) { /* clear events since we did not call poll() */ for (p = 0; p < *npfd_activep; p++) (*pfdp)[p].revents = 0; return; } oready = obfuscate_keystroke_timing(ssh, &timeout, channel_did_enqueue); /* Monitor server connection on reserved pollfd entries */ (*pfdp)[0].fd = connection_in; (*pfdp)[0].events = POLLIN; (*pfdp)[1].fd = connection_out; (*pfdp)[1].events = (oready && ssh_packet_have_data_to_write(ssh)) ? POLLOUT : 0; /* * Wait for something to happen. This will suspend the process until * some polled descriptor can be read, written, or has some other * event pending, or a timeout expires. */ set_control_persist_exit_time(ssh); if (control_persist_exit_time > 0) ptimeout_deadline_monotime(&timeout, control_persist_exit_time); if (options.server_alive_interval > 0) ptimeout_deadline_monotime(&timeout, server_alive_time); if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) { ptimeout_deadline_sec(&timeout, ssh_packet_get_rekey_timeout(ssh)); } ret = ppoll(*pfdp, *npfd_activep, ptimeout_get_tsp(&timeout), sigsetp); if (ret == -1) { /* * We have to clear the events because we return. * We have to return, because the mainloop checks for the flags * set by the signal handlers. */ for (p = 0; p < *npfd_activep; p++) (*pfdp)[p].revents = 0; if (errno == EINTR) return; /* Note: we might still have data in the buffers. */ quit_message("poll: %s", strerror(errno)); return; } *conn_in_readyp = (*pfdp)[0].revents != 0; *conn_out_readyp = (*pfdp)[1].revents != 0; if (options.server_alive_interval > 0 && !*conn_in_readyp && monotime() >= server_alive_time) { /* * ServerAlive check is needed. We can't rely on the poll * timing out since traffic on the client side such as port * forwards can keep waking it up. */ server_alive_check(ssh); } } static void client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr) { /* Flush stdout and stderr buffers. */ if (sshbuf_len(bout) > 0) atomicio(vwrite, fileno(stdout), sshbuf_mutable_ptr(bout), sshbuf_len(bout)); if (sshbuf_len(berr) > 0) atomicio(vwrite, fileno(stderr), sshbuf_mutable_ptr(berr), sshbuf_len(berr)); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); sshbuf_reset(bin); sshbuf_reset(bout); sshbuf_reset(berr); /* Send the suspend signal to the program itself. */ kill(getpid(), SIGTSTP); /* Reset window sizes in case they have changed */ received_window_change_signal = 1; enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); } static void client_process_net_input(struct ssh *ssh) { int r; /* * Read input from the server, and add any such data to the buffer of * the packet subsystem. */ schedule_server_alive_check(); if ((r = ssh_packet_process_read(ssh, connection_in)) == 0) return; /* success */ if (r == SSH_ERR_SYSTEM_ERROR) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) return; if (errno == EPIPE) { quit_message("Connection to %s closed by remote host.", host); return; } } quit_message("Read from remote host %s: %s", host, ssh_err(r)); } static void client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) { struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; char errmsg[256]; int r, tochan; /* * If a TTY was explicitly requested, then a failure to allocate * one is fatal. */ if (cr->action == CONFIRM_TTY && (options.request_tty == REQUEST_TTY_FORCE || options.request_tty == REQUEST_TTY_YES)) cr->action = CONFIRM_CLOSE; /* XXX suppress on mux _client_ quietmode */ tochan = options.log_level >= SYSLOG_LEVEL_ERROR && c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; if (type == SSH2_MSG_CHANNEL_SUCCESS) { debug2("%s request accepted on channel %d", cr->request_type, c->self); } else if (type == SSH2_MSG_CHANNEL_FAILURE) { if (tochan) { snprintf(errmsg, sizeof(errmsg), "%s request failed\r\n", cr->request_type); } else { snprintf(errmsg, sizeof(errmsg), "%s request failed on channel %d", cr->request_type, c->self); } /* If error occurred on primary session channel, then exit */ if (cr->action == CONFIRM_CLOSE && c->self == session_ident) fatal("%s", errmsg); /* * If error occurred on mux client, append to * their stderr. */ if (tochan) { debug3_f("channel %d: mux request: %s", c->self, cr->request_type); if ((r = sshbuf_put(c->extended, errmsg, strlen(errmsg))) != 0) fatal_fr(r, "sshbuf_put"); } else error("%s", errmsg); if (cr->action == CONFIRM_TTY) { /* * If a TTY allocation error occurred, then arrange * for the correct TTY to leave raw mode. */ if (c->self == session_ident) leave_raw_mode(0); else mux_tty_alloc_failed(ssh, c); } else if (cr->action == CONFIRM_CLOSE) { chan_read_failed(ssh, c); chan_write_failed(ssh, c); } } free(cr); } static void client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx) { free(ctx); } void client_expect_confirm(struct ssh *ssh, int id, const char *request, enum confirm_action action) { struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); cr->request_type = request; cr->action = action; channel_register_status_confirm(ssh, id, client_status_confirm, client_abandon_status_confirm, cr); } void client_register_global_confirm(global_confirm_cb *cb, void *ctx) { struct global_confirm *gc, *last_gc; /* Coalesce identical callbacks */ last_gc = TAILQ_LAST(&global_confirms, global_confirms); if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) { if (++last_gc->ref_count >= INT_MAX) fatal_f("last_gc->ref_count = %d", last_gc->ref_count); return; } gc = xcalloc(1, sizeof(*gc)); gc->cb = cb; gc->ctx = ctx; gc->ref_count = 1; TAILQ_INSERT_TAIL(&global_confirms, gc, entry); } /* * Returns non-zero if the client is able to handle a hostkeys-00@openssh.com * hostkey update request. */ static int can_update_hostkeys(void) { if (hostkeys_update_complete) return 0; if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK && options.batch_mode) return 0; /* won't ask in batchmode, so don't even try */ if (!options.update_hostkeys || options.num_user_hostfiles <= 0) return 0; return 1; } static void client_repledge(void) { debug3_f("enter"); /* Might be able to tighten pledge now that session is established */ if (options.control_master || options.control_path != NULL || options.forward_x11 || options.fork_after_authentication || can_update_hostkeys() || (session_ident != -1 && !session_setup_complete)) { /* Can't tighten */ return; } /* * LocalCommand and UpdateHostkeys have finished, so can get rid of * filesystem. * * XXX protocol allows a server can to change hostkeys during the * connection at rekey time that could trigger a hostkeys update * but AFAIK no implementations support this. Could improve by * forcing known_hosts to be read-only or via unveil(2). */ if (options.num_local_forwards != 0 || options.num_remote_forwards != 0 || options.num_permitted_remote_opens != 0 || options.enable_escape_commandline != 0) { /* rfwd needs inet */ debug("pledge: network"); if (pledge("stdio unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else if (options.forward_agent != 0) { /* agent forwarding needs to open $SSH_AUTH_SOCK at will */ debug("pledge: agent"); if (pledge("stdio unix proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else { debug("pledge: fork"); if (pledge("stdio proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } /* XXX further things to do: * * - might be able to get rid of proc if we kill ~^Z * - ssh -N (no session) * - stdio forwarding * - sessions without tty */ } static void process_cmdline(struct ssh *ssh) { void (*handler)(int); char *s, *cmd; int ok, delete = 0, local = 0, remote = 0, dynamic = 0; struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); handler = ssh_signal(SIGINT, SIG_IGN); cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); if (s == NULL) goto out; while (isspace((u_char)*s)) s++; if (*s == '-') s++; /* Skip cmdline '-', if any */ if (*s == '\0') goto out; if (*s == 'h' || *s == 'H' || *s == '?') { logit("Commands:"); logit(" -L[bind_address:]port:host:hostport " "Request local forward"); logit(" -R[bind_address:]port:host:hostport " "Request remote forward"); logit(" -D[bind_address:]port " "Request dynamic forward"); logit(" -KL[bind_address:]port " "Cancel local forward"); logit(" -KR[bind_address:]port " "Cancel remote forward"); logit(" -KD[bind_address:]port " "Cancel dynamic forward"); if (!options.permit_local_command) goto out; logit(" !args " "Execute local command"); goto out; } if (*s == '!' && options.permit_local_command) { s++; ssh_local_cmd(s); goto out; } if (*s == 'K') { delete = 1; s++; } if (*s == 'L') local = 1; else if (*s == 'R') remote = 1; else if (*s == 'D') dynamic = 1; else { logit("Invalid command."); goto out; } while (isspace((u_char)*++s)) ; /* XXX update list of forwards in options */ if (delete) { /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */ if (!parse_forward(&fwd, s, 1, 0)) { logit("Bad forwarding close specification."); goto out; } if (remote) ok = channel_request_rforward_cancel(ssh, &fwd) == 0; else if (dynamic) ok = channel_cancel_lport_listener(ssh, &fwd, 0, &options.fwd_opts) > 0; else ok = channel_cancel_lport_listener(ssh, &fwd, CHANNEL_CANCEL_PORT_STATIC, &options.fwd_opts) > 0; if (!ok) { logit("Unknown port forwarding."); goto out; } logit("Canceled forwarding."); } else { /* -R specs can be both dynamic or not, so check both. */ if (remote) { if (!parse_forward(&fwd, s, 0, remote) && !parse_forward(&fwd, s, 1, remote)) { logit("Bad remote forwarding specification."); goto out; } } else if (!parse_forward(&fwd, s, dynamic, remote)) { logit("Bad local forwarding specification."); goto out; } if (local || dynamic) { if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { logit("Port forwarding failed."); goto out; } } else { if (channel_request_remote_forwarding(ssh, &fwd) < 0) { logit("Port forwarding failed."); goto out; } } logit("Forwarding port."); } out: ssh_signal(SIGINT, handler); enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); free(cmd); free(fwd.listen_host); free(fwd.listen_path); free(fwd.connect_host); free(fwd.connect_path); } /* reasons to suppress output of an escape command in help output */ #define SUPPRESS_NEVER 0 /* never suppress, always show */ #define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */ #define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */ #define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */ #define SUPPRESS_NOCMDLINE 8 /* don't show when cmdline disabled*/ struct escape_help_text { const char *cmd; const char *text; unsigned int flags; }; static struct escape_help_text esc_txt[] = { {".", "terminate session", SUPPRESS_MUXMASTER}, {".", "terminate connection (and any multiplexed sessions)", SUPPRESS_MUXCLIENT}, {"B", "send a BREAK to the remote system", SUPPRESS_NEVER}, {"C", "open a command line", SUPPRESS_MUXCLIENT|SUPPRESS_NOCMDLINE}, {"R", "request rekey", SUPPRESS_NEVER}, {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, {"#", "list forwarded connections", SUPPRESS_NEVER}, {"&", "background ssh (when waiting for connections to terminate)", SUPPRESS_MUXCLIENT}, {"?", "this message", SUPPRESS_NEVER}, }; static void print_escape_help(struct sshbuf *b, int escape_char, int mux_client, int using_stderr) { unsigned int i, suppress_flags; int r; if ((r = sshbuf_putf(b, "%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); suppress_flags = (mux_client ? SUPPRESS_MUXCLIENT : 0) | (mux_client ? 0 : SUPPRESS_MUXMASTER) | (using_stderr ? 0 : SUPPRESS_SYSLOG) | (options.enable_escape_commandline == 0 ? SUPPRESS_NOCMDLINE : 0); for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) { if (esc_txt[i].flags & suppress_flags) continue; if ((r = sshbuf_putf(b, " %c%-3s - %s\r\n", escape_char, esc_txt[i].cmd, esc_txt[i].text)) != 0) fatal_fr(r, "sshbuf_putf"); } if ((r = sshbuf_putf(b, " %c%c - send the escape character by typing it twice\r\n" "(Note that escapes are only recognized immediately after " "newline.)\r\n", escape_char, escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); } /* * Process the characters one by one. */ static int process_escapes(struct ssh *ssh, Channel *c, struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr, char *buf, int len) { pid_t pid; int r, bytes = 0; u_int i; u_char ch; char *s; struct escape_filter_ctx *efc; if (c == NULL || c->filter_ctx == NULL || len <= 0) return 0; efc = (struct escape_filter_ctx *)c->filter_ctx; for (i = 0; i < (u_int)len; i++) { /* Get one character at a time. */ ch = buf[i]; if (efc->escape_pending) { /* We have previously seen an escape character. */ /* Clear the flag now. */ efc->escape_pending = 0; /* Process the escaped character. */ switch (ch) { case '.': /* Terminate the connection. */ if ((r = sshbuf_putf(berr, "%c.\r\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); if (c && c->ctl_chan != -1) { channel_force_close(ssh, c, 1); return 0; } else quit_pending = 1; return -1; case 'Z' - 64: /* XXX support this for mux clients */ if (c && c->ctl_chan != -1) { char b[16]; noescape: if (ch == 'Z' - 64) snprintf(b, sizeof b, "^Z"); else snprintf(b, sizeof b, "%c", ch); if ((r = sshbuf_putf(berr, "%c%s escape not available to " "multiplexed sessions\r\n", efc->escape_char, b)) != 0) fatal_fr(r, "sshbuf_putf"); continue; } /* Suspend the program. Inform the user */ if ((r = sshbuf_putf(berr, "%c^Z [suspend ssh]\r\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); /* Restore terminal modes and suspend. */ client_suspend_self(bin, bout, berr); /* We have been continued. */ continue; case 'B': if ((r = sshbuf_putf(berr, "%cB\r\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); channel_request_start(ssh, c->self, "break", 0); if ((r = sshpkt_put_u32(ssh, 1000)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); continue; case 'R': if (ssh->compat & SSH_BUG_NOREKEY) logit("Server does not " "support re-keying"); else need_rekeying = 1; continue; case 'V': /* FALLTHROUGH */ case 'v': if (c && c->ctl_chan != -1) goto noescape; if (!log_is_on_stderr()) { if ((r = sshbuf_putf(berr, "%c%c [Logging to syslog]\r\n", efc->escape_char, ch)) != 0) fatal_fr(r, "sshbuf_putf"); continue; } if (ch == 'V' && options.log_level > SYSLOG_LEVEL_QUIET) log_change_level(--options.log_level); if (ch == 'v' && options.log_level < SYSLOG_LEVEL_DEBUG3) log_change_level(++options.log_level); if ((r = sshbuf_putf(berr, "%c%c [LogLevel %s]\r\n", efc->escape_char, ch, log_level_name(options.log_level))) != 0) fatal_fr(r, "sshbuf_putf"); continue; case '&': if (c->ctl_chan != -1) goto noescape; /* * Detach the program (continue to serve * connections, but put in background and no * more new connections). */ /* Restore tty modes. */ leave_raw_mode( options.request_tty == REQUEST_TTY_FORCE); /* Stop listening for new connections. */ channel_stop_listening(ssh); if ((r = sshbuf_putf(berr, "%c& " "[backgrounded]\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); /* Fork into background. */ pid = fork(); if (pid == -1) { error("fork: %.100s", strerror(errno)); continue; } if (pid != 0) { /* This is the parent. */ /* The parent just exits. */ exit(0); } /* The child continues serving connections. */ /* fake EOF on stdin */ if ((r = sshbuf_put_u8(bin, 4)) != 0) fatal_fr(r, "sshbuf_put_u8"); return -1; case '?': print_escape_help(berr, efc->escape_char, (c && c->ctl_chan != -1), log_is_on_stderr()); continue; case '#': if ((r = sshbuf_putf(berr, "%c#\r\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); s = channel_open_message(ssh); if ((r = sshbuf_put(berr, s, strlen(s))) != 0) fatal_fr(r, "sshbuf_put"); free(s); continue; case 'C': if (c && c->ctl_chan != -1) goto noescape; if (options.enable_escape_commandline == 0) { if ((r = sshbuf_putf(berr, "commandline disabled\r\n")) != 0) fatal_fr(r, "sshbuf_putf"); continue; } process_cmdline(ssh); continue; default: if (ch != efc->escape_char) { if ((r = sshbuf_put_u8(bin, efc->escape_char)) != 0) fatal_fr(r, "sshbuf_put_u8"); bytes++; } /* Escaped characters fall through here */ break; } } else { /* * The previous character was not an escape char. * Check if this is an escape. */ if (last_was_cr && ch == efc->escape_char) { /* * It is. Set the flag and continue to * next character. */ efc->escape_pending = 1; continue; } } /* * Normal character. Record whether it was a newline, * and append it to the buffer. */ last_was_cr = (ch == '\r' || ch == '\n'); if ((r = sshbuf_put_u8(bin, ch)) != 0) fatal_fr(r, "sshbuf_put_u8"); bytes++; } return bytes; } /* * Get packets from the connection input buffer, and process them as long as * there are packets available. * * Any unknown packets received during the actual * session cause the session to terminate. This is * intended to make debugging easier since no * confirmations are sent. Any compatible protocol * extensions must be negotiated during the * preparatory phase. */ static void client_process_buffered_input_packets(struct ssh *ssh) { ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, &quit_pending); } /* scan buf[] for '~' before sending data to the peer */ /* Helper: allocate a new escape_filter_ctx and fill in its escape char */ void * client_new_escape_filter_ctx(int escape_char) { struct escape_filter_ctx *ret; ret = xcalloc(1, sizeof(*ret)); ret->escape_pending = 0; ret->escape_char = escape_char; return (void *)ret; } /* Free the escape filter context on channel free */ void client_filter_cleanup(struct ssh *ssh, int cid, void *ctx) { free(ctx); } int client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len) { if (c->extended_usage != CHAN_EXTENDED_WRITE) return 0; return process_escapes(ssh, c, c->input, c->output, c->extended, buf, len); } static void client_channel_closed(struct ssh *ssh, int id, int force, void *arg) { channel_cancel_cleanup(ssh, id); session_closed = 1; leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); } /* * Implements the interactive session with the server. This is called after * the user has been authenticated, and a command has been started on the * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character * used as an escape character for terminating or suspending the session. */ int client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, int ssh2_chan_id) { struct pollfd *pfd = NULL; u_int npfd_alloc = 0, npfd_active = 0; double start_time, total_time; int channel_did_enqueue = 0, r; u_int64_t ibytes, obytes; int conn_in_ready, conn_out_ready; sigset_t bsigset, osigset; debug("Entering interactive session."); session_ident = ssh2_chan_id; if (options.control_master && !option_clear_or_none(options.control_path)) { debug("pledge: id"); if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else if (options.forward_x11 || options.permit_local_command) { debug("pledge: exec"); if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else if (options.update_hostkeys) { debug("pledge: filesystem"); if (pledge("stdio rpath wpath cpath unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else if (!option_clear_or_none(options.proxy_command) || options.fork_after_authentication) { debug("pledge: proc"); if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else { debug("pledge: network"); if (pledge("stdio unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } /* might be able to tighten now */ client_repledge(); start_time = monotime_double(); /* Initialize variables. */ last_was_cr = 1; exit_status = -1; connection_in = ssh_packet_get_connection_in(ssh); connection_out = ssh_packet_get_connection_out(ssh); quit_pending = 0; client_init_dispatch(ssh); /* * Set signal handlers, (e.g. to restore non-blocking mode) * but don't overwrite SIG_IGN, matches behaviour from rsh(1) */ if (ssh_signal(SIGHUP, SIG_IGN) != SIG_IGN) ssh_signal(SIGHUP, signal_handler); if (ssh_signal(SIGINT, SIG_IGN) != SIG_IGN) ssh_signal(SIGINT, signal_handler); if (ssh_signal(SIGQUIT, SIG_IGN) != SIG_IGN) ssh_signal(SIGQUIT, signal_handler); if (ssh_signal(SIGTERM, SIG_IGN) != SIG_IGN) ssh_signal(SIGTERM, signal_handler); ssh_signal(SIGWINCH, window_change_handler); if (have_pty) enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); if (session_ident != -1) { if (escape_char_arg != SSH_ESCAPECHAR_NONE) { channel_register_filter(ssh, session_ident, client_simple_escape_filter, NULL, client_filter_cleanup, client_new_escape_filter_ctx( escape_char_arg)); } channel_register_cleanup(ssh, session_ident, client_channel_closed, 0); } schedule_server_alive_check(); if (sigemptyset(&bsigset) == -1 || sigaddset(&bsigset, SIGHUP) == -1 || sigaddset(&bsigset, SIGINT) == -1 || sigaddset(&bsigset, SIGQUIT) == -1 || sigaddset(&bsigset, SIGTERM) == -1) error_f("bsigset setup: %s", strerror(errno)); /* Main loop of the client for the interactive session mode. */ while (!quit_pending) { channel_did_enqueue = 0; /* Process buffered packets sent by the server. */ client_process_buffered_input_packets(ssh); if (session_closed && !channel_still_open(ssh)) break; if (ssh_packet_is_rekeying(ssh)) { debug("rekeying in progress"); } else if (need_rekeying) { /* manual rekey request */ debug("need rekeying"); if ((r = kex_start_rekex(ssh)) != 0) fatal_fr(r, "kex_start_rekex"); need_rekeying = 0; } else { /* * Make packets from buffered channel data, and * enqueue them for sending to the server. */ if (ssh_packet_not_very_much_data_to_write(ssh)) channel_did_enqueue = channel_output_poll(ssh); /* * Check if the window size has changed, and buffer a * message about it to the server if so. */ client_check_window_change(ssh); } /* * Wait until we have something to do (something becomes * available on one of the descriptors). */ if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1) error_f("bsigset sigprocmask: %s", strerror(errno)); if (quit_pending) break; client_wait_until_can_do_something(ssh, &pfd, &npfd_alloc, &npfd_active, channel_did_enqueue, &osigset, &conn_in_ready, &conn_out_ready); if (sigprocmask(SIG_SETMASK, &osigset, NULL) == -1) error_f("osigset sigprocmask: %s", strerror(errno)); if (quit_pending) break; /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); /* Buffer input from the connection. */ if (conn_in_ready) client_process_net_input(ssh); if (quit_pending) break; /* A timeout may have triggered rekeying */ if ((r = ssh_packet_check_rekey(ssh)) != 0) fatal_fr(r, "cannot start rekeying"); /* * Send as much buffered packet data as possible to the * sender. */ if (conn_out_ready) { if ((r = ssh_packet_write_poll(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll", __func__); } } /* * If we are a backgrounded control master, and the * timeout has expired without any active client * connections, then quit. */ if (control_persist_exit_time > 0) { if (monotime() >= control_persist_exit_time) { debug("ControlPersist timeout expired"); break; } } } free(pfd); /* Terminate the session. */ /* * In interactive mode (with pseudo tty) display a message indicating * that the connection has been closed. */ if (have_pty && options.log_level >= SYSLOG_LEVEL_INFO) quit_message("Connection to %s closed.", host); /* Stop watching for window change. */ ssh_signal(SIGWINCH, SIG_DFL); if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 || (r = sshpkt_put_cstring(ssh, "disconnected by user")) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language tag */ (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send disconnect"); channel_free_all(ssh); if (have_pty) leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); /* * If there was no shell or command requested, there will be no remote * exit status to be returned. In that case, clear error code if the * connection was deliberately terminated at this end. */ if (options.session_type == SESSION_TYPE_NONE && received_signal == SIGTERM) { received_signal = 0; exit_status = 0; } if (received_signal) { verbose("Killed by signal %d.", (int) received_signal); cleanup_exit(255); } /* Report bytes transferred, and transfer rates. */ total_time = monotime_double() - start_time; ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds", (unsigned long long)obytes, (unsigned long long)ibytes, total_time); if (total_time > 0) verbose("Bytes per second: sent %.1f, received %.1f", obytes / total_time, ibytes / total_time); /* Return the exit status of the program. */ debug("Exit status %d", exit_status); return exit_status; } /*********/ static Channel * client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, int rchan, u_int rwindow, u_int rmaxpack) { Channel *c = NULL; struct sshbuf *b = NULL; char *listen_address, *originator_address; u_int listen_port, originator_port; int r; /* Get rest of the packet */ if ((r = sshpkt_get_cstring(ssh, &listen_address, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &listen_port)) != 0 || (r = sshpkt_get_cstring(ssh, &originator_address, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &originator_port)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); debug_f("listen %s port %d, originator %s port %d", listen_address, listen_port, originator_address, originator_port); if (listen_port > 0xffff) error_f("invalid listen port"); else if (originator_port > 0xffff) error_f("invalid originator port"); else { c = channel_connect_by_listen_address(ssh, listen_address, listen_port, "forwarded-tcpip", originator_address); } if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { if ((b = sshbuf_new()) == NULL) { error_f("alloc reply"); goto out; } /* reconstruct and send to muxclient */ if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */ (r = sshbuf_put_u8(b, SSH2_MSG_CHANNEL_OPEN)) != 0 || (r = sshbuf_put_cstring(b, request_type)) != 0 || (r = sshbuf_put_u32(b, rchan)) != 0 || (r = sshbuf_put_u32(b, rwindow)) != 0 || (r = sshbuf_put_u32(b, rmaxpack)) != 0 || (r = sshbuf_put_cstring(b, listen_address)) != 0 || (r = sshbuf_put_u32(b, listen_port)) != 0 || (r = sshbuf_put_cstring(b, originator_address)) != 0 || (r = sshbuf_put_u32(b, originator_port)) != 0 || (r = sshbuf_put_stringb(c->output, b)) != 0) { error_fr(r, "compose for muxclient"); goto out; } } out: sshbuf_free(b); free(originator_address); free(listen_address); return c; } static Channel * client_request_forwarded_streamlocal(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; char *listen_path; int r; /* Get the remote path. */ if ((r = sshpkt_get_cstring(ssh, &listen_path, NULL)) != 0 || (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* reserved */ (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); debug_f("request: %s", listen_path); c = channel_connect_by_listen_path(ssh, listen_path, "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); free(listen_path); return c; } static Channel * client_request_x11(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; char *originator; u_int originator_port; int r, sock; if (!options.forward_x11) { error("Warning: ssh server tried X11 forwarding."); error("Warning: this is probably a break-in attempt by a " "malicious server."); return NULL; } if (x11_refuse_time != 0 && monotime() >= x11_refuse_time) { verbose("Rejected X11 connection after ForwardX11Timeout " "expired"); return NULL; } if ((r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &originator_port)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); /* XXX check permission */ /* XXX range check originator port? */ debug("client_request_x11: request from %s %u", originator, originator_port); free(originator); sock = x11_connect_display(ssh); if (sock < 0) return NULL; c = channel_new(ssh, "x11-connection", SSH_CHANNEL_X11_OPEN, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); c->force_drain = 1; return c; } static Channel * client_request_agent(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; int r, sock; if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); error("Warning: this is probably a break-in attempt by a " "malicious server."); return NULL; } if (forward_agent_sock_path == NULL) { r = ssh_get_authentication_socket(&sock); } else { r = ssh_get_authentication_socket_path(forward_agent_sock_path, &sock); } if (r != 0) { if (r != SSH_ERR_AGENT_NOT_PRESENT) debug_fr(r, "ssh_get_authentication_socket"); return NULL; } if ((r = ssh_agent_bind_hostkey(sock, ssh->kex->initial_hostkey, ssh->kex->session_id, ssh->kex->initial_sig, 1)) == 0) debug_f("bound agent to hostkey"); else debug2_fr(r, "ssh_agent_bind_hostkey"); c = channel_new(ssh, "agent-connection", SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "authentication agent connection", 1); c->force_drain = 1; return c; } char * client_request_tun_fwd(struct ssh *ssh, int tun_mode, int local_tun, int remote_tun, channel_open_fn *cb, void *cbctx) { Channel *c; int r, fd; char *ifname = NULL; if (tun_mode == SSH_TUNMODE_NO) return 0; debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); /* Open local tunnel device */ if ((fd = tun_open(local_tun, tun_mode, &ifname)) == -1) { error("Tunnel device open failed."); return NULL; } debug("Tunnel forwarding using interface %s", ifname); c = channel_new(ssh, "tun-connection", SSH_CHANNEL_OPENING, fd, fd, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); c->datagram = 1; #if defined(SSH_TUN_FILTER) if (options.tun_open == SSH_TUNMODE_POINTOPOINT) channel_register_filter(ssh, c->self, sys_tun_infilter, sys_tun_outfilter, NULL, NULL); #endif if (cb != NULL) channel_register_open_confirm(ssh, c->self, cb, cbctx); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 || (r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window_max)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_put_u32(ssh, tun_mode)) != 0 || (r = sshpkt_put_u32(ssh, remote_tun)) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send reply", __func__); return ifname; } /* XXXX move to generic input handler */ static int client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *ctype = NULL; int r; u_int rchan; size_t len; u_int rmaxpack, rwindow; if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 || (r = sshpkt_get_u32(ssh, &rchan)) != 0 || (r = sshpkt_get_u32(ssh, &rwindow)) != 0 || (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0) goto out; debug("client_input_channel_open: ctype %s rchan %d win %d max %d", ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "forwarded-tcpip") == 0) { c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow, rmaxpack); } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { c = client_request_forwarded_streamlocal(ssh, ctype, rchan); } else if (strcmp(ctype, "x11") == 0) { c = client_request_x11(ssh, ctype, rchan); } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { c = client_request_agent(ssh, ctype, rchan); } if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { debug3("proxied to downstream: %s", ctype); } else if (c != NULL) { debug("confirm %s", ctype); c->remote_id = rchan; c->have_remote_id = 1; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; if (c->type != SSH_CHANNEL_CONNECTING) { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send reply", __func__); } } else { debug("failure %s", ctype); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, rchan)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) != 0 || (r = sshpkt_put_cstring(ssh, "open failed")) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send failure", __func__); } r = 0; out: free(ctype); return r; } static int client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *rtype = NULL; u_char reply; u_int id, exitval; int r, success = 0; if ((r = sshpkt_get_u32(ssh, &id)) != 0) return r; if (id <= INT_MAX) c = channel_lookup(ssh, id); if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &reply)) != 0) goto out; debug("client_input_channel_req: channel %u rtype %s reply %d", id, rtype, reply); if (c == NULL) { error("client_input_channel_req: channel %d: " "unknown channel", id); } else if (strcmp(rtype, "eow@openssh.com") == 0) { if ((r = sshpkt_get_end(ssh)) != 0) goto out; chan_rcvd_eow(ssh, c); } else if (strcmp(rtype, "exit-status") == 0) { if ((r = sshpkt_get_u32(ssh, &exitval)) != 0) goto out; if (c->ctl_chan != -1) { mux_exit_message(ssh, c, exitval); success = 1; } else if ((int)id == session_ident) { /* Record exit value of local session */ success = 1; exit_status = exitval; } else { /* Probably for a mux channel that has already closed */ debug_f("no sink for exit-status on channel %d", id); } if ((r = sshpkt_get_end(ssh)) != 0) goto out; } if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { if (!c->have_remote_id) fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send failure", __func__); } r = 0; out: free(rtype); return r; } struct hostkeys_update_ctx { /* The hostname and (optionally) IP address string for the server */ char *host_str, *ip_str; /* * Keys received from the server and a flag for each indicating * whether they already exist in known_hosts. * keys_match is filled in by hostkeys_find() and later (for new * keys) by client_global_hostkeys_prove_confirm(). */ struct sshkey **keys; u_int *keys_match; /* mask of HKF_MATCH_* from hostfile.h */ int *keys_verified; /* flag for new keys verified by server */ size_t nkeys, nnew, nincomplete; /* total, new keys, incomplete match */ /* * Keys that are in known_hosts, but were not present in the update * from the server (i.e. scheduled to be deleted). * Filled in by hostkeys_find(). */ struct sshkey **old_keys; size_t nold; /* Various special cases. */ int complex_hostspec; /* wildcard or manual pattern-list host name */ int ca_available; /* saw CA key for this host */ int old_key_seen; /* saw old key with other name/addr */ int other_name_seen; /* saw key with other name/addr */ }; static void hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx) { size_t i; if (ctx == NULL) return; for (i = 0; i < ctx->nkeys; i++) sshkey_free(ctx->keys[i]); free(ctx->keys); free(ctx->keys_match); free(ctx->keys_verified); for (i = 0; i < ctx->nold; i++) sshkey_free(ctx->old_keys[i]); free(ctx->old_keys); free(ctx->host_str); free(ctx->ip_str); free(ctx); } /* * Returns non-zero if a known_hosts hostname list is not of a form that * can be handled by UpdateHostkeys. These include wildcard hostnames and * hostnames lists that do not follow the form host[,ip]. */ static int hostspec_is_complex(const char *hosts) { char *cp; /* wildcard */ if (strchr(hosts, '*') != NULL || strchr(hosts, '?') != NULL) return 1; /* single host/ip = ok */ if ((cp = strchr(hosts, ',')) == NULL) return 0; /* more than two entries on the line */ if (strchr(cp + 1, ',') != NULL) return 1; /* XXX maybe parse cp+1 and ensure it is an IP? */ return 0; } /* callback to search for ctx->keys in known_hosts */ static int hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) { struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i; struct sshkey **tmp; if (l->key == NULL) return 0; if (l->status != HKF_STATUS_MATCHED) { /* Record if one of the keys appears on a non-matching line */ for (i = 0; i < ctx->nkeys; i++) { if (sshkey_equal(l->key, ctx->keys[i])) { ctx->other_name_seen = 1; debug3_f("found %s key under different " "name/addr at %s:%ld", sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum); return 0; } } return 0; } /* Don't proceed if revocation or CA markers are present */ /* XXX relax this */ if (l->marker != MRK_NONE) { debug3_f("hostkeys file %s:%ld has CA/revocation marker", l->path, l->linenum); ctx->complex_hostspec = 1; return 0; } /* If CheckHostIP is enabled, then check for mismatched hostname/addr */ if (ctx->ip_str != NULL && strchr(l->hosts, ',') != NULL) { if ((l->match & HKF_MATCH_HOST) == 0) { /* Record if address matched a different hostname. */ ctx->other_name_seen = 1; debug3_f("found address %s against different hostname " "at %s:%ld", ctx->ip_str, l->path, l->linenum); return 0; } else if ((l->match & HKF_MATCH_IP) == 0) { /* Record if hostname matched a different address. */ ctx->other_name_seen = 1; debug3_f("found hostname %s against different address " "at %s:%ld", ctx->host_str, l->path, l->linenum); } } /* * UpdateHostkeys is skipped for wildcard host names and hostnames * that contain more than two entries (ssh never writes these). */ if (hostspec_is_complex(l->hosts)) { debug3_f("hostkeys file %s:%ld complex host specification", l->path, l->linenum); ctx->complex_hostspec = 1; return 0; } /* Mark off keys we've already seen for this host */ for (i = 0; i < ctx->nkeys; i++) { if (!sshkey_equal(l->key, ctx->keys[i])) continue; debug3_f("found %s key at %s:%ld", sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum); ctx->keys_match[i] |= l->match; return 0; } /* This line contained a key that not offered by the server */ debug3_f("deprecated %s key at %s:%ld", sshkey_ssh_name(l->key), l->path, l->linenum); if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1, sizeof(*ctx->old_keys))) == NULL) fatal_f("recallocarray failed nold = %zu", ctx->nold); ctx->old_keys = tmp; ctx->old_keys[ctx->nold++] = l->key; l->key = NULL; return 0; } /* callback to search for ctx->old_keys in known_hosts under other names */ static int hostkeys_check_old(struct hostkey_foreach_line *l, void *_ctx) { struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i; int hashed; /* only care about lines that *don't* match the active host spec */ if (l->status == HKF_STATUS_MATCHED || l->key == NULL) return 0; hashed = l->match & (HKF_MATCH_HOST_HASHED|HKF_MATCH_IP_HASHED); for (i = 0; i < ctx->nold; i++) { if (!sshkey_equal(l->key, ctx->old_keys[i])) continue; debug3_f("found deprecated %s key at %s:%ld as %s", sshkey_ssh_name(ctx->old_keys[i]), l->path, l->linenum, hashed ? "[HASHED]" : l->hosts); ctx->old_key_seen = 1; break; } return 0; } /* * Check known_hosts files for deprecated keys under other names. Returns 0 * on success or -1 on failure. Updates ctx->old_key_seen if deprecated keys * exist under names other than the active hostname/IP. */ static int check_old_keys_othernames(struct hostkeys_update_ctx *ctx) { size_t i; int r; debug2_f("checking for %zu deprecated keys", ctx->nold); for (i = 0; i < options.num_user_hostfiles; i++) { debug3_f("searching %s for %s / %s", options.user_hostfiles[i], ctx->host_str, ctx->ip_str ? ctx->ip_str : "(none)"); if ((r = hostkeys_foreach(options.user_hostfiles[i], hostkeys_check_old, ctx, ctx->host_str, ctx->ip_str, HKF_WANT_PARSE_KEY, 0)) != 0) { if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { debug_f("hostkeys file %s does not exist", options.user_hostfiles[i]); continue; } error_fr(r, "hostkeys_foreach failed for %s", options.user_hostfiles[i]); return -1; } } return 0; } static void hostkey_change_preamble(LogLevel loglevel) { do_log2(loglevel, "The server has updated its host keys."); do_log2(loglevel, "These changes were verified by the server's " "existing trusted key."); } static void update_known_hosts(struct hostkeys_update_ctx *ctx) { int r, was_raw = 0, first = 1; int asking = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK; LogLevel loglevel = asking ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE; char *fp, *response; size_t i; struct stat sb; for (i = 0; i < ctx->nkeys; i++) { if (!ctx->keys_verified[i]) continue; if ((fp = sshkey_fingerprint(ctx->keys[i], options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); if (first && asking) hostkey_change_preamble(loglevel); do_log2(loglevel, "Learned new hostkey: %s %s", sshkey_type(ctx->keys[i]), fp); first = 0; free(fp); } for (i = 0; i < ctx->nold; i++) { if ((fp = sshkey_fingerprint(ctx->old_keys[i], options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); if (first && asking) hostkey_change_preamble(loglevel); do_log2(loglevel, "Deprecating obsolete hostkey: %s %s", sshkey_type(ctx->old_keys[i]), fp); first = 0; free(fp); } if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { if (get_saved_tio() != NULL) { leave_raw_mode(1); was_raw = 1; } response = NULL; for (i = 0; !quit_pending && i < 3; i++) { free(response); response = read_passphrase("Accept updated hostkeys? " "(yes/no): ", RP_ECHO); if (response != NULL && strcasecmp(response, "yes") == 0) break; else if (quit_pending || response == NULL || strcasecmp(response, "no") == 0) { options.update_hostkeys = 0; break; } else { do_log2(loglevel, "Please enter " "\"yes\" or \"no\""); } } if (quit_pending || i >= 3 || response == NULL) options.update_hostkeys = 0; free(response); if (was_raw) enter_raw_mode(1); } if (options.update_hostkeys == 0) return; /* * Now that all the keys are verified, we can go ahead and replace * them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't * cancel the operation). */ for (i = 0; i < options.num_user_hostfiles; i++) { /* * NB. keys are only added to hostfiles[0], for the rest we * just delete the hostname entries. */ if (stat(options.user_hostfiles[i], &sb) != 0) { if (errno == ENOENT) { debug_f("known hosts file %s does not " "exist", options.user_hostfiles[i]); } else { error_f("known hosts file %s " "inaccessible: %s", options.user_hostfiles[i], strerror(errno)); } continue; } if ((r = hostfile_replace_entries(options.user_hostfiles[i], ctx->host_str, ctx->ip_str, i == 0 ? ctx->keys : NULL, i == 0 ? ctx->nkeys : 0, options.hash_known_hosts, 0, options.fingerprint_hash)) != 0) { error_fr(r, "hostfile_replace_entries failed for %s", options.user_hostfiles[i]); } } } static void client_global_hostkeys_prove_confirm(struct ssh *ssh, int type, u_int32_t seq, void *_ctx) { struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i, ndone; struct sshbuf *signdata; int r, plaintype; const u_char *sig; const char *rsa_kexalg = NULL; char *alg = NULL; size_t siglen; if (ctx->nnew == 0) fatal_f("ctx->nnew == 0"); /* sanity */ if (type != SSH2_MSG_REQUEST_SUCCESS) { error("Server failed to confirm ownership of " "private host keys"); hostkeys_update_ctx_free(ctx); return; } if (sshkey_type_plain(sshkey_type_from_name( ssh->kex->hostkey_alg)) == KEY_RSA) rsa_kexalg = ssh->kex->hostkey_alg; if ((signdata = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* * Expect a signature for each of the ctx->nnew private keys we * haven't seen before. They will be in the same order as the * ctx->keys where the corresponding ctx->keys_match[i] == 0. */ for (ndone = i = 0; i < ctx->nkeys; i++) { if (ctx->keys_match[i]) continue; plaintype = sshkey_type_plain(ctx->keys[i]->type); /* Prepare data to be signed: session ID, unique string, key */ sshbuf_reset(signdata); if ( (r = sshbuf_put_cstring(signdata, "hostkeys-prove-00@openssh.com")) != 0 || (r = sshbuf_put_stringb(signdata, ssh->kex->session_id)) != 0 || (r = sshkey_puts(ctx->keys[i], signdata)) != 0) fatal_fr(r, "compose signdata"); /* Extract and verify signature */ if ((r = sshpkt_get_string_direct(ssh, &sig, &siglen)) != 0) { error_fr(r, "parse sig"); goto out; } if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) { error_fr(r, "server gave unintelligible signature " "for %s key %zu", sshkey_type(ctx->keys[i]), i); goto out; } /* * Special case for RSA keys: if a RSA hostkey was negotiated, * then use its signature type for verification of RSA hostkey * proofs. Otherwise, accept only RSA-SHA256/512 signatures. */ if (plaintype == KEY_RSA && rsa_kexalg == NULL && match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) { debug_f("server used untrusted RSA signature algorithm " "%s for key %zu, disregarding", alg, i); free(alg); /* zap the key from the list */ sshkey_free(ctx->keys[i]); ctx->keys[i] = NULL; ndone++; continue; } debug3_f("verify %s key %zu using sigalg %s", sshkey_type(ctx->keys[i]), i, alg); free(alg); if ((r = sshkey_verify(ctx->keys[i], sig, siglen, sshbuf_ptr(signdata), sshbuf_len(signdata), plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) { error_fr(r, "server gave bad signature for %s key %zu", sshkey_type(ctx->keys[i]), i); goto out; } /* Key is good. Mark it as 'seen' */ ctx->keys_verified[i] = 1; ndone++; } /* Shouldn't happen */ if (ndone != ctx->nnew) fatal_f("ndone != ctx->nnew (%zu / %zu)", ndone, ctx->nnew); if ((r = sshpkt_get_end(ssh)) != 0) { error_f("protocol error"); goto out; } /* Make the edits to known_hosts */ update_known_hosts(ctx); out: hostkeys_update_ctx_free(ctx); hostkeys_update_complete = 1; client_repledge(); } /* * Handle hostkeys-00@openssh.com global request to inform the client of all * the server's hostkeys. The keys are checked against the user's * HostkeyAlgorithms preference before they are accepted. */ static int client_input_hostkeys(struct ssh *ssh) { const u_char *blob = NULL; size_t i, len = 0; struct sshbuf *buf = NULL; struct sshkey *key = NULL, **tmp; int r, prove_sent = 0; char *fp; static int hostkeys_seen = 0; /* XXX use struct ssh */ extern struct sockaddr_storage hostaddr; /* XXX from ssh.c */ struct hostkeys_update_ctx *ctx = NULL; u_int want; if (hostkeys_seen) fatal_f("server already sent hostkeys"); if (!can_update_hostkeys()) return 1; hostkeys_seen = 1; ctx = xcalloc(1, sizeof(*ctx)); while (ssh_packet_remaining(ssh) > 0) { sshkey_free(key); key = NULL; if ((r = sshpkt_get_string_direct(ssh, &blob, &len)) != 0) { error_fr(r, "parse key"); goto out; } if ((r = sshkey_from_blob(blob, len, &key)) != 0) { do_log2_fr(r, r == SSH_ERR_KEY_TYPE_UNKNOWN ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR, "convert key"); continue; } fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); debug3_f("received %s key %s", sshkey_type(key), fp); free(fp); if (!hostkey_accepted_by_hostkeyalgs(key)) { debug3_f("%s key not permitted by " "HostkeyAlgorithms", sshkey_ssh_name(key)); continue; } /* Skip certs */ if (sshkey_is_cert(key)) { debug3_f("%s key is a certificate; skipping", sshkey_ssh_name(key)); continue; } /* Ensure keys are unique */ for (i = 0; i < ctx->nkeys; i++) { if (sshkey_equal(key, ctx->keys[i])) { error_f("received duplicated %s host key", sshkey_ssh_name(key)); goto out; } } /* Key is good, record it */ if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1, sizeof(*ctx->keys))) == NULL) fatal_f("recallocarray failed nkeys = %zu", ctx->nkeys); ctx->keys = tmp; ctx->keys[ctx->nkeys++] = key; key = NULL; } if (ctx->nkeys == 0) { debug_f("server sent no hostkeys"); goto out; } if ((ctx->keys_match = calloc(ctx->nkeys, sizeof(*ctx->keys_match))) == NULL || (ctx->keys_verified = calloc(ctx->nkeys, sizeof(*ctx->keys_verified))) == NULL) fatal_f("calloc failed"); get_hostfile_hostname_ipaddr(host, options.check_host_ip ? (struct sockaddr *)&hostaddr : NULL, options.port, &ctx->host_str, options.check_host_ip ? &ctx->ip_str : NULL); /* Find which keys we already know about. */ for (i = 0; i < options.num_user_hostfiles; i++) { debug_f("searching %s for %s / %s", options.user_hostfiles[i], ctx->host_str, ctx->ip_str ? ctx->ip_str : "(none)"); if ((r = hostkeys_foreach(options.user_hostfiles[i], hostkeys_find, ctx, ctx->host_str, ctx->ip_str, HKF_WANT_PARSE_KEY, 0)) != 0) { if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { debug_f("hostkeys file %s does not exist", options.user_hostfiles[i]); continue; } error_fr(r, "hostkeys_foreach failed for %s", options.user_hostfiles[i]); goto out; } } /* Figure out if we have any new keys to add */ ctx->nnew = ctx->nincomplete = 0; want = HKF_MATCH_HOST | ( options.check_host_ip ? HKF_MATCH_IP : 0); for (i = 0; i < ctx->nkeys; i++) { if (ctx->keys_match[i] == 0) ctx->nnew++; if ((ctx->keys_match[i] & want) != want) ctx->nincomplete++; } debug3_f("%zu server keys: %zu new, %zu retained, " "%zu incomplete match. %zu to remove", ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew - ctx->nincomplete, ctx->nincomplete, ctx->nold); if (ctx->nnew == 0 && ctx->nold == 0) { debug_f("no new or deprecated keys from server"); goto out; } /* Various reasons why we cannot proceed with the update */ if (ctx->complex_hostspec) { debug_f("CA/revocation marker, manual host list or wildcard " "host pattern found, skipping UserKnownHostsFile update"); goto out; } if (ctx->other_name_seen) { debug_f("host key found matching a different name/address, " "skipping UserKnownHostsFile update"); goto out; } /* * If removing keys, check whether they appear under different * names/addresses and refuse to proceed if they do. This avoids * cases such as hosts with multiple names becoming inconsistent * with regards to CheckHostIP entries. * XXX UpdateHostkeys=force to override this (and other) checks? */ if (ctx->nold != 0) { if (check_old_keys_othernames(ctx) != 0) goto out; /* error already logged */ if (ctx->old_key_seen) { debug_f("key(s) for %s%s%s exist under other names; " "skipping UserKnownHostsFile update", ctx->host_str, ctx->ip_str == NULL ? "" : ",", ctx->ip_str == NULL ? "" : ctx->ip_str); goto out; } } if (ctx->nnew == 0) { /* * We have some keys to remove or fix matching for. * We can proceed to do this without requiring a fresh proof * from the server. */ update_known_hosts(ctx); goto out; } /* * We have received previously-unseen keys from the server. * Ask the server to confirm ownership of the private halves. */ debug3_f("asking server to prove ownership for %zu keys", ctx->nnew); if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "hostkeys-prove-00@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0) /* bool: want reply */ fatal_fr(r, "prepare hostkeys-prove"); if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); for (i = 0; i < ctx->nkeys; i++) { if (ctx->keys_match[i]) continue; sshbuf_reset(buf); if ((r = sshkey_putb(ctx->keys[i], buf)) != 0 || (r = sshpkt_put_stringb(ssh, buf)) != 0) fatal_fr(r, "assemble hostkeys-prove"); } if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send hostkeys-prove"); client_register_global_confirm( client_global_hostkeys_prove_confirm, ctx); ctx = NULL; /* will be freed in callback */ prove_sent = 1; /* Success */ out: hostkeys_update_ctx_free(ctx); sshkey_free(key); sshbuf_free(buf); if (!prove_sent) { /* UpdateHostkeys handling completed */ hostkeys_update_complete = 1; client_repledge(); } /* * NB. Return success for all cases. The server doesn't need to know * what the client does with its hosts file. */ return 1; } static int client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype; u_char want_reply; int r, success = 0; if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) goto out; debug("client_input_global_request: rtype %s want_reply %d", rtype, want_reply); if (strcmp(rtype, "hostkeys-00@openssh.com") == 0) success = client_input_hostkeys(ssh); if (want_reply) { if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) goto out; } r = 0; out: free(rtype); return r; } static void client_send_env(struct ssh *ssh, int id, const char *name, const char *val) { int r; debug("channel %d: setting env %s = \"%s\"", id, name, val); channel_request_start(ssh, id, "env", 0); if ((r = sshpkt_put_cstring(ssh, name)) != 0 || (r = sshpkt_put_cstring(ssh, val)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send setenv"); } void client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd, char **env) { size_t i, j, len; int matched, r; char *name, *val; Channel *c = NULL; debug2_f("id %d", id); if ((c = channel_lookup(ssh, id)) == NULL) fatal_f("channel %d: unknown channel", id); ssh_packet_set_interactive(ssh, want_tty, options.ip_qos_interactive, options.ip_qos_bulk); if (want_tty) { struct winsize ws; /* Store window size in the packet. */ if (ioctl(in_fd, TIOCGWINSZ, &ws) == -1) memset(&ws, 0, sizeof(ws)); channel_request_start(ssh, id, "pty-req", 1); client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); if ((r = sshpkt_put_cstring(ssh, term != NULL ? term : "")) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0) fatal_fr(r, "build pty-req"); if (tiop == NULL) tiop = get_saved_tio(); ssh_tty_make_modes(ssh, -1, tiop); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send pty-req"); /* XXX wait for reply */ c->client_tty = 1; } /* Transfer any environment variables from client to server */ if (options.num_send_env != 0 && env != NULL) { debug("Sending environment."); for (i = 0; env[i] != NULL; i++) { /* Split */ name = xstrdup(env[i]); if ((val = strchr(name, '=')) == NULL) { free(name); continue; } *val++ = '\0'; matched = 0; for (j = 0; j < options.num_send_env; j++) { if (match_pattern(name, options.send_env[j])) { matched = 1; break; } } if (!matched) { debug3("Ignored env %s", name); free(name); continue; } client_send_env(ssh, id, name, val); free(name); } } for (i = 0; i < options.num_setenv; i++) { /* Split */ name = xstrdup(options.setenv[i]); if ((val = strchr(name, '=')) == NULL) { free(name); continue; } *val++ = '\0'; client_send_env(ssh, id, name, val); free(name); } len = sshbuf_len(cmd); if (len > 0) { if (len > 900) len = 900; if (want_subsystem) { debug("Sending subsystem: %.*s", (int)len, (const u_char*)sshbuf_ptr(cmd)); channel_request_start(ssh, id, "subsystem", 1); client_expect_confirm(ssh, id, "subsystem", CONFIRM_CLOSE); } else { debug("Sending command: %.*s", (int)len, (const u_char*)sshbuf_ptr(cmd)); channel_request_start(ssh, id, "exec", 1); client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); } if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send command"); } else { channel_request_start(ssh, id, "shell", 1); client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send shell"); } session_setup_complete = 1; client_repledge(); } static void client_init_dispatch(struct ssh *ssh) { ssh_dispatch_init(ssh, &dispatch_protocol_error); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm); ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); /* rekeying */ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); /* global request reply messages */ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); } void client_stop_mux(void) { if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); /* * If we are in persist mode, or don't have a shell, signal that we * should close when all active channels are closed. */ if (options.control_persist || options.session_type == SESSION_TYPE_NONE) { session_closed = 1; setproctitle("[stopped mux]"); } } /* client specific fatal cleanup */ void cleanup_exit(int i) { leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); ssh_kill_proxy_command(); _exit(i); } openssh-10.0p1/PaxHeaders.10889/clientloop.h100644 001750 001750 0000000003614775415623 0015475xustar0030 atime=1744182234.531078306 openssh-10.0p1/clientloop.h010064400017500001750000000072411477541562300140640ustar00djmdjm/* $OpenBSD: clientloop.h,v 1.38 2024/05/17 06:42:04 jsg Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 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 struct ssh; /* Client side main loop for the interactive session. */ 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_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(struct ssh *, int, void *); int client_simple_escape_filter(struct ssh *, Channel *, char *, int); /* Global request confirmation callbacks */ 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(struct ssh *, int, const char *, enum confirm_action); /* Multiplexing protocol version */ #define SSHMUX_VER 4 /* Multiplexing control protocol flags */ #define SSHMUX_COMMAND_OPEN 1 /* Open new connection */ #define SSHMUX_COMMAND_ALIVE_CHECK 2 /* Check master is alive */ #define SSHMUX_COMMAND_TERMINATE 3 /* Ask master to exit */ #define SSHMUX_COMMAND_STDIO_FWD 4 /* Open stdio fwd (ssh -W) */ #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(struct ssh *); int muxclient(const char *); void mux_exit_message(struct ssh *, Channel *, int); void mux_tty_alloc_failed(struct ssh *ssh, Channel *); openssh-10.0p1/PaxHeaders.10889/compat.c100644 001750 001750 0000000003614775415623 0014603xustar0030 atime=1744182234.531078306 openssh-10.0p1/compat.c010064400017500001750000000121321477541562300131650ustar00djmdjm/* $OpenBSD: compat.c,v 1.126 2023/03/06 12:14:48 dtucker Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include "xmalloc.h" #include "packet.h" #include "compat.h" #include "log.h" #include "match.h" /* determine bug flags from SSH protocol banner */ void compat_banner(struct ssh *ssh, const char *version) { int i; static struct { char *pat; int bugs; } check[] = { { "OpenSSH_2.*," "OpenSSH_3.0*," "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| SSH_BUG_SIGTYPE}, { "OpenSSH_7.4*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE| SSH_BUG_SIGTYPE74}, { "OpenSSH_7.0*," "OpenSSH_7.1*," "OpenSSH_7.2*," "OpenSSH_7.3*," "OpenSSH_7.5*," "OpenSSH_7.6*," "OpenSSH_7.7*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE}, { "OpenSSH*", SSH_NEW_OPENSSH }, { "*MindTerm*", 0 }, { "3.0.*", SSH_BUG_DEBUG }, { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, { "1.7 SecureFX*", SSH_OLD_SESSIONID }, { "Cisco-1.*", SSH_BUG_DHGEX_LARGE| SSH_BUG_HOSTKEYS }, { "*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 */ ssh->compat = 0; for (i = 0; check[i].pat; i++) { if (match_pattern_list(version, check[i].pat, 0) == 1) { debug_f("match: %s pat %s compat 0x%08x", version, check[i].pat, check[i].bugs); ssh->compat = check[i].bugs; return; } } debug_f("no match: %s", version); } /* Always returns pointer to allocated memory, caller must free. */ char * compat_kex_proposal(struct ssh *ssh, const char *p) { char *cp = NULL, *cp2 = NULL; if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) return xstrdup(p); debug2_f("original KEX proposal: %s", p); if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) if ((cp = match_filter_denylist(p, "curve25519-sha256@libssh.org")) == NULL) fatal("match_filter_denylist failed"); if ((ssh->compat & SSH_OLD_DHGEX) != 0) { if ((cp2 = match_filter_denylist(cp ? cp : p, "diffie-hellman-group-exchange-sha256," "diffie-hellman-group-exchange-sha1")) == NULL) fatal("match_filter_denylist failed"); free(cp); cp = cp2; } if (cp == NULL || *cp == '\0') fatal("No supported key exchange algorithms found"); debug2_f("compat KEX proposal: %s", cp); return cp; } openssh-10.0p1/PaxHeaders.10889/compat.h100644 001750 001750 0000000003614775415623 0014610xustar0030 atime=1744182234.531078306 openssh-10.0p1/compat.h010064400017500001750000000050631477541562300131770ustar00djmdjm/* $OpenBSD: compat.h,v 1.62 2023/03/06 12:14:48 dtucker Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef COMPAT_H #define COMPAT_H #define SSH_BUG_UTF8TTYMODE 0x00000001 #define SSH_BUG_SIGTYPE 0x00000002 #define SSH_BUG_SIGTYPE74 0x00000004 /* #define unused 0x00000008 */ #define SSH_OLD_SESSIONID 0x00000010 /* #define unused 0x00000020 */ #define SSH_BUG_DEBUG 0x00000040 /* #define unused 0x00000080 */ /* #define unused 0x00000100 */ /* #define unused 0x00000200 */ /* #define unused 0x00000400 */ #define SSH_BUG_SCANNER 0x00000800 /* #define unused 0x00001000 */ /* #define unused 0x00002000 */ #define SSH_OLD_DHGEX 0x00004000 #define SSH_BUG_NOREKEY 0x00008000 /* #define unused 0x00010000 */ /* #define unused 0x00020000 */ /* #define unused 0x00040000 */ /* #define unused 0x00100000 */ #define SSH_BUG_EXTEOF 0x00200000 #define SSH_BUG_PROBE 0x00400000 /* #define unused 0x00800000 */ #define SSH_OLD_FORWARD_ADDR 0x01000000 /* #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 struct ssh; void compat_banner(struct ssh *, const char *); char *compat_kex_proposal(struct ssh *, const char *); #endif openssh-10.0p1/PaxHeaders.10889/config.guess100755 001750 001750 0000000003614775415623 0015474xustar0030 atime=1744182234.533031942 openssh-10.0p1/config.guess010075500017500001750000001414221477541562300140630ustar00djmdjm#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-09-17' # 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # 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"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. 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 Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2022 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." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # Just in case it came from the environment. GUESS= # 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 # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. 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,SC3028 { 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 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown 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/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. 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*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) 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 Debian*) release='-gnu' ;; *) 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. GUESS=$machine-${os}${release}${abi-} ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ;; *:SecBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ;; *:MidnightBSD:*:*) GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ;; *:ekkoBSD:*:*) GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ;; *:SolidBSD:*:*) GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ;; *:OS108:*:*) GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ;; macppc:MirBSD:*:*) GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ;; *:MirBSD:*:*) GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ;; *:Sortix:*:*) GUESS=$UNAME_MACHINE-unknown-sortix ;; *:Twizzler:*:*) GUESS=$UNAME_MACHINE-unknown-twizzler ;; *:Redox:*:*) GUESS=$UNAME_MACHINE-unknown-redox ;; mips:OSF1:*.*) GUESS=mips-dec-osf1 ;; alpha:OSF1:*:*) # Reset EXIT trap before exiting to avoid spurious non-zero exit code. trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. 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 ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") 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. OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ;; Amiga*:UNIX_System_V:4.0:*) GUESS=m68k-unknown-sysv4 ;; *:[Aa]miga[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-amigaos ;; *:[Mm]orph[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-morphos ;; *:OS/390:*:*) GUESS=i370-ibm-openedition ;; *:z/VM:*:*) GUESS=s390-ibm-zvmoe ;; *:OS400:*:*) GUESS=powerpc-ibm-os400 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) GUESS=arm-acorn-riscix$UNAME_RELEASE ;; arm*:riscos:*:*|arm*:RISCOS:*:*) GUESS=arm-unknown-riscos ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) GUESS=hppa1.1-hitachi-hiuxmpp ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. case `(/bin/universe) 2>/dev/null` in att) GUESS=pyramid-pyramid-sysv3 ;; *) GUESS=pyramid-pyramid-bsd ;; esac ;; NILE*:*:*:dcosx) GUESS=pyramid-pyramid-svr4 ;; DRS?6000:unix:4.0:6*) GUESS=sparc-icl-nx6 ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) GUESS=sparc-icl-nx7 ;; esac ;; s390x:SunOS:*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ;; sun4H:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-hal-solaris2$SUN_REL ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris2$SUN_REL ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) GUESS=i386-pc-auroraux$UNAME_RELEASE ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) 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 test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ;; 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. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris3$SUN_REL ;; sun4*:SunOS:*:*) case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; sun3*:SunOS:*:*) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; 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 case `/bin/arch` in sun3) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac ;; aushp:SunOS:*:*) GUESS=sparc-auspex-sunos$UNAME_RELEASE ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) GUESS=m68k-milan-mint$UNAME_RELEASE ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) GUESS=m68k-hades-mint$UNAME_RELEASE ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) GUESS=m68k-unknown-mint$UNAME_RELEASE ;; m68k:machten:*:*) GUESS=m68k-apple-machten$UNAME_RELEASE ;; powerpc:machten:*:*) GUESS=powerpc-apple-machten$UNAME_RELEASE ;; RISC*:Mach:*:*) GUESS=mips-dec-mach_bsd4.3 ;; RISC*:ULTRIX:*:*) GUESS=mips-dec-ultrix$UNAME_RELEASE ;; VAX*:ULTRIX*:*:*) GUESS=vax-dec-ultrix$UNAME_RELEASE ;; 2020:CLIX:*:* | 2430:CLIX:*:*) GUESS=clipper-intergraph-clix$UNAME_RELEASE ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) 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); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) 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"` && { echo "$SYSTEM_NAME"; exit; } GUESS=mips-mips-riscos$UNAME_RELEASE ;; Motorola:PowerMAX_OS:*:*) GUESS=powerpc-motorola-powermax ;; Motorola:*:4.3:PL8-*) GUESS=powerpc-harris-powermax ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) GUESS=powerpc-harris-powermax ;; Night_Hawk:Power_UNIX:*:*) GUESS=powerpc-harris-powerunix ;; m88k:CX/UX:7*:*) GUESS=m88k-harris-cxux7 ;; m88k:*:4*:R4*) GUESS=m88k-motorola-sysv4 ;; m88k:*:3*:R3*) GUESS=m88k-motorola-sysv3 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then GUESS=m88k-dg-dgux$UNAME_RELEASE else GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else GUESS=i586-dg-dgux$UNAME_RELEASE fi ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) GUESS=m88k-dolphin-sysv3 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 GUESS=m88k-motorola-sysv3 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) GUESS=m88k-tektronix-sysv3 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) GUESS=m68k-tektronix-bsd ;; *:IRIX*:*:*) IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` GUESS=mips-sgi-irix$IRIX_REL ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) GUESS=i386-ibm-aix ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then GUESS=$SYSTEM_NAME else GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then GUESS=rs6000-ibm-aix3.2.4 else GUESS=rs6000-ibm-aix3.2 fi ;; *: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 IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -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 fi GUESS=$IBM_ARCH-ibm-aix$IBM_REV ;; *:AIX:*:*) GUESS=rs6000-ibm-aix ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) GUESS=romp-ibm-bsd4.4 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) GUESS=rs6000-bull-bosx ;; DPX/2?00:B.O.S.:*:*) GUESS=m68k-bull-sysv3 ;; 9000/[34]??:4.3bsd:1.*:*) GUESS=m68k-hp-bsd ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) GUESS=m68k-hp-bsd4.4 ;; 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 ;; 9000/[678][0-9][0-9]) if test -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 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 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then 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 # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi GUESS=$HP_ARCH-hp-hpux$HPUX_REV ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` GUESS=ia64-hp-hpux$HPUX_REV ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } GUESS=unknown-hitachi-hiuxwe2 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) GUESS=hppa1.1-hp-bsd ;; 9000/8??:4.3bsd:*:*) GUESS=hppa1.0-hp-bsd ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) GUESS=hppa1.0-hp-mpeix ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) GUESS=hppa1.1-hp-osf ;; hp8??:OSF1:*:*) GUESS=hppa1.0-hp-osf ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then GUESS=$UNAME_MACHINE-unknown-osf1mk else GUESS=$UNAME_MACHINE-unknown-osf1 fi ;; parisc*:Lites*:*:*) GUESS=hppa1.1-hp-lites ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) GUESS=c1-convex-bsd ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) GUESS=c34-convex-bsd ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) GUESS=c38-convex-bsd ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) GUESS=c4-convex-bsd ;; CRAY*Y-MP:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=ymp-cray-unicos$CRAY_REL ;; CRAY*[A-Z]90:*:*:*) 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:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=t90-cray-unicos$CRAY_REL ;; CRAY*T3E:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=alphaev5-cray-unicosmk$CRAY_REL ;; CRAY*SV1:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=sv1-cray-unicos$CRAY_REL ;; *:UNICOS/mp:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=craynv-cray-unicosmp$CRAY_REL ;; 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/ /_/'` GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; 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/ /_/'` GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ;; sparc*:BSD/OS:*:*) GUESS=sparc-unknown-bsdi$UNAME_RELEASE ;; *:BSD/OS:*:*) GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ;; 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 FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ;; i*:CYGWIN*:*) GUESS=$UNAME_MACHINE-pc-cygwin ;; *:MINGW64*:*) GUESS=$UNAME_MACHINE-pc-mingw64 ;; *:MINGW*:*) GUESS=$UNAME_MACHINE-pc-mingw32 ;; *:MSYS*:*) GUESS=$UNAME_MACHINE-pc-msys ;; i*:PW*:*) GUESS=$UNAME_MACHINE-pc-pw32 ;; *:SerenityOS:*:*) GUESS=$UNAME_MACHINE-pc-serenity ;; *:Interix*:*) case $UNAME_MACHINE in x86) GUESS=i586-pc-interix$UNAME_RELEASE ;; authenticamd | genuineintel | EM64T) GUESS=x86_64-unknown-interix$UNAME_RELEASE ;; IA64) GUESS=ia64-unknown-interix$UNAME_RELEASE ;; esac ;; i*:UWIN*:*) GUESS=$UNAME_MACHINE-pc-uwin ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) GUESS=x86_64-pc-cygwin ;; prep*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=powerpcle-unknown-solaris2$SUN_REL ;; *:GNU:*:*) # the GNU system GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ;; *:GNU/*:*:*) # other systems with GNU libc and userland GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-pc-managarm-mlibc" ;; *:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; alpha:Linux:*:*) 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 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi ;; avr32*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; cris:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; crisv32:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; e2k:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; frv:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; hexagon:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:Linux:*:*) GUESS=$UNAME_MACHINE-pc-linux-$LIBC ;; ia64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; loongarch32:Linux:*:* | loongarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m68*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #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) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; openrisc*:Linux:*:*) GUESS=or1k-unknown-linux-$LIBC ;; or32:Linux:*:* | or1k*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; padre:Linux:*:*) GUESS=sparc-unknown-linux-$LIBC ;; parisc64:Linux:*:* | hppa64:Linux:*:*) GUESS=hppa64-unknown-linux-$LIBC ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; *) GUESS=hppa-unknown-linux-$LIBC ;; esac ;; ppc64:Linux:*:*) GUESS=powerpc64-unknown-linux-$LIBC ;; ppc:Linux:*:*) GUESS=powerpc-unknown-linux-$LIBC ;; ppc64le:Linux:*:*) GUESS=powerpc64le-unknown-linux-$LIBC ;; ppcle:Linux:*:*) GUESS=powerpcle-unknown-linux-$LIBC ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; s390:Linux:*:* | s390x:Linux:*:*) GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ;; sh64*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sh*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; vax:Linux:*:*) GUESS=$UNAME_MACHINE-dec-linux-$LIBC ;; x86_64:Linux:*:*) set_cc_for_build CPU=$UNAME_MACHINE LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then ABI=64 sed 's/^ //' << EOF > "$dummy.c" #ifdef __i386__ ABI=x86 #else #ifdef __ILP32__ ABI=x32 #endif #endif EOF cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` eval "$cc_set_abi" case $ABI in x86) CPU=i686 ;; x32) LIBCABI=${LIBC}x32 ;; esac fi GUESS=$CPU-pc-linux-$LIBCABI ;; xtensa*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. GUESS=i386-sequent-sysv4 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # 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. GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; i*86:XTS-300:*:STOP) GUESS=$UNAME_MACHINE-unknown-stop ;; i*86:atheos:*:*) GUESS=$UNAME_MACHINE-unknown-atheos ;; i*86:syllable:*:*) GUESS=$UNAME_MACHINE-pc-syllable ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) GUESS=i386-unknown-lynxos$UNAME_RELEASE ;; i*86:*DOS:*:*) GUESS=$UNAME_MACHINE-pc-msdosdjgpp ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv32 fi ;; pc:*:*:*) # Left here for compatibility: # 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 configure will decide that # this is a cross-build. GUESS=i586-pc-msdosdjgpp ;; Intel:Mach:3*:*) GUESS=i386-pc-mach3 ;; paragon:*:*:*) GUESS=i860-intel-osf1 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi ;; mini*:CTIX:SYS*5:*) # "miniframe" GUESS=m68010-convergent-sysv ;; mc68k:UNIX:SYSTEM5:3.51m) GUESS=m68k-convergent-sysv ;; M680?0:D-NIX:5.3:*) GUESS=m68k-diab-dnix ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' 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; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { 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; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' 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; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { 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; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) GUESS=m68k-unknown-lynxos$UNAME_RELEASE ;; mc68030:UNIX_System_V:4.*:*) GUESS=m68k-atari-sysv4 ;; TSUNAMI:LynxOS:2.*:*) GUESS=sparc-unknown-lynxos$UNAME_RELEASE ;; rs6000:LynxOS:2.*:*) GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ;; SM[BE]S:UNIX_SV:*:*) GUESS=mips-dde-sysv$UNAME_RELEASE ;; RM*:ReliantUNIX-*:*:*) GUESS=mips-sni-sysv4 ;; RM*:SINIX-*:*:*) GUESS=mips-sni-sysv4 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` GUESS=$UNAME_MACHINE-sni-sysv4 else GUESS=ns32k-sni-sysv fi ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm GUESS=hppa1.1-stratus-sysv4 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. GUESS=i860-stratus-sysv4 ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. GUESS=$UNAME_MACHINE-stratus-vos ;; *:VOS:*:*) # From Paul.Green@stratus.com. GUESS=hppa1.1-stratus-vos ;; mc68*:A/UX:*:*) GUESS=m68k-apple-aux$UNAME_RELEASE ;; news*:NEWS-OS:6*:*) GUESS=mips-sony-newsos6 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then GUESS=mips-nec-sysv$UNAME_RELEASE else GUESS=mips-unknown-sysv$UNAME_RELEASE fi ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. GUESS=powerpc-be-beos ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. GUESS=powerpc-apple-beos ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. GUESS=i586-pc-beos ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; ppc:Haiku:*:*) # Haiku running on Apple PowerPC GUESS=powerpc-apple-haiku ;; *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) GUESS=$UNAME_MACHINE-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE ;; SX-5:SUPER-UX:*:*) GUESS=sx5-nec-superux$UNAME_RELEASE ;; SX-6:SUPER-UX:*:*) GUESS=sx6-nec-superux$UNAME_RELEASE ;; SX-7:SUPER-UX:*:*) GUESS=sx7-nec-superux$UNAME_RELEASE ;; SX-8:SUPER-UX:*:*) GUESS=sx8-nec-superux$UNAME_RELEASE ;; SX-8R:SUPER-UX:*:*) GUESS=sx8r-nec-superux$UNAME_RELEASE ;; SX-ACE:SUPER-UX:*:*) GUESS=sxace-nec-superux$UNAME_RELEASE ;; Power*:Rhapsody:*:*) GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ;; *:Rhapsody:*:*) GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ;; arm64:Darwin:*:*) GUESS=aarch64-apple-darwin$UNAME_RELEASE ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$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 GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ;; *:QNX:*:4*) GUESS=i386-pc-qnx ;; NEO-*:NONSTOP_KERNEL:*:*) GUESS=neo-tandem-nsk$UNAME_RELEASE ;; NSE-*:NONSTOP_KERNEL:*:*) GUESS=nse-tandem-nsk$UNAME_RELEASE ;; NSR-*:NONSTOP_KERNEL:*:*) GUESS=nsr-tandem-nsk$UNAME_RELEASE ;; NSV-*:NONSTOP_KERNEL:*:*) GUESS=nsv-tandem-nsk$UNAME_RELEASE ;; NSX-*:NONSTOP_KERNEL:*:*) GUESS=nsx-tandem-nsk$UNAME_RELEASE ;; *:NonStop-UX:*:*) GUESS=mips-compaq-nonstopux ;; BS2000:POSIX*:*:*) GUESS=bs2000-siemens-sysv ;; DS/*:UNIX_System_V:*:*) GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ;; *: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 UNAME_MACHINE=i386 elif test "x${cputype-}" != x; then UNAME_MACHINE=$cputype fi GUESS=$UNAME_MACHINE-unknown-plan9 ;; *:TOPS-10:*:*) GUESS=pdp10-unknown-tops10 ;; *:TENEX:*:*) GUESS=pdp10-unknown-tenex ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) GUESS=pdp10-dec-tops20 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) GUESS=pdp10-xkl-tops20 ;; *:TOPS-20:*:*) GUESS=pdp10-unknown-tops20 ;; *:ITS:*:*) GUESS=pdp10-unknown-its ;; SEI:*:*:SEIUX) GUESS=mips-sei-seiux$UNAME_RELEASE ;; *:DragonFly:*:*) DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case $UNAME_MACHINE in A*) GUESS=alpha-dec-vms ;; I*) GUESS=ia64-dec-vms ;; V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) GUESS=i386-pc-xenix ;; i*86:skyos:*:*) SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ;; i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; i*86:Fiwix:*:*) GUESS=$UNAME_MACHINE-pc-fiwix ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; x86_64:VMkernel:*:*) GUESS=$UNAME_MACHINE-unknown-esx ;; amd64:Isilon\ OneFS:*:*) GUESS=x86_64-unknown-onefs ;; *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; esac # Do we have a guess based on uname results? if test "x$GUESS" != x; then echo "$GUESS" exit fi # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || 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` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 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" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: openssh-10.0p1/PaxHeaders.10889/config.h.in100644 001750 001750 0000000003614775415623 0015177xustar0030 atime=1744182234.534008599 openssh-10.0p1/config.h.in010064400017500001750000001532551477541562300135750ustar00djmdjm/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address */ #undef AIX_GETNAMEINFO_HACK /* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */ #undef AIX_LOGINFAILED_4ARG /* System only supports IPv4 audit records */ #undef AU_IPv4 /* Define if your resolver libs need this for getrrsetbyname */ #undef BIND_8_COMPAT /* The system has incomplete BSM API */ #undef BROKEN_BSM_API /* broken in chroots on older kernels */ #undef BROKEN_CLOSEFROM /* Define if cmsg_type is not passed correctly */ #undef BROKEN_CMSG_TYPE /* getaddrinfo is broken (if present) */ #undef BROKEN_GETADDRINFO /* getgroups(0,NULL) will return -1 */ #undef BROKEN_GETGROUPS /* getline is not what we expect */ #undef BROKEN_GETLINE /* FreeBSD glob does not do what we need */ #undef BROKEN_GLOB /* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ #undef BROKEN_INET_NTOA /* Define if your struct dirent expects you to allocate extra space for d_name */ #undef BROKEN_ONE_BYTE_DIRENT_D_NAME /* System poll(2) implementation is broken */ #undef BROKEN_POLL /* Can't do comparisons on readv */ #undef BROKEN_READV_COMPARISON /* NetBSD read function is sometimes redirected, breaking atomicio comparisons against it */ #undef BROKEN_READ_COMPARISON /* Needed for NeXT */ #undef BROKEN_SAVED_UIDS /* Define if your setregid() is broken */ #undef BROKEN_SETREGID /* Define if your setresgid() is broken */ #undef BROKEN_SETRESGID /* Define if your setresuid() is broken */ #undef BROKEN_SETRESUID /* Define if your setreuid() is broken */ #undef BROKEN_SETREUID /* LynxOS has broken setvbuf() implementation */ #undef BROKEN_SETVBUF /* QNX shadow support is broken */ #undef BROKEN_SHADOW_EXPIRE /* Define if your snprintf is busted */ #undef BROKEN_SNPRINTF /* strndup broken, see APAR IY61211 */ #undef BROKEN_STRNDUP /* strnlen broken, see APAR IY62551 */ #undef BROKEN_STRNLEN /* strnvis detected broken */ #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 /* Need to call setpgrp as root */ #undef DISABLE_FD_PASSING /* Define if you don't want to use lastlog */ #undef DISABLE_LASTLOG /* Define if you don't want to use your system's login() call */ #undef DISABLE_LOGIN /* Define if you don't want to use pututline() etc. to write [uw]tmp */ #undef DISABLE_PUTUTLINE /* Define if you don't want to use pututxline() etc. to write [uw]tmpx */ #undef DISABLE_PUTUTXLINE /* Define if you want to disable shadow passwords */ #undef DISABLE_SHADOW /* Define if you don't want to use utmp */ #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 /* Enable for U2F/FIDO support */ #undef ENABLE_SK /* Enable for built-in U2F/FIDO support */ #undef ENABLE_SK_INTERNAL /* define if fflush(NULL) does not work */ #undef FFLUSH_NULL_BUG /* File names may not contain backslash characters */ #undef FILESYSTEM_NO_BACKSLASH /* fsid_t has member val */ #undef FSID_HAS_VAL /* fsid_t has member __val */ #undef FSID_HAS___VAL /* getpgrp takes one arg */ #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 `auth_hostok' function. */ #undef HAVE_AUTH_HOSTOK /* Define to 1 if you have the `auth_timeok' function. */ #undef HAVE_AUTH_TIMEOK /* 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 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 header file. */ #undef HAVE_BSD_LIBUTIL_H /* Define to 1 if you have the header file. */ #undef HAVE_BSM_AUDIT_H /* Define to 1 if you have the header file. */ #undef HAVE_BSTRING_H /* Define to 1 if you have the `bzero' function. */ #undef HAVE_BZERO /* calloc(0, x) returns NULL */ #undef HAVE_CALLOC /* Define if you have caph_cache_tzdata */ #undef HAVE_CAPH_CACHE_TZDATA /* Define to 1 if you have the header file. */ #undef HAVE_CAPSICUM_HELPERS_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 to 1 if you have the `close_range' function. */ #undef HAVE_CLOSE_RANGE /* 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 header file. */ #undef HAVE_CRYPTO_SHA2_H /* Define to 1 if you have the header file. */ #undef HAVE_CRYPT_H /* Define if you are on Cygwin */ #undef HAVE_CYGWIN /* Define if your libraries define daemon() */ #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 `bzero', and to 0 if you don't. */ #undef HAVE_DECL_BZERO /* Define to 1 if you have the declaration of `ftruncate', and to 0 if you don't. */ #undef HAVE_DECL_FTRUNCATE /* Define to 1 if you have the declaration of `getentropy', and to 0 if you don't. */ #undef HAVE_DECL_GETENTROPY /* Define to 1 if you have the declaration of `getpeereid', and to 0 if you don't. */ #undef HAVE_DECL_GETPEEREID /* 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 `htole64', and to 0 if you don't. */ #undef HAVE_DECL_HTOLE64 /* 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 `le32toh', and to 0 if you don't. */ #undef HAVE_DECL_LE32TOH /* Define to 1 if you have the declaration of `le64toh', and to 0 if you don't. */ #undef HAVE_DECL_LE64TOH /* 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 `memmem', and to 0 if you don't. */ #undef HAVE_DECL_MEMMEM /* 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 `readv', and to 0 if you don't. */ #undef HAVE_DECL_READV /* 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 `UINT32_MAX', and to 0 if you don't. */ #undef HAVE_DECL_UINT32_MAX /* 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 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 `dlopen' function. */ #undef HAVE_DLOPEN /* Define to 1 if you have the `DSA_generate_parameters_ex' function. */ #undef HAVE_DSA_GENERATE_PARAMETERS_EX /* Define to 1 if you have the `EC_KEY_METHOD_new' function. */ #undef HAVE_EC_KEY_METHOD_NEW /* Define to 1 if you have the 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 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 to 1 if you have the `err' function. */ #undef HAVE_ERR /* Define to 1 if you have the `errx' function. */ #undef HAVE_ERRX /* Define to 1 if you have the header file. */ #undef HAVE_ERR_H /* Define if your system has /etc/default/login */ #undef HAVE_ETC_DEFAULT_LOGIN /* Define to 1 if you have the `EVP_chacha20' function. */ #undef HAVE_EVP_CHACHA20 /* Define to 1 if you have the `EVP_CIPHER_CTX_get_iv' function. */ #undef HAVE_EVP_CIPHER_CTX_GET_IV /* Define to 1 if you have the `EVP_CIPHER_CTX_get_updated_iv' function. */ #undef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV /* Define to 1 if you have the `EVP_CIPHER_CTX_iv' function. */ #undef HAVE_EVP_CIPHER_CTX_IV /* Define to 1 if you have the `EVP_CIPHER_CTX_iv_noconst' function. */ #undef HAVE_EVP_CIPHER_CTX_IV_NOCONST /* Define to 1 if you have the `EVP_CIPHER_CTX_set_iv' function. */ #undef HAVE_EVP_CIPHER_CTX_SET_IV /* Define to 1 if you have the `EVP_DigestFinal_ex' function. */ #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_DigestSign' function. */ #undef HAVE_EVP_DIGESTSIGN /* Define to 1 if you have the `EVP_DigestVerify' function. */ #undef HAVE_EVP_DIGESTVERIFY /* 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_PKEY_get_raw_private_key' function. */ #undef HAVE_EVP_PKEY_GET_RAW_PRIVATE_KEY /* Define to 1 if you have the `EVP_PKEY_get_raw_public_key' function. */ #undef HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY /* Define to 1 if you have the `EVP_sha256' function. */ #undef HAVE_EVP_SHA256 /* Define to 1 if you have the `EVP_sha384' function. */ #undef HAVE_EVP_SHA384 /* Define to 1 if you have the `EVP_sha512' function. */ #undef HAVE_EVP_SHA512 /* 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 `explicit_memset' function. */ #undef HAVE_EXPLICIT_MEMSET /* Define to 1 if you have the `fchmod' function. */ #undef HAVE_FCHMOD /* Define to 1 if you have the `fchmodat' function. */ #undef HAVE_FCHMODAT /* Define to 1 if you have the `fchown' function. */ #undef HAVE_FCHOWN /* Define to 1 if you have the `fchownat' function. */ #undef HAVE_FCHOWNAT /* Use F_CLOSEM fcntl for closefrom */ #undef HAVE_FCNTL_CLOSEM /* Define to 1 if you have the 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 header file. */ #undef HAVE_FEATURES_H /* Define to 1 if you have the `fido_assert_set_clientdata' function. */ #undef HAVE_FIDO_ASSERT_SET_CLIENTDATA /* Define to 1 if you have the `fido_cred_prot' function. */ #undef HAVE_FIDO_CRED_PROT /* Define to 1 if you have the `fido_cred_set_clientdata' function. */ #undef HAVE_FIDO_CRED_SET_CLIENTDATA /* Define to 1 if you have the `fido_cred_set_prot' function. */ #undef HAVE_FIDO_CRED_SET_PROT /* Define to 1 if you have the `fido_dev_get_touch_begin' function. */ #undef HAVE_FIDO_DEV_GET_TOUCH_BEGIN /* Define to 1 if you have the `fido_dev_get_touch_status' function. */ #undef HAVE_FIDO_DEV_GET_TOUCH_STATUS /* Define to 1 if you have the `fido_dev_is_winhello' function. */ #undef HAVE_FIDO_DEV_IS_WINHELLO /* Define to 1 if you have the `fido_dev_supports_cred_prot' function. */ #undef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT /* Define to 1 if you have the header file. */ #undef HAVE_FLOATINGPOINT_H /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK /* Define to 1 if you have the `fmt_scaled' function. */ #undef HAVE_FMT_SCALED /* Define to 1 if you have the `fnmatch' function. */ #undef HAVE_FNMATCH /* Define to 1 if you have the header file. */ #undef HAVE_FNMATCH_H /* Define to 1 if you have the `freeaddrinfo' function. */ #undef HAVE_FREEADDRINFO /* Define to 1 if you have the `freezero' function. */ #undef HAVE_FREEZERO /* 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 `getentropy' function. */ #undef HAVE_GETENTROPY /* 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 `getline' function. */ #undef HAVE_GETLINE /* 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 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 `getrandom' function. */ #undef HAVE_GETRANDOM /* 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 `getseuserbyname' function. */ #undef HAVE_GETSEUSERBYNAME /* Define to 1 if you have the `getsid' function. */ #undef HAVE_GETSID /* 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 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 header file. */ #undef HAVE_GSSAPI_GENERIC_H /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_GSSAPI_GENERIC_H /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_GSSAPI_H /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_GSSAPI_KRB5_H /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_H /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_KRB5_H /* Define if HEADER.ad exists in arpa/nameser.h */ #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 header file. */ #undef HAVE_IAF_H /* Define to 1 if you have the header file. */ #undef HAVE_IA_H /* Define if you have ut_id in utmp.h */ #undef HAVE_ID_IN_UTMP /* Define if you have ut_id in utmpx.h */ #undef HAVE_ID_IN_UTMPX /* Define to 1 if you have the header file. */ #undef HAVE_IFADDRS_H /* 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 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 `killpg' function. */ #undef HAVE_KILLPG /* Define to 1 if you have the `krb5_cc_new_unique' function. */ #undef HAVE_KRB5_CC_NEW_UNIQUE /* Define to 1 if you have the `krb5_free_error_message' function. */ #undef HAVE_KRB5_FREE_ERROR_MESSAGE /* Define to 1 if you have the `krb5_get_error_message' function. */ #undef HAVE_KRB5_GET_ERROR_MESSAGE /* Define to 1 if you have the header file. */ #undef HAVE_LANGINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_LASTLOG_H /* Define if you want ldns support */ #undef HAVE_LDNS /* Define to 1 if you have the header file. */ #undef HAVE_LIBAUDIT_H /* Define to 1 if you have the `bsm' library (-lbsm). */ #undef HAVE_LIBBSM /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the 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 `pam' library (-lpam). */ #undef HAVE_LIBPAM /* Define to 1 if you have the header file. */ #undef HAVE_LIBPROC_H /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define to 1 if you have the header file. */ #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 header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_AUDIT_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_FILTER_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_IF_TUN_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_SECCOMP_H /* Define to 1 if you have the `llabs' function. */ #undef HAVE_LLABS /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* Define to 1 if you have the `login' function. */ #undef HAVE_LOGIN /* Define to 1 if you have the 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_getpwclass' function. */ #undef HAVE_LOGIN_GETPWCLASS /* Define to 1 if you have the header file. */ #undef HAVE_LOGIN_H /* Define to 1 if you have the `logout' function. */ #undef HAVE_LOGOUT /* Define to 1 if you have the `logwtmp' function. */ #undef HAVE_LOGWTMP /* Define to 1 if the system has the type `long double'. */ #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 header file. */ #undef HAVE_MAILLOCK_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the `mblen' function. */ #undef HAVE_MBLEN /* Define to 1 if you have the `mbtowc' function. */ #undef HAVE_MBTOWC /* Define to 1 if you have the `memmem' function. */ #undef HAVE_MEMMEM /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* 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 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 header file. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETGROUP_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_TUN_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_ROUTE_H /* Define if you are on NeXT */ #undef HAVE_NEXT /* Define to 1 if the system has the type `nfds_t'. */ #undef HAVE_NFDS_T /* Define to 1 if you have the `ngetaddrinfo' function. */ #undef HAVE_NGETADDRINFO /* Define to 1 if you have the `nl_langinfo' function. */ #undef HAVE_NL_LANGINFO /* 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 /* as a macro */ #undef HAVE_OPENSSL_ADD_ALL_ALGORITHMS /* Define to 1 if you have the `OpenSSL_version' function. */ #undef HAVE_OPENSSL_VERSION /* Define to 1 if you have the `OpenSSL_version_num' function. */ #undef HAVE_OPENSSL_VERSION_NUM /* 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 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 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 `pledge' function. */ #undef HAVE_PLEDGE /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL /* Define to 1 if you have the header file. */ #undef HAVE_POLL_H /* Define to 1 if you have the `ppoll' function. */ #undef HAVE_PPOLL /* Define to 1 if you have the `prctl' function. */ #undef HAVE_PRCTL /* Define to 1 if you have the `priv_basicset' function. */ #undef HAVE_PRIV_BASICSET /* Define to 1 if you have the header file. */ #undef HAVE_PRIV_H /* Define to 1 if you have the `procctl' function. */ #undef HAVE_PROCCTL /* Define if you have /proc/$pid/fd */ #undef HAVE_PROC_PID /* Define to 1 if you have the `proc_pidinfo' function. */ #undef HAVE_PROC_PIDINFO /* Define to 1 if you have the `pselect' function. */ #undef HAVE_PSELECT /* Define to 1 if you have the `pstat' function. */ #undef HAVE_PSTAT /* Define to 1 if you have the header file. */ #undef HAVE_PTY_H /* Define to 1 if you have the `pututline' function. */ #undef HAVE_PUTUTLINE /* Define to 1 if you have the `pututxline' function. */ #undef HAVE_PUTUTXLINE /* Define to 1 if you have the `raise' function. */ #undef HAVE_RAISE /* Define to 1 if you have the `readpassphrase' function. */ #undef HAVE_READPASSPHRASE /* Define to 1 if you have the header file. */ #undef HAVE_READPASSPHRASE_H /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #undef HAVE_REALLOC /* 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 `recallocarray' function. */ #undef HAVE_RECALLOCARRAY /* 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 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 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 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 `setpflags' function. */ #undef HAVE_SETPFLAGS /* Define to 1 if you have the `setppriv' function. */ #undef HAVE_SETPPRIV /* Define to 1 if you have the `setproctitle' function. */ #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 `SHA256Update' function. */ #undef HAVE_SHA256UPDATE /* Define to 1 if you have the header file. */ #undef HAVE_SHA2_H /* Define to 1 if you have the `SHA384Update' function. */ #undef HAVE_SHA384UPDATE /* Define to 1 if you have the `SHA512Update' function. */ #undef HAVE_SHA512UPDATE /* Define to 1 if you have the header file. */ #undef HAVE_SHADOW_H /* Define to 1 if you have the `sigaction' function. */ #undef HAVE_SIGACTION /* Define to 1 if the system has the type `sighandler_t'. */ #undef HAVE_SIGHANDLER_T /* 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 if you have ut_ss in utmpx.h */ #undef HAVE_SS_IN_UTMPX /* 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 header file. */ #undef HAVE_STDDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasestr' function. */ #undef HAVE_STRCASESTR /* 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 /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the 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 `strndup' function. */ #undef HAVE_STRNDUP /* 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 `strsignal' function. */ #undef HAVE_STRSIGNAL /* 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 a member of `struct passwd'. */ #undef HAVE_STRUCT_PASSWD_PW_CHANGE /* Define to 1 if `pw_class' is a member of `struct passwd'. */ #undef HAVE_STRUCT_PASSWD_PW_CLASS /* Define to 1 if `pw_expire' is a member of `struct passwd'. */ #undef HAVE_STRUCT_PASSWD_PW_EXPIRE /* Define to 1 if `pw_gecos' is a member of `struct passwd'. */ #undef HAVE_STRUCT_PASSWD_PW_GECOS /* Define to 1 if `fd' is a member of `struct pollfd'. */ #undef HAVE_STRUCT_POLLFD_FD /* define if you have struct sockaddr_in6 data type */ #undef HAVE_STRUCT_SOCKADDR_IN6 /* Define to 1 if `sin6_scope_id' is a 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 `f_files' is a member of `struct statfs'. */ #undef HAVE_STRUCT_STATFS_F_FILES /* Define to 1 if `f_flags' is a member of `struct statfs'. */ #undef HAVE_STRUCT_STATFS_F_FLAGS /* Define to 1 if `st_blksize' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BLKSIZE /* Define to 1 if `st_mtim' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIM /* Define to 1 if `st_mtime' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIME /* define if you have struct timespec */ #undef HAVE_STRUCT_TIMESPEC /* define if you have struct timeval */ #undef HAVE_STRUCT_TIMEVAL /* 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 header file. */ #undef HAVE_SYS_AUDIT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BITYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BSDTTY_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BYTEORDER_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_CAPSICUM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_CDEFS_H /* Define to 1 if you have the 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 header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_LABEL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_NDIR_H /* Define if your system defines sys_nerr */ #undef HAVE_SYS_NERR /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PRCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PROCCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PSTAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PTMS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PTRACE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RANDOM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STREAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STROPTS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STRTIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSCTL_H /* Force use of sys/syslog.h on Ultrix */ #undef HAVE_SYS_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSMACROS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIMERS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VFS_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 `timegm' function. */ #undef HAVE_TIMEGM /* Define to 1 if you have the 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 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 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 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 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 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 header file. */ #undef HAVE_UTIL_H /* Define to 1 if you have the `utimensat' function. */ #undef HAVE_UTIMENSAT /* Define to 1 if you have the `utimes' function. */ #undef HAVE_UTIMES /* Define to 1 if you have the 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 header file. */ #undef HAVE_UTMPX_H /* Define to 1 if you have the 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 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 `warn' function. */ #undef HAVE_WARN /* Define to 1 if you have the header file. */ #undef HAVE_WCHAR_H /* Define to 1 if you have the `wcwidth' function. */ #undef HAVE_WCWIDTH /* 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 /* Lock all memory to protect sshd against Linux kcompactd */ #undef LINUX_MEMLOCK_ONFAULT /* 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 systems need a utmpx entry for /bin/login to work */ #undef LOGIN_NEEDS_UTMPX /* Set this to your mail directory if you do not have _PATH_MAILDIR */ #undef MAIL_DIRECTORY /* Define if your compiler lacks __builtin_popcount */ #undef MISSING_BUILTIN_POPCOUNT /* Need setpgrp to for controlling tty */ #undef NEED_SETPGRP /* compiler does not accept __attribute__ on prototype args */ #undef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS /* compiler does not accept __attribute__ on return types */ #undef NO_ATTRIBUTE_ON_RETURN_TYPE /* SA_RESTARTed signals do no interrupt select */ #undef NO_SA_RESTART /* Define to disable UID restoration test */ #undef NO_UID_RESTORATION_TEST /* Define if X11 doesn't support AF_UNIX sockets on that system */ #undef NO_X11_UNIX_SOCKETS /* Define if EVP_DigestUpdate returns void */ #undef OPENSSL_EVP_DIGESTUPDATE_VOID /* OpenSSL has ECC */ #undef OPENSSL_HAS_ECC /* libcrypto has ed25519 support */ #undef OPENSSL_HAS_ED25519 /* 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 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 home page for this package. */ #undef PACKAGE_URL /* 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 Solaris/Illumos privileges */ #undef SANDBOX_SOLARIS /* 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 /* The size of `time_t', as computed by sizeof. */ #undef SIZEOF_TIME_T /* Define as const if snprintf() can declare const char *fmt */ #undef SNPRINTF_CONST /* sockaddr_in has sin_len */ #undef SOCK_HAS_LEN /* Define to a Set Process Title type if your system is supported by bsd-setproctitle.c */ #undef SPT_TYPE /* Define if sshd somehow reacquires a controlling TTY after setsid() */ #undef SSHD_ACQUIRES_CTTY /* sshd PAM service name */ #undef SSHD_PAM_SERVICE /* Define if pam_chauthtok wants real uid set to the unpriv'ed user */ #undef SSHPAM_CHAUTHTOK_NEEDS_RUID /* Use audit debugging module */ #undef SSH_AUDIT_EVENTS /* Windows is sensitive to read buffer size */ #undef SSH_IOBUFSZ /* non-privileged user for privilege separation */ #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 all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #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 /* Have sshd notify systemd on start/reload */ #undef SYSTEMD_NOTIFY /* Support routing domains using Linux VRF */ #undef SYS_RDOMAIN_LINUX /* Support passwords > 8 chars */ #undef UNIXWARE_LONG_PASSWORDS /* Specify default $PATH */ #undef USER_PATH /* Define this if you want to use libkafs' AFS support */ #undef USE_AFS /* Use BSM audit module */ #undef USE_BSM_AUDIT /* Use btmp to log bad logins */ #undef USE_BTMP /* Use libedit for sftp */ #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 privileges */ #undef USE_SOLARIS_PRIVS /* Define if you have Solaris process contracts */ #undef USE_SOLARIS_PROCESS_CONTRACTS /* Define if you have Solaris projects */ #undef USE_SOLARIS_PROJECTS /* Use libwtmpdb for sshd */ #undef USE_WTMPDB /* compiler variable declarations after code */ #undef VARIABLE_DECLARATION_AFTER_CODE /* compiler supports variable length arrays */ #undef VARIABLE_LENGTH_ARRAYS /* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ #undef WITH_ABBREV_NO_TTY /* Define if you want to enable AIX4's authenticate function */ #undef WITH_AIXAUTHENTICATE /* Define if you have/want arrays (cluster-wide session management, not C arrays) */ #undef WITH_IRIX_ARRAY /* Define if you want IRIX audit trails */ #undef WITH_IRIX_AUDIT /* Define if you want IRIX kernel jobs */ #undef WITH_IRIX_JOBS /* Define if you want IRIX project management */ #undef WITH_IRIX_PROJECT /* use libcrypto for cryptography */ #undef WITH_OPENSSL /* Define if you want SELinux support. */ #undef WITH_SELINUX /* Enable zlib */ #undef WITH_ZLIB /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Define if xauth is found in your path */ #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 rpl_calloc if the replacement function should be used. */ #undef calloc /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to rpl_realloc if the replacement function should be used. */ #undef realloc /* type to use in place of socklen_t if not defined */ #undef socklen_t openssh-10.0p1/PaxHeaders.10889/config.sub100755 001750 001750 0000000003614775415623 0015137xustar0030 atime=1744182234.534985026 openssh-10.0p1/config.sub010075500017500001750000001057531477541562300135350ustar00djmdjm#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-09-17' # 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # 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 . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. 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 Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2022 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." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_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 basic_os=$field2 ;; zephyr*) basic_machine=$field1-unknown basic_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 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # 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 ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) ;; uclinux-uclibc* ) ;; managarm-mlibc* | managarm-kernel* ) ;; -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; -kernel* ) echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2 exit 1 ;; *-kernel* ) echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; vxworks-simlinux | vxworks-simwindows | vxworks-spe) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: openssh-10.0p1/PaxHeaders.10889/configure100755 001750 001750 0000000003514775415623 0015062xustar0029 atime=1744182234.55451647 openssh-10.0p1/configure010075500017500001750000026405261477541562300134650ustar00djmdjm#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for OpenSSH Portable. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 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 as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac 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 printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: openssh-unix-dev@mindrot.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$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 || printf "%s\n" 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" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error 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 if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # 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 as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # 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" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # 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 } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' 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 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then 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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' 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='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # 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'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/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= # Identity of this package. PACKAGE_NAME='OpenSSH' PACKAGE_TARNAME='openssh' PACKAGE_VERSION='Portable' PACKAGE_STRING='OpenSSH Portable' PACKAGE_BUGREPORT='openssh-unix-dev@mindrot.org' PACKAGE_URL='' ac_unique_file="ssh.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='LTLIBOBJS CFLAGS_NOPIE LDFLAGS_NOPIE DROPBEARCONVERT DROPBEARKEY DBCLIENT DROPBEAR CONCH PUTTYGEN PLINK DEPEND UNSUPPORTED_ALGORITHMS TEST_MALLOC_OPTIONS TEST_SSH_UTF8 TEST_SSH_IPV6 piddir user_path mansubdir MANTYPE XAUTH_PATH STRIP_OPT xauth_path PRIVSEP_PATH CHANNELLIBS K5LIBS GSSLIBS KRB5CONF SSHDLIBS SSH_PRIVSEP_USER SK_STANDALONE LIBFIDO2 SK_DUMMY_LIBRARY OPENSSL_BIN openssl_bin PICFLAG LIBWTMPDB LIBEDIT LDNSCONFIG LIBOBJS LD PATH_PASSWD_PROG STARTUP_SCRIPT_SHELL MAKE_PACKAGE_SUPPORTED PATH_USERADD_PROG PATH_GROUPADD_PROG MANFMT TEST_SHELL PKGCONFIG MANDOC NROFF GROFF SH TEST_MINUS_S_SH SED KILL CAT ac_ct_AR AR MKDIR_P EGREP GREP INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM RANLIB CPP AWK host_os host_vendor host_cpu host build_os build_vendor build_cpu build OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_largefile with_openssl with_stackprotect with_hardening with_retpoline with_rpath with_cflags with_cflags_after with_cppflags with_ldflags with_ldflags_after with_libs with_Werror with_linux_memlock_onfault with_solaris_contracts with_solaris_projects with_solaris_privs with_osfsia with_zlib with_zlib_version_check with_ldns with_libedit with_wtmpdb with_audit with_pie enable_pkcs11 enable_security_key with_security_key_builtin with_security_key_standalone with_ssl_dir with_openssl_header_check with_ssl_engine with_prngd_port with_prngd_socket with_pam with_pam_service with_privsep_user with_sandbox with_selinux with_kerberos5 with_privsep_path with_xauth enable_strip with_maildir with_mantype with_shadow with_ipaddr_display enable_etc_default_login with_default_path with_superuser_path with_4in6 with_bsd_auth with_pid_dir enable_fd_passing enable_lastlog enable_utmp enable_utmpx enable_wtmp enable_wtmpx enable_libutil enable_pututline enable_pututxline with_lastlog ' 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 ac_unrecognized_opts= ac_unrecognized_sep= # 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' runstatedir='${localstatedir}/run' 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= ;; *) ac_optarg=yes ;; esac 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_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=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_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$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 ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -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_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=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 ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$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'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. 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 runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" 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 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 .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # 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 -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | 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 .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" 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] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --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-option-checking ignore unrecognized --enable/--with options --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-pkcs11 disable PKCS#11 support code [no] --disable-security-key disable U2F/FIDO support code no --disable-strip Disable calling strip(1) on install --disable-etc-default-login Disable using PATH from /etc/default/login no --disable-fd-passing disable file descriptor passsing 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-stackprotect Don't use compiler's stack protection --without-hardening Don't use toolchain hardening flags --without-retpoline Enable retpoline spectre mitigation --without-rpath Disable auto-added -R linker paths --with-cflags Specify additional flags to pass to compiler --with-cflags-after Specify additional flags to pass to compiler after configure --with-cppflags Specify additional flags to pass to preprocessor --with-ldflags Specify additional flags to pass to linker --with-ldflags-after Specify additional flags to pass to linker after configure --with-libs Specify additional libraries to link with --with-Werror Build main code with -Werror --with-linux-memlock-onfault Enables memory locking on Linux --with-solaris-contracts Enable Solaris process contracts (experimental) --with-solaris-projects Enable Solaris projects (experimental) --with-solaris-privs Enable Solaris/Illumos privileges (experimental) --with-osfsia Enable Digital Unix SIA --with-zlib=PATH Use zlib in PATH --without-zlib-version-check Disable zlib version check --with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH) --with-libedit[=PATH] Enable libedit support for sftp --with-wtmpdb[=PATH] Enable wtmpdb support for sshd --with-audit=module Enable audit support (modules=debug,bsm,linux) --with-pie Build Position Independent Executables if possible --with-security-key-builtin include builtin U2F/FIDO support --with-security-key-standalone build standalone sk-libfido2 SecurityKeyProvider --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-pam-service=name Specify PAM service name --with-privsep-user=user Specify non-privileged user for privilege separation --with-sandbox=style Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter) --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 --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 sshd.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 if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory 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 . _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" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && 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=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$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 configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. 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 printf "%s\n" "$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.71 Copyright (C) 2021 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 ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: program exited with status $ac_status" >&5 printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR # ------------------------------------------------------------------ # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. ac_fn_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 printf %s "checking whether $as_decl_name is declared... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` eval ac_save_FLAGS=\$$6 as_fn_append $6 " $5" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext eval $6=\$ac_save_FLAGS fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_check_decl # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* 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 $2 (); /* 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_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 printf %s "checking for $2.$3... " >&6; } if eval test \${$4+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main (void) { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$4=yes" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main (void) { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$4=yes" else $as_nop eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$4 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid; break else $as_nop as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=$ac_mid; break else $as_nop as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid else $as_nop as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval (void) { return $2; } static unsigned long int ulongval (void) { return $2; } #include #include int main (void) { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : echo >>conftest.val; read $3 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.71. Invocation command line was $ $0$ac_configure_args_raw _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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "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=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append 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 as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset 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=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" 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_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; 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 printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$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'; as_fn_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 printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } 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. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*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 do not provoke an error unfortunately, instead are silently treated as an "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 is necessary to write \x00 == 0 to get something that is 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 **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Auxiliary files required by this configure script. ac_aux_files="install-sh config.guess config.sub" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 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. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" 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,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$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 # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$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. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## 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 # Check for stale configure as early as possible. for i in $srcdir/configure.ac $srcdir/m4/*.m4; do if test "$i" -nt "$srcdir/configure"; then as_fn_error $? "$i newer than configure, run autoreconf" "$LINENO" 5 fi 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 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 for ac_prog in cc gcc clang 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cc gcc clang do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM 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. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.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 ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 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 | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && 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 $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 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 | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; 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 ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 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 | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; 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 ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _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" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi 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 # XXX relax this after reimplementing logit() etc. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports C99-style variadic macros" >&5 printf %s "checking if $CC supports C99-style variadic macros... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int f(int a, int b, int c) { return a + b + c; } #define F(a, ...) f(a, __VA_ARGS__) int main (void) { return F(1, 2, -3); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop as_fn_error $? "*** OpenSSH requires support for C99-style variadic macros" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else $as_nop 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 && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else $as_nop 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` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; 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_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 printf %s "checking whether byte ordering is bigendian... " >&6; } if test ${ac_cv_c_bigendian+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO" then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ unsigned short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; unsigned short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } unsigned short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; unsigned short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main (void) { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" 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 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { /* 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 if ac_fn_c_try_run "$LINENO" then : ac_cv_c_bigendian=no else $as_nop ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 printf "%s\n" "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 printf %s "checking how to run the C preprocessor... " >&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+y} then : printf %s "(cached) " >&6 else $as_nop # Double quotes because $CC needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" 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. # 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 printf "%s\n" "$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. # 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&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. # Reject install programs that cannot install multiple files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac # Account for fact that we put trailing slashes in our PATH walk. 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 as_fn_executable_p "$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 rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test ${ac_cv_path_install+y}; 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 printf "%s\n" "$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' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 printf %s "checking for grep that handles long lines and -e... " >&6; } if test ${ac_cv_path_GREP+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$GREP"; then 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac 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" as_fn_executable_p "$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 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" '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 as_fn_arith $ac_count + 1 && ac_count=$as_val 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 if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 printf "%s\n" "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 printf %s "checking for egrep... " >&6; } if test ${ac_cv_path_EGREP+y} then : printf %s "(cached) " >&6 else $as_nop if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac 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" as_fn_executable_p "$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 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" '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 as_fn_arith $ac_count + 1 && ac_count=$as_val 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 if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 printf "%s\n" "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test ${ac_cv_path_mkdir+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir ('*'coreutils) '* | \ 'BusyBox '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P 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. MKDIR_P="$ac_install_sh -d" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 printf "%s\n" "$MKDIR_P" >&6; } if test -n "$ac_tool_prefix"; then for ac_prog in ar 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 printf "%s\n" "$ac_ct_AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi # Extract the first word of "cat", so it can be a program name with args. set dummy cat; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_CAT+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_CAT="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CAT" >&5 printf "%s\n" "$CAT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "kill", so it can be a program name with args. set dummy kill; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_KILL+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_KILL="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $KILL" >&5 printf "%s\n" "$KILL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_SED+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_SED="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 printf "%s\n" "$SED" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "bash", so it can be a program name with args. set dummy bash; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_TEST_MINUS_S_SH+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_TEST_MINUS_S_SH="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5 printf "%s\n" "$TEST_MINUS_S_SH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "ksh", so it can be a program name with args. set dummy ksh; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_TEST_MINUS_S_SH+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_TEST_MINUS_S_SH="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5 printf "%s\n" "$TEST_MINUS_S_SH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "sh", so it can be a program name with args. set dummy sh; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_TEST_MINUS_S_SH+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_TEST_MINUS_S_SH="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5 printf "%s\n" "$TEST_MINUS_S_SH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "bash", so it can be a program name with args. set dummy bash; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_SH+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_SH="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 printf "%s\n" "$SH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "ksh", so it can be a program name with args. set dummy ksh; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_SH+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_SH="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 printf "%s\n" "$SH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "sh", so it can be a program name with args. set dummy sh; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_SH+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_SH="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 printf "%s\n" "$SH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "groff", so it can be a program name with args. set dummy groff; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_GROFF+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_GROFF="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5 printf "%s\n" "$GROFF" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "nroff awf", so it can be a program name with args. set dummy nroff awf; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_NROFF+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_NROFF="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5 printf "%s\n" "$NROFF" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "mandoc", so it can be a program name with args. set dummy mandoc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_MANDOC+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_MANDOC="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANDOC" >&5 printf "%s\n" "$MANDOC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKGCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 printf "%s\n" "$PKGCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_PKGCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5 printf "%s\n" "$ac_pt_PKGCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKGCONFIG" = x; then PKGCONFIG="no" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKGCONFIG=$ac_pt_PKGCONFIG fi else PKGCONFIG="$ac_cv_path_PKGCONFIG" 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: no manpage formatter found" >&5 printf "%s\n" "$as_me: WARNING: no manpage formatter 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PATH_GROUPADD_PROG+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PATH_GROUPADD_PROG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PATH_GROUPADD_PROG" >&5 printf "%s\n" "$PATH_GROUPADD_PROG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "useradd", so it can be a program name with args. set dummy useradd; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PATH_USERADD_PROG+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PATH_USERADD_PROG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PATH_USERADD_PROG" >&5 printf "%s\n" "$PATH_USERADD_PROG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "pkgmk", so it can be a program name with args. set dummy pkgmk; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_MAKE_PACKAGE_SUPPORTED+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_MAKE_PACKAGE_SUPPORTED="yes" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAKE_PACKAGE_SUPPORTED" >&5 printf "%s\n" "$MAKE_PACKAGE_SUPPORTED" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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+y} then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 printf %s "checking for special C compiler options needed for large files... " >&6; } if test ${ac_cv_sys_largefile_CC+y} then : printf %s "(cached) " >&6 else $as_nop 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* 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 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : break fi rm -f core conftest.err conftest.$ac_objext conftest.beam CC="$CC -n32" if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if test ${ac_cv_sys_file_offset_bits+y} then : printf %s "(cached) " >&6 else $as_nop while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* 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 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* 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 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 printf %s "checking for _LARGE_FILES value needed for large files... " >&6; } if test ${ac_cv_sys_large_files+y} then : printf %s "(cached) " >&6 else $as_nop while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* 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 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* 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 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 printf "%s\n" "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h ;; esac rm -rf conftest* fi fi if test -z "$AR" ; then as_fn_error $? "*** 'ar' missing, please install or fix your \$PATH ***" "$LINENO" 5 fi # Extract the first word of "passwd", so it can be a program name with args. set dummy passwd; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PATH_PASSWD_PROG+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PATH_PASSWD_PROG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PATH_PASSWD_PROG" >&5 printf "%s\n" "$PATH_PASSWD_PROG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test ! -z "$PATH_PASSWD_PROG" ; then printf "%s\n" "#define _PATH_PASSWD_PROG \"$PATH_PASSWD_PROG\"" >>confdefs.h fi LD="$CC" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 printf %s "checking for inline... " >&6; } if test ${ac_cv_c_inline+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo (void) {return 0; } $ac_kw foo_t foo (void) {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } if test ${ac_cv_c_undeclared_builtin_options+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CFLAGS=$CFLAGS ac_cv_c_undeclared_builtin_options='cannot detect' for ac_arg in '' -fno-builtin; do CFLAGS="$ac_save_CFLAGS $ac_arg" # This test program should *not* compile successfully. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { (void) strchr; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop # This test program should compile successfully. # No library function is consistently available on # freestanding implementations, so test against a dummy # declaration. Include always-available headers on the # off chance that they somehow elicit warnings. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include extern void ac_decl (int, char *); int main (void) { (void) ac_decl (0, (char *) 0); (void) ac_decl; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if test x"$ac_arg" = x then : ac_cv_c_undeclared_builtin_options='none needed' else $as_nop ac_cv_c_undeclared_builtin_options=$ac_arg fi break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done CFLAGS=$ac_save_CFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } case $ac_cv_c_undeclared_builtin_options in #( 'cannot detect') : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot make $CC report undeclared builtins See \`config.log' for more details" "$LINENO" 5; } ;; #( 'none needed') : ac_c_undeclared_builtin_options='' ;; #( *) : ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; esac ac_fn_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_LLONG_MAX" = xyes then : have_llong_max=1 fi ac_fn_check_decl "$LINENO" "LONG_LONG_MAX" "ac_cv_have_decl_LONG_LONG_MAX" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_LONG_LONG_MAX" = xyes then : have_long_long_max=1 fi ac_fn_check_decl "$LINENO" "RLIMIT_NPROC" "ac_cv_have_decl_RLIMIT_NPROC" " #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_RLIMIT_NPROC" = xyes then : printf "%s\n" "#define HAVE_RLIMIT_NPROC /**/" >>confdefs.h fi ac_fn_check_decl "$LINENO" "PR_SET_NO_NEW_PRIVS" "ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" " #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" = xyes then : have_linux_no_new_privs=1 fi openssl=yes openssl_bin=openssl # Check whether --with-openssl was given. if test ${with_openssl+y} then : withval=$with_openssl; if test "x$withval" = "xno" ; then openssl=no openssl_bin="" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL will be used for cryptography" >&5 printf %s "checking whether OpenSSL will be used for cryptography... " >&6; } if test "x$openssl" = "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define WITH_OPENSSL 1" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi use_stack_protector=1 use_toolchain_hardening=1 use_retpoline=1 # Check whether --with-stackprotect was given. if test ${with_stackprotect+y} 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+y} then : withval=$with_hardening; if test "x$withval" = "xno"; then use_toolchain_hardening=0 fi fi # Check whether --with-retpoline was given. if test ${with_retpoline+y} then : withval=$with_retpoline; if test "x$withval" = "xno"; then use_retpoline=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. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Werror" >&5 printf %s "checking if $CC supports -Werror... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main(void) { return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } WERROR="-Werror" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } WERROR="" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CFLAGS="$saved_CFLAGS" if test "$GCC" = "yes" || test "$GCC" = "egcs"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5 printf %s "checking gcc version... " >&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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GCC_VER" >&5 printf "%s\n" "$GCC_VER" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking clang version" >&5 printf %s "checking clang version... " >&6; } ver="`$CC -v 2>&1`" if echo "$ver" | grep "Apple" >/dev/null; then CLANG_VER=apple-`echo "$ver" | grep 'clang version' | \ $SED 's/.*clang version //g' | $AWK '{print $1}'` else CLANG_VER=`echo "$ver" | grep 'clang version' | \ $SED 's/.*clang version //g' | $AWK '{print $1}'` fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CLANG_VER" >&5 printf "%s\n" "$CLANG_VER" >&6; } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5 printf %s "checking if $CC supports compile flag -pipe... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -pipe" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunknown-warning-option" >&5 printf %s "checking if $CC supports compile flag -Wunknown-warning-option... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunknown-warning-option" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wunknown-warning-option" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-error=format-truncation" >&5 printf %s "checking if $CC supports compile flag -Wno-error=format-truncation... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wno-error=format-truncation" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wno-error=format-truncation" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Qunused-arguments" >&5 printf %s "checking if $CC supports compile flag -Qunused-arguments... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Qunused-arguments" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Qunused-arguments" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wall" >&5 printf %s "checking if $CC supports compile flag -Wall... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wall" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wall" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wextra" >&5 printf %s "checking if $CC supports compile flag -Wextra... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wextra" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wextra" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-arith" >&5 printf %s "checking if $CC supports compile flag -Wpointer-arith... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wpointer-arith" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wpointer-arith" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wuninitialized" >&5 printf %s "checking if $CC supports compile flag -Wuninitialized... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wuninitialized" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wuninitialized" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsign-compare" >&5 printf %s "checking if $CC supports compile flag -Wsign-compare... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wsign-compare" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wsign-compare" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wformat-security" >&5 printf %s "checking if $CC supports compile flag -Wformat-security... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wformat-security" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wformat-security" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsizeof-pointer-memaccess" >&5 printf %s "checking if $CC supports compile flag -Wsizeof-pointer-memaccess... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wsizeof-pointer-memaccess" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wsizeof-pointer-memaccess" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-sign" >&5 printf %s "checking if $CC supports compile flag -Wpointer-sign... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wpointer-sign" _define_flag="-Wno-pointer-sign" test "x$_define_flag" = "x" && _define_flag="-Wpointer-sign" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-parameter" >&5 printf %s "checking if $CC supports compile flag -Wunused-parameter... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunused-parameter" _define_flag="-Wno-unused-parameter" test "x$_define_flag" = "x" && _define_flag="-Wunused-parameter" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-result" >&5 printf %s "checking if $CC supports compile flag -Wunused-result... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunused-result" _define_flag="-Wno-unused-result" test "x$_define_flag" = "x" && _define_flag="-Wunused-result" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wimplicit-fallthrough" >&5 printf %s "checking if $CC supports compile flag -Wimplicit-fallthrough... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wimplicit-fallthrough" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wimplicit-fallthrough" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wmisleading-indentation" >&5 printf %s "checking if $CC supports compile flag -Wmisleading-indentation... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wmisleading-indentation" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wmisleading-indentation" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wbitwise-instead-of-logical" >&5 printf %s "checking if $CC supports compile flag -Wbitwise-instead-of-logical... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wbitwise-instead-of-logical" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wbitwise-instead-of-logical" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fno-strict-aliasing" >&5 printf %s "checking if $CC supports compile flag -fno-strict-aliasing... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fno-strict-aliasing" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-fno-strict-aliasing" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } if test "x$use_toolchain_hardening" = "x1"; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5 printf %s "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... " >&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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5 printf %s "checking if $LD supports link flag -Wl,-z,relro... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,relro" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wl,-z,relro" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,now" >&5 printf %s "checking if $LD supports link flag -Wl,-z,now... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,now" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wl,-z,now" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,noexecstack" >&5 printf %s "checking if $LD supports link flag -Wl,-z,noexecstack... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,noexecstack" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wl,-z,noexecstack" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ 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. { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrapv and linking succeeds" >&5 printf %s "checking if $CC supports compile flag -ftrapv and linking succeeds... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -ftrapv" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-ftrapv" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext } # clang 15 seems to have a bug in -fzero-call-used-regs=all. See # https://bugzilla.mindrot.org/show_bug.cgi?id=3475 and # https://github.com/llvm/llvm-project/issues/59242 # clang 17 has a different bug that causes an ICE when using this # flag at all (https://bugzilla.mindrot.org/show_bug.cgi?id=3629) case "$CLANG_VER" in apple-15*) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds" >&5 printf %s "checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fzero-call-used-regs=used" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-fzero-call-used-regs=used" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext } ;; 17*) ;; *) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds" >&5 printf %s "checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fzero-call-used-regs=used" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-fzero-call-used-regs=used" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext } ;; esac { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrivial-auto-var-init=zero" >&5 printf %s "checking if $CC supports compile flag -ftrivial-auto-var-init=zero... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -ftrivial-auto-var-init=zero" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-ftrivial-auto-var-init=zero" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } fi if test "x$use_retpoline" = "x1"; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -mretpoline" >&5 printf %s "checking if $CC supports compile flag -mretpoline... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -mretpoline" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-mretpoline" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } # clang { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,retpolineplt" >&5 printf %s "checking if $LD supports link flag -Wl,-z,retpolineplt... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,retpolineplt" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wl,-z,retpolineplt" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC accepts -fno-builtin-memset" >&5 printf %s "checking if $CC accepts -fno-builtin-memset... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-builtin-memset" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { char b[10]; memset(b, 0, sizeof(b)); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports $t" >&5 printf %s "checking if $CC supports $t... " >&6; } saved_CFLAGS="$CFLAGS" saved_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $t -Werror" LDFLAGS="$LDFLAGS $t -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} int main (void) { char x[256]; snprintf(x, sizeof(x), "XXX%d", func(1)); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $t" LDFLAGS="$saved_LDFLAGS $t" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $t works" >&5 printf %s "checking if $t works... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: cannot test" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: cannot test" >&2;} break else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} int main (void) { char x[256]; snprintf(x, sizeof(x), "XXX%d", func(1)); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } break else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ 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" ac_fn_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_LLONG_MAX" = xyes then : have_llong_max=1 else $as_nop CFLAGS="$saved_CFLAGS" fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ on return types" >&5 printf %s "checking if compiler allows __attribute__ on return types... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include __attribute__((__unused__)) static void foo(void){return;} int main (void) { exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define NO_ATTRIBUTE_ON_RETURN_TYPE 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ prototype args" >&5 printf %s "checking if compiler allows __attribute__ prototype args... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2))); int main (void) { exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define NO_ATTRIBUTE_ON_PROTOTYPE_ARGS 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports variable length arrays" >&5 printf %s "checking if compiler supports variable length arrays... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int i; for (i=0; i<3; i++){int a[i]; a[i-1]=0;} exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define VARIABLE_LENGTH_ARRAYS 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts variable declarations after code" >&5 printf %s "checking if compiler accepts variable declarations after code... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int a; a = 1; int b = 1; exit(a-b); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define VARIABLE_DECLARATION_AFTER_CODE 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test "x$no_attrib_nonnull" != "x1" ; then printf "%s\n" "#define HAVE_ATTRIBUTE__NONNULL__ 1" >>confdefs.h fi # Check whether --with-rpath was given. if test ${with_rpath+y} then : withval=$with_rpath; if test "x$withval" = "xno" ; then rpath_opt="" elif test "x$withval" = "xyes" ; then rpath_opt="-R" else rpath_opt="$withval" fi fi # Allow user to specify flags # Check whether --with-cflags was given. if test ${with_cflags+y} 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-cflags-after was given. if test ${with_cflags_after+y} then : withval=$with_cflags_after; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then CFLAGS_AFTER="$withval" fi fi # Check whether --with-cppflags was given. if test ${with_cppflags+y} 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+y} 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-ldflags-after was given. if test ${with_ldflags_after+y} then : withval=$with_ldflags_after; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then LDFLAGS_AFTER="$withval" fi fi # Check whether --with-libs was given. if test ${with_libs+y} 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+y} 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 if test "x$ac_cv_header_sys_stat_h" != "xyes"; then unset ac_cv_header_sys_stat_h ac_fn_c_check_header_compile "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default" if test "x$ac_cv_header_sys_stat_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STAT_H 1" >>confdefs.h fi fi ac_fn_c_check_header_compile "$LINENO" "blf.h" "ac_cv_header_blf_h" "$ac_includes_default" if test "x$ac_cv_header_blf_h" = xyes then : printf "%s\n" "#define HAVE_BLF_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "bstring.h" "ac_cv_header_bstring_h" "$ac_includes_default" if test "x$ac_cv_header_bstring_h" = xyes then : printf "%s\n" "#define HAVE_BSTRING_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "crypt.h" "ac_cv_header_crypt_h" "$ac_includes_default" if test "x$ac_cv_header_crypt_h" = xyes then : printf "%s\n" "#define HAVE_CRYPT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "crypto/sha2.h" "ac_cv_header_crypto_sha2_h" "$ac_includes_default" if test "x$ac_cv_header_crypto_sha2_h" = xyes then : printf "%s\n" "#define HAVE_CRYPTO_SHA2_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default" if test "x$ac_cv_header_dirent_h" = xyes then : printf "%s\n" "#define HAVE_DIRENT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" if test "x$ac_cv_header_endian_h" = xyes then : printf "%s\n" "#define HAVE_ENDIAN_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "elf.h" "ac_cv_header_elf_h" "$ac_includes_default" if test "x$ac_cv_header_elf_h" = xyes then : printf "%s\n" "#define HAVE_ELF_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "err.h" "ac_cv_header_err_h" "$ac_includes_default" if test "x$ac_cv_header_err_h" = xyes then : printf "%s\n" "#define HAVE_ERR_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "features.h" "ac_cv_header_features_h" "$ac_includes_default" if test "x$ac_cv_header_features_h" = xyes then : printf "%s\n" "#define HAVE_FEATURES_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" if test "x$ac_cv_header_fcntl_h" = xyes then : printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "floatingpoint.h" "ac_cv_header_floatingpoint_h" "$ac_includes_default" if test "x$ac_cv_header_floatingpoint_h" = xyes then : printf "%s\n" "#define HAVE_FLOATINGPOINT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "fnmatch.h" "ac_cv_header_fnmatch_h" "$ac_includes_default" if test "x$ac_cv_header_fnmatch_h" = xyes then : printf "%s\n" "#define HAVE_FNMATCH_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "getopt.h" "ac_cv_header_getopt_h" "$ac_includes_default" if test "x$ac_cv_header_getopt_h" = xyes then : printf "%s\n" "#define HAVE_GETOPT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default" if test "x$ac_cv_header_glob_h" = xyes then : printf "%s\n" "#define HAVE_GLOB_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "ia.h" "ac_cv_header_ia_h" "$ac_includes_default" if test "x$ac_cv_header_ia_h" = xyes then : printf "%s\n" "#define HAVE_IA_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "iaf.h" "ac_cv_header_iaf_h" "$ac_includes_default" if test "x$ac_cv_header_iaf_h" = xyes then : printf "%s\n" "#define HAVE_IAF_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default" if test "x$ac_cv_header_ifaddrs_h" = xyes then : printf "%s\n" "#define HAVE_IFADDRS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" if test "x$ac_cv_header_inttypes_h" = xyes then : printf "%s\n" "#define HAVE_INTTYPES_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default" if test "x$ac_cv_header_langinfo_h" = xyes then : printf "%s\n" "#define HAVE_LANGINFO_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" if test "x$ac_cv_header_limits_h" = xyes then : printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" if test "x$ac_cv_header_locale_h" = xyes then : printf "%s\n" "#define HAVE_LOCALE_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "login.h" "ac_cv_header_login_h" "$ac_includes_default" if test "x$ac_cv_header_login_h" = xyes then : printf "%s\n" "#define HAVE_LOGIN_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "maillock.h" "ac_cv_header_maillock_h" "$ac_includes_default" if test "x$ac_cv_header_maillock_h" = xyes then : printf "%s\n" "#define HAVE_MAILLOCK_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "ndir.h" "ac_cv_header_ndir_h" "$ac_includes_default" if test "x$ac_cv_header_ndir_h" = xyes then : printf "%s\n" "#define HAVE_NDIR_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "net/if_tun.h" "ac_cv_header_net_if_tun_h" "$ac_includes_default" if test "x$ac_cv_header_net_if_tun_h" = xyes then : printf "%s\n" "#define HAVE_NET_IF_TUN_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" if test "x$ac_cv_header_netdb_h" = xyes then : printf "%s\n" "#define HAVE_NETDB_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "netgroup.h" "ac_cv_header_netgroup_h" "$ac_includes_default" if test "x$ac_cv_header_netgroup_h" = xyes then : printf "%s\n" "#define HAVE_NETGROUP_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "pam/pam_appl.h" "ac_cv_header_pam_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_pam_pam_appl_h" = xyes then : printf "%s\n" "#define HAVE_PAM_PAM_APPL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "paths.h" "ac_cv_header_paths_h" "$ac_includes_default" if test "x$ac_cv_header_paths_h" = xyes then : printf "%s\n" "#define HAVE_PATHS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default" if test "x$ac_cv_header_poll_h" = xyes then : printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "pty.h" "ac_cv_header_pty_h" "$ac_includes_default" if test "x$ac_cv_header_pty_h" = xyes then : printf "%s\n" "#define HAVE_PTY_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "readpassphrase.h" "ac_cv_header_readpassphrase_h" "$ac_includes_default" if test "x$ac_cv_header_readpassphrase_h" = xyes then : printf "%s\n" "#define HAVE_READPASSPHRASE_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "rpc/types.h" "ac_cv_header_rpc_types_h" "$ac_includes_default" if test "x$ac_cv_header_rpc_types_h" = xyes then : printf "%s\n" "#define HAVE_RPC_TYPES_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "security/pam_appl.h" "ac_cv_header_security_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_security_pam_appl_h" = xyes then : printf "%s\n" "#define HAVE_SECURITY_PAM_APPL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sha2.h" "ac_cv_header_sha2_h" "$ac_includes_default" if test "x$ac_cv_header_sha2_h" = xyes then : printf "%s\n" "#define HAVE_SHA2_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "shadow.h" "ac_cv_header_shadow_h" "$ac_includes_default" if test "x$ac_cv_header_shadow_h" = xyes then : printf "%s\n" "#define HAVE_SHADOW_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default" if test "x$ac_cv_header_stddef_h" = xyes then : printf "%s\n" "#define HAVE_STDDEF_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" if test "x$ac_cv_header_stdint_h" = xyes then : printf "%s\n" "#define HAVE_STDINT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" if test "x$ac_cv_header_string_h" = xyes then : printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default" if test "x$ac_cv_header_strings_h" = xyes then : printf "%s\n" "#define HAVE_STRINGS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/bitypes.h" "ac_cv_header_sys_bitypes_h" "$ac_includes_default" if test "x$ac_cv_header_sys_bitypes_h" = xyes then : printf "%s\n" "#define HAVE_SYS_BITYPES_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/byteorder.h" "ac_cv_header_sys_byteorder_h" "$ac_includes_default" if test "x$ac_cv_header_sys_byteorder_h" = xyes then : printf "%s\n" "#define HAVE_SYS_BYTEORDER_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/bsdtty.h" "ac_cv_header_sys_bsdtty_h" "$ac_includes_default" if test "x$ac_cv_header_sys_bsdtty_h" = xyes then : printf "%s\n" "#define HAVE_SYS_BSDTTY_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/cdefs.h" "ac_cv_header_sys_cdefs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_cdefs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_CDEFS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/dir.h" "ac_cv_header_sys_dir_h" "$ac_includes_default" if test "x$ac_cv_header_sys_dir_h" = xyes then : printf "%s\n" "#define HAVE_SYS_DIR_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/file.h" "ac_cv_header_sys_file_h" "$ac_includes_default" if test "x$ac_cv_header_sys_file_h" = xyes then : printf "%s\n" "#define HAVE_SYS_FILE_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" if test "x$ac_cv_header_sys_mman_h" = xyes then : printf "%s\n" "#define HAVE_SYS_MMAN_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/label.h" "ac_cv_header_sys_label_h" "$ac_includes_default" if test "x$ac_cv_header_sys_label_h" = xyes then : printf "%s\n" "#define HAVE_SYS_LABEL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/ndir.h" "ac_cv_header_sys_ndir_h" "$ac_includes_default" if test "x$ac_cv_header_sys_ndir_h" = xyes then : printf "%s\n" "#define HAVE_SYS_NDIR_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" if test "x$ac_cv_header_sys_param_h" = xyes then : printf "%s\n" "#define HAVE_SYS_PARAM_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/poll.h" "ac_cv_header_sys_poll_h" "$ac_includes_default" if test "x$ac_cv_header_sys_poll_h" = xyes then : printf "%s\n" "#define HAVE_SYS_POLL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_prctl_h" = xyes then : printf "%s\n" "#define HAVE_SYS_PRCTL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/procctl.h" "ac_cv_header_sys_procctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_procctl_h" = xyes then : printf "%s\n" "#define HAVE_SYS_PROCCTL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/pstat.h" "ac_cv_header_sys_pstat_h" "$ac_includes_default" if test "x$ac_cv_header_sys_pstat_h" = xyes then : printf "%s\n" "#define HAVE_SYS_PSTAT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/ptrace.h" "ac_cv_header_sys_ptrace_h" "$ac_includes_default" if test "x$ac_cv_header_sys_ptrace_h" = xyes then : printf "%s\n" "#define HAVE_SYS_PTRACE_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default" if test "x$ac_cv_header_sys_random_h" = xyes then : printf "%s\n" "#define HAVE_SYS_RANDOM_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" if test "x$ac_cv_header_sys_select_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/stream.h" "ac_cv_header_sys_stream_h" "$ac_includes_default" if test "x$ac_cv_header_sys_stream_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STREAM_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/stropts.h" "ac_cv_header_sys_stropts_h" "$ac_includes_default" if test "x$ac_cv_header_sys_stropts_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STROPTS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/strtio.h" "ac_cv_header_sys_strtio_h" "$ac_includes_default" if test "x$ac_cv_header_sys_strtio_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STRTIO_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/statvfs.h" "ac_cv_header_sys_statvfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statvfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STATVFS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default" if test "x$ac_cv_header_sys_sysmacros_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SYSMACROS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes then : printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/timers.h" "ac_cv_header_sys_timers_h" "$ac_includes_default" if test "x$ac_cv_header_sys_timers_h" = xyes then : printf "%s\n" "#define HAVE_SYS_TIMERS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/vfs.h" "ac_cv_header_sys_vfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_vfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_VFS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" if test "x$ac_cv_header_time_h" = xyes then : printf "%s\n" "#define HAVE_TIME_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "tmpdir.h" "ac_cv_header_tmpdir_h" "$ac_includes_default" if test "x$ac_cv_header_tmpdir_h" = xyes then : printf "%s\n" "#define HAVE_TMPDIR_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "ttyent.h" "ac_cv_header_ttyent_h" "$ac_includes_default" if test "x$ac_cv_header_ttyent_h" = xyes then : printf "%s\n" "#define HAVE_TTYENT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "ucred.h" "ac_cv_header_ucred_h" "$ac_includes_default" if test "x$ac_cv_header_ucred_h" = xyes then : printf "%s\n" "#define HAVE_UCRED_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes then : printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "usersec.h" "ac_cv_header_usersec_h" "$ac_includes_default" if test "x$ac_cv_header_usersec_h" = xyes then : printf "%s\n" "#define HAVE_USERSEC_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "util.h" "ac_cv_header_util_h" "$ac_includes_default" if test "x$ac_cv_header_util_h" = xyes then : printf "%s\n" "#define HAVE_UTIL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "utime.h" "ac_cv_header_utime_h" "$ac_includes_default" if test "x$ac_cv_header_utime_h" = xyes then : printf "%s\n" "#define HAVE_UTIME_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "utmp.h" "ac_cv_header_utmp_h" "$ac_includes_default" if test "x$ac_cv_header_utmp_h" = xyes then : printf "%s\n" "#define HAVE_UTMP_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "utmpx.h" "ac_cv_header_utmpx_h" "$ac_includes_default" if test "x$ac_cv_header_utmpx_h" = xyes then : printf "%s\n" "#define HAVE_UTMPX_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "vis.h" "ac_cv_header_vis_h" "$ac_includes_default" if test "x$ac_cv_header_vis_h" = xyes then : printf "%s\n" "#define HAVE_VIS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "wchar.h" "ac_cv_header_wchar_h" "$ac_includes_default" if test "x$ac_cv_header_wchar_h" = xyes then : printf "%s\n" "#define HAVE_WCHAR_H 1" >>confdefs.h fi ac_fn_check_decl "$LINENO" "le32toh" "ac_cv_have_decl_le32toh" " #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_ENDIAN_H # include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_le32toh" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_LE32TOH $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "le64toh" "ac_cv_have_decl_le64toh" " #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_ENDIAN_H # include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_le64toh" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_LE64TOH $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "htole64" "ac_cv_have_decl_htole64" " #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_ENDIAN_H # include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_htole64" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_HTOLE64 $ac_have_decl" >>confdefs.h # On some platforms (eg SunOS4) sys/audit.h requires sys/[time|types|label.h] # to be included first. ac_fn_c_check_header_compile "$LINENO" "sys/audit.h" "ac_cv_header_sys_audit_h" " #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_LABEL_H # include #endif " if test "x$ac_cv_header_sys_audit_h" = xyes then : printf "%s\n" "#define HAVE_SYS_AUDIT_H 1" >>confdefs.h fi # sys/capsicum.h requires sys/types.h ac_fn_c_check_header_compile "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" " #ifdef HAVE_SYS_TYPES_H # include #endif " if test "x$ac_cv_header_sys_capsicum_h" = xyes then : printf "%s\n" "#define HAVE_SYS_CAPSICUM_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "capsicum_helpers.h" "ac_cv_header_capsicum_helpers_h" " #ifdef HAVE_SYS_TYPES_H # include #endif " if test "x$ac_cv_header_capsicum_helpers_h" = xyes then : printf "%s\n" "#define HAVE_CAPSICUM_HELPERS_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for caph_cache_tzdata" >&5 printf %s "checking for caph_cache_tzdata... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { caph_cache_tzdata(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_CAPH_CACHE_TZDATA 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext # net/route.h requires sys/socket.h and sys/types.h. # sys/sysctl.h also requires sys/param.h ac_fn_c_check_header_compile "$LINENO" "net/route.h" "ac_cv_header_net_route_h" " #ifdef HAVE_SYS_TYPES_H # include #endif #include #include " if test "x$ac_cv_header_net_route_h" = xyes then : printf "%s\n" "#define HAVE_NET_ROUTE_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" " #ifdef HAVE_SYS_TYPES_H # include #endif #include #include " if test "x$ac_cv_header_sys_sysctl_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SYSCTL_H 1" >>confdefs.h fi # lastlog.h requires sys/time.h to be included first on Solaris ac_fn_c_check_header_compile "$LINENO" "lastlog.h" "ac_cv_header_lastlog_h" " #ifdef HAVE_SYS_TIME_H # include #endif " if test "x$ac_cv_header_lastlog_h" = xyes then : printf "%s\n" "#define HAVE_LASTLOG_H 1" >>confdefs.h fi # sys/ptms.h requires sys/stream.h to be included first on Solaris ac_fn_c_check_header_compile "$LINENO" "sys/ptms.h" "ac_cv_header_sys_ptms_h" " #ifdef HAVE_SYS_STREAM_H # include #endif " if test "x$ac_cv_header_sys_ptms_h" = xyes then : printf "%s\n" "#define HAVE_SYS_PTMS_H 1" >>confdefs.h fi # login_cap.h requires sys/types.h on NetBSD ac_fn_c_check_header_compile "$LINENO" "login_cap.h" "ac_cv_header_login_cap_h" " #include " if test "x$ac_cv_header_login_cap_h" = xyes then : printf "%s\n" "#define HAVE_LOGIN_CAP_H 1" >>confdefs.h fi # older BSDs need sys/param.h before sys/mount.h ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" " #include " if test "x$ac_cv_header_sys_mount_h" = xyes then : printf "%s\n" "#define HAVE_SYS_MOUNT_H 1" >>confdefs.h fi # Android requires sys/socket.h to be included before sys/un.h ac_fn_c_check_header_compile "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" " #include #include " if test "x$ac_cv_header_sys_un_h" = xyes then : printf "%s\n" "#define HAVE_SYS_UN_H 1" >>confdefs.h fi # Messages for features tested for in target-specific section SIA_MSG="no" SPC_MSG="no" SP_MSG="no" SPP_MSG="no" # Support for Solaris/Illumos privileges (this test is used by both # the --with-solaris-privs option and --with-sandbox=solaris). SOLARIS_PRIVS="no" # Default shared library extension SHLIBEXT=".so" # Check for some target-specific stuff case "$host" in *-*-aix*) # Some versions of VAC won't allow macro redefinitions at # -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that # particularly with older versions of vac or xlc. # It also throws errors about null macro arguments, but these are # not fatal. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler allows macro redefinitions" >&5 printf %s "checking if compiler allows macro redefinitions... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #define testmacro foo #define testmacro bar int main (void) { exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CC="`echo $CC | 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.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to specify blibpath for linker ($LD)" >&5 printf %s "checking how to specify blibpath for linker ($LD)... " >&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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : blibflags=$tryflags fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi done if (test -z "$blibflags"); then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 printf "%s\n" "not found" >&6; } as_fn_error $? "*** must be able to specify blibpath on AIX - check config.log" "$LINENO" 5 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $blibflags" >&5 printf "%s\n" "$blibflags" >&6; } fi LDFLAGS="$saved_LDFLAGS" ac_fn_c_check_func "$LINENO" "authenticate" "ac_cv_func_authenticate" if test "x$ac_cv_func_authenticate" = xyes then : printf "%s\n" "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for authenticate in -ls" >&5 printf %s "checking for authenticate in -ls... " >&6; } if test ${ac_cv_lib_s_authenticate+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ls $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char authenticate (); int main (void) { return authenticate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_s_authenticate=yes else $as_nop ac_cv_lib_s_authenticate=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_s_authenticate" >&5 printf "%s\n" "$ac_cv_lib_s_authenticate" >&6; } if test "x$ac_cv_lib_s_authenticate" = xyes then : printf "%s\n" "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h LIBS="$LIBS -ls" fi fi ac_fn_check_decl "$LINENO" "authenticate" "ac_cv_have_decl_authenticate" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_authenticate" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_AUTHENTICATE $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "loginrestrictions" "ac_cv_have_decl_loginrestrictions" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_loginrestrictions" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_LOGINRESTRICTIONS $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "loginsuccess" "ac_cv_have_decl_loginsuccess" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_loginsuccess" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_LOGINSUCCESS $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "passwdexpired" "ac_cv_have_decl_passwdexpired" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_passwdexpired" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_PASSWDEXPIRED $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "setauthdb" "ac_cv_have_decl_setauthdb" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_setauthdb" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_SETAUTHDB $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "loginfailed" "ac_cv_have_decl_loginfailed" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_loginfailed" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_LOGINFAILED $ac_have_decl" >>confdefs.h if test $ac_have_decl = 1 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if loginfailed takes 4 arguments" >&5 printf %s "checking if loginfailed takes 4 arguments... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { (void)loginfailed("user","host","tty",0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define AIX_LOGINFAILED_4ARG 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi ac_fn_c_check_func "$LINENO" "getgrset" "ac_cv_func_getgrset" if test "x$ac_cv_func_getgrset" = xyes then : printf "%s\n" "#define HAVE_GETGRSET 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setauthdb" "ac_cv_func_setauthdb" if test "x$ac_cv_func_setauthdb" = xyes then : printf "%s\n" "#define HAVE_SETAUTHDB 1" >>confdefs.h fi ac_fn_check_decl "$LINENO" "F_CLOSEM" "ac_cv_have_decl_F_CLOSEM" " #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_F_CLOSEM" = xyes then : printf "%s\n" "#define HAVE_FCNTL_CLOSEM 1" >>confdefs.h fi check_for_aix_broken_getaddrinfo=1 printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h printf "%s\n" "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h printf "%s\n" "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h printf "%s\n" "#define PTY_ZEROREAD 1" >>confdefs.h printf "%s\n" "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h printf "%s\n" "#define BROKEN_STRNDUP 1" >>confdefs.h printf "%s\n" "#define BROKEN_STRNLEN 1" >>confdefs.h ;; *-*-android*) printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h ;; *-*-cygwin*) LIBS="$LIBS /usr/lib/textreadmode.o" printf "%s\n" "#define HAVE_CYGWIN 1" >>confdefs.h printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h printf "%s\n" "#define DISABLE_SHADOW 1" >>confdefs.h printf "%s\n" "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h printf "%s\n" "#define SSH_IOBUFSZ 65535" >>confdefs.h printf "%s\n" "#define FILESYSTEM_NO_BACKSLASH 1" >>confdefs.h # Cygwin defines optargs, optargs as declspec(dllimport) for historical # reasons which cause compile warnings, so we disable those warnings. { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-attributes" >&5 printf %s "checking if $CC supports compile flag -Wno-attributes... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wno-attributes" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-Wno-attributes" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } SHLIBEXT=".dll" ;; *-*-dgux*) printf "%s\n" "#define IP_TOS_IS_BROKEN 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h ;; *-*-darwin*) use_pie=auto { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we have working getaddrinfo" >&5 printf %s "checking if we have working getaddrinfo... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: assume it is working" >&5 printf "%s\n" "assume it is working" >&6; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) exit(0); else exit(1); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: working" >&5 printf "%s\n" "working" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: buggy" >&5 printf "%s\n" "buggy" >&6; } printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define BROKEN_GLOB 1" >>confdefs.h printf "%s\n" "#define BIND_8_COMPAT 1" >>confdefs.h printf "%s\n" "#define SSH_TUN_FREEBSD 1" >>confdefs.h printf "%s\n" "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h printf "%s\n" "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h ac_fn_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_AU_IPv4" = xyes then : else $as_nop printf "%s\n" "#define AU_IPv4 0" >>confdefs.h #include printf "%s\n" "#define LASTLOG_WRITE_PUTUTXLINE 1" >>confdefs.h fi printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h ac_fn_c_check_func "$LINENO" "sandbox_init" "ac_cv_func_sandbox_init" if test "x$ac_cv_func_sandbox_init" = xyes then : printf "%s\n" "#define HAVE_SANDBOX_INIT 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sandbox.h" "ac_cv_header_sandbox_h" "$ac_includes_default" if test "x$ac_cv_header_sandbox_h" = xyes then : printf "%s\n" "#define HAVE_SANDBOX_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sandbox_apply in -lsandbox" >&5 printf %s "checking for sandbox_apply in -lsandbox... " >&6; } if test ${ac_cv_lib_sandbox_sandbox_apply+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsandbox $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char sandbox_apply (); int main (void) { return sandbox_apply (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_sandbox_sandbox_apply=yes else $as_nop ac_cv_lib_sandbox_sandbox_apply=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sandbox_sandbox_apply" >&5 printf "%s\n" "$ac_cv_lib_sandbox_sandbox_apply" >&6; } if test "x$ac_cv_lib_sandbox_sandbox_apply" = xyes then : SSHDLIBS="$SSHDLIBS -lsandbox" fi # proc_pidinfo()-based closefrom() replacement. ac_fn_c_check_header_compile "$LINENO" "libproc.h" "ac_cv_header_libproc_h" "$ac_includes_default" if test "x$ac_cv_header_libproc_h" = xyes then : printf "%s\n" "#define HAVE_LIBPROC_H 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "proc_pidinfo" "ac_cv_func_proc_pidinfo" if test "x$ac_cv_func_proc_pidinfo" = xyes then : printf "%s\n" "#define HAVE_PROC_PIDINFO 1" >>confdefs.h fi # poll(2) is broken for character-special devices (at least). # cf. Apple bug 3710161 (not public, but searchable) printf "%s\n" "#define BROKEN_POLL 1" >>confdefs.h SHLIBEXT=".dylib" ;; *-*-dragonfly*) SSHDLIBS="$SSHDLIBS" TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-haiku*) LIBS="$LIBS -lbsd " CFLAGS="$CFLAGS -D_BSD_SOURCE" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5 printf %s "checking for socket in -lnetwork... " >&6; } if test ${ac_cv_lib_network_socket+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lnetwork $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char socket (); int main (void) { return socket (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_network_socket=yes else $as_nop ac_cv_lib_network_socket=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5 printf "%s\n" "$ac_cv_lib_network_socket" >&6; } if test "x$ac_cv_lib_network_socket" = xyes then : printf "%s\n" "#define HAVE_LIBNETWORK 1" >>confdefs.h LIBS="-lnetwork $LIBS" fi printf "%s\n" "#define HAVE_U_INT64_T 1" >>confdefs.h printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h 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 printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h printf "%s\n" "#define LOCKED_PASSWD_STRING \"*\"" >>confdefs.h printf "%s\n" "#define SPT_TYPE SPT_PSTAT" >>confdefs.h printf "%s\n" "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h maildir="/var/mail" LIBS="$LIBS -lsec" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for t_error in -lxnet" >&5 printf %s "checking for t_error in -lxnet... " >&6; } if test ${ac_cv_lib_xnet_t_error+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lxnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char t_error (); int main (void) { return t_error (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_xnet_t_error=yes else $as_nop ac_cv_lib_xnet_t_error=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_t_error" >&5 printf "%s\n" "$ac_cv_lib_xnet_t_error" >&6; } if test "x$ac_cv_lib_xnet_t_error" = xyes then : printf "%s\n" "#define HAVE_LIBXNET 1" >>confdefs.h LIBS="-lxnet $LIBS" else $as_nop as_fn_error $? "*** -lxnet needed on HP-UX - check config.log ***" "$LINENO" 5 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 printf "%s\n" "#define BROKEN_GETLINE 1" >>confdefs.h ;; *-*-hpux11*) printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h printf "%s\n" "#define USE_BTMP 1" >>confdefs.h 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) printf "%s\n" "#define HAVE_SECUREWARE 1" >>confdefs.h disable_ptmx_check=yes LIBS="$LIBS -lsecpw" ;; esac ;; *-*-irix5*) PATH="$PATH:/usr/etc" printf "%s\n" "#define BROKEN_INET_NTOA 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h ;; *-*-irix6*) PATH="$PATH:/usr/etc" printf "%s\n" "#define WITH_IRIX_ARRAY 1" >>confdefs.h printf "%s\n" "#define WITH_IRIX_PROJECT 1" >>confdefs.h printf "%s\n" "#define WITH_IRIX_AUDIT 1" >>confdefs.h ac_fn_c_check_func "$LINENO" "jlimit_startjob" "ac_cv_func_jlimit_startjob" if test "x$ac_cv_func_jlimit_startjob" = xyes then : printf "%s\n" "#define WITH_IRIX_JOBS 1" >>confdefs.h fi printf "%s\n" "#define BROKEN_INET_NTOA 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define BROKEN_UPDWTMPX 1" >>confdefs.h printf "%s\n" "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h ;; *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu) printf "%s\n" "#define PAM_TTY_KLUDGE 1" >>confdefs.h printf "%s\n" "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h printf "%s\n" "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h printf "%s\n" "#define USE_BTMP 1" >>confdefs.h ;; *-*-linux*) no_dev_ptmx=1 use_pie=auto check_for_openpty_ctty_bug=1 CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_GNU_SOURCE" printf "%s\n" "#define BROKEN_CLOSEFROM 1" >>confdefs.h printf "%s\n" "#define PAM_TTY_KLUDGE 1" >>confdefs.h printf "%s\n" "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h printf "%s\n" "#define LINK_OPNOTSUPP_ERRNO EPERM" >>confdefs.h printf "%s\n" "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h printf "%s\n" "#define USE_BTMP 1" >>confdefs.h printf "%s\n" "#define LINUX_OOM_ADJUST 1" >>confdefs.h # Check whether --with-linux-memlock-onfault was given. if test ${with_linux_memlock_onfault+y} then : withval=$with_linux_memlock_onfault; if test "x$withval" != "xno" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for MCL_ONFAULT" >&5 printf %s "checking for MCL_ONFAULT... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { mlockall(MCL_FUTURE | MCL_ONFAULT); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: supported" >&5 printf "%s\n" "supported" >&6; } printf "%s\n" "#define LINUX_MEMLOCK_ONFAULT 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not supported" >&5 printf "%s\n" "not supported" >&6; } as_fn_error $? "MCL_ONFAULT is not available on your system" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi printf "%s\n" "#define SYSTEMD_NOTIFY 1" >>confdefs.h inet6_default_4in6=yes case `uname -r` in 1.*|2.0.*) printf "%s\n" "#define BROKEN_CMSG_TYPE 1" >>confdefs.h ;; esac # tun(4) forwarding compat code ac_fn_c_check_header_compile "$LINENO" "linux/if_tun.h" "ac_cv_header_linux_if_tun_h" "$ac_includes_default" if test "x$ac_cv_header_linux_if_tun_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_IF_TUN_H 1" >>confdefs.h fi if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then printf "%s\n" "#define SSH_TUN_LINUX 1" >>confdefs.h printf "%s\n" "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h printf "%s\n" "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "linux/if.h" "ac_cv_header_linux_if_h" " #ifdef HAVE_SYS_TYPES_H # include #endif " if test "x$ac_cv_header_linux_if_h" = xyes then : printf "%s\n" "#define SYS_RDOMAIN_LINUX 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "linux/seccomp.h" "ac_cv_header_linux_seccomp_h" "#include " if test "x$ac_cv_header_linux_seccomp_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_SECCOMP_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "linux/filter.h" "ac_cv_header_linux_filter_h" "#include " if test "x$ac_cv_header_linux_filter_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_FILTER_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "linux/audit.h" "ac_cv_header_linux_audit_h" "#include " if test "x$ac_cv_header_linux_audit_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_AUDIT_H 1" >>confdefs.h fi # Obtain MIPS ABI case "$host" in mips*) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if _MIPS_SIM != _ABIO32 #error #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : mips_abi="o32" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if _MIPS_SIM != _ABIN32 #error #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : mips_abi="n32" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if _MIPS_SIM != _ABI64 #error #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : mips_abi="n64" else $as_nop as_fn_error $? "unknown MIPS ABI" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for seccomp architecture" >&5 printf %s "checking for seccomp architecture... " >&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 ;; aarch64*-*) seccomp_audit_arch=AUDIT_ARCH_AARCH64 ;; s390x-*) seccomp_audit_arch=AUDIT_ARCH_S390X ;; s390-*) seccomp_audit_arch=AUDIT_ARCH_S390 ;; powerpc-*) seccomp_audit_arch=AUDIT_ARCH_PPC ;; powerpc64-*) seccomp_audit_arch=AUDIT_ARCH_PPC64 ;; powerpc64le-*) seccomp_audit_arch=AUDIT_ARCH_PPC64LE ;; mips-*) seccomp_audit_arch=AUDIT_ARCH_MIPS ;; mipsel-*) seccomp_audit_arch=AUDIT_ARCH_MIPSEL ;; mips64-*) case "$mips_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPS64N32 ;; "n64") seccomp_audit_arch=AUDIT_ARCH_MIPS64 ;; esac ;; mips64el-*) case "$mips_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32 ;; "n64") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64 ;; esac ;; riscv64-*) seccomp_audit_arch=AUDIT_ARCH_RISCV64 ;; esac if test "x$seccomp_audit_arch" != "x" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"$seccomp_audit_arch\"" >&5 printf "%s\n" "\"$seccomp_audit_arch\"" >&6; } printf "%s\n" "#define SECCOMP_AUDIT_ARCH $seccomp_audit_arch" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: architecture not supported" >&5 printf "%s\n" "architecture not supported" >&6; } fi ;; *-*-minix) printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h # poll(2) seems to choke on /dev/null; "Bad file descriptor" printf "%s\n" "#define BROKEN_POLL 1" >>confdefs.h ;; mips-sony-bsd|mips-sony-newsos4) printf "%s\n" "#define NEED_SETPGRP 1" >>confdefs.h SONY=1 ;; *-*-netbsd*) if test "x$withval" != "xno" ; then rpath_opt="-R" fi CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE" printf "%s\n" "#define SSH_TUN_FREEBSD 1" >>confdefs.h ac_fn_c_check_header_compile "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default" if test "x$ac_cv_header_net_if_tap_h" = xyes then : else $as_nop printf "%s\n" "#define SSH_TUN_NO_L2 1" >>confdefs.h fi printf "%s\n" "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h TEST_MALLOC_OPTIONS="AJRX" printf "%s\n" "#define BROKEN_READ_COMPARISON 1" >>confdefs.h ;; *-*-freebsd*) printf "%s\n" "#define LOCKED_PASSWD_PREFIX \"*LOCKED*\"" >>confdefs.h printf "%s\n" "#define SSH_TUN_FREEBSD 1" >>confdefs.h ac_fn_c_check_header_compile "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default" if test "x$ac_cv_header_net_if_tap_h" = xyes then : else $as_nop printf "%s\n" "#define SSH_TUN_NO_L2 1" >>confdefs.h fi printf "%s\n" "#define BROKEN_GLOB 1" >>confdefs.h TEST_MALLOC_OPTIONS="AJRX" # Preauth crypto occasionally uses file descriptors for crypto offload # and will crash if they cannot be opened. printf "%s\n" "#define SANDBOX_SKIP_RLIMIT_NOFILE 1" >>confdefs.h case "$host" in *-*-freebsd9.*|*-*-freebsd10.*) # Capsicum on 9 and 10 do not allow ppoll() so don't auto-enable. disable_capsicum=yes esac ;; *-*-bsdi*) printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h ;; *-next-*) conf_lastlog_location="/usr/adm/lastlog" conf_utmp_location=/etc/utmp conf_wtmp_location=/usr/adm/wtmp maildir=/usr/spool/mail printf "%s\n" "#define HAVE_NEXT 1" >>confdefs.h printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define BROKEN_SAVED_UIDS 1" >>confdefs.h ;; *-*-openbsd*) use_pie=auto printf "%s\n" "#define HAVE_ATTRIBUTE__SENTINEL__ 1" >>confdefs.h printf "%s\n" "#define HAVE_ATTRIBUTE__BOUNDED__ 1" >>confdefs.h printf "%s\n" "#define SSH_TUN_OPENBSD 1" >>confdefs.h printf "%s\n" "#define SYSLOG_R_SAFE_IN_SIGHAND 1" >>confdefs.h TEST_MALLOC_OPTIONS="SJRU" ;; *-*-solaris*) if test "x$withval" != "xno" ; then rpath_opt="-R" fi printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h printf "%s\n" "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h printf "%s\n" "#define PAM_TTY_KLUDGE 1" >>confdefs.h printf "%s\n" "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h # Pushing STREAMS modules will cause sshd to acquire a controlling tty. printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h printf "%s\n" "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h external_path_file=/etc/default/login # hardwire lastlog location (can't detect it on some versions) conf_lastlog_location="/var/adm/lastlog" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for obsolete utmp and wtmp in solaris2.x" >&5 printf %s "checking for obsolete utmp and wtmp in solaris2.x... " >&6; } sol2ver=`echo "$host"| sed -e 's/.*[0-9]\.//'` if test "$sol2ver" -ge 8; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi ac_fn_c_check_func "$LINENO" "setpflags" "ac_cv_func_setpflags" if test "x$ac_cv_func_setpflags" = xyes then : printf "%s\n" "#define HAVE_SETPFLAGS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setppriv" "ac_cv_func_setppriv" if test "x$ac_cv_func_setppriv" = xyes then : printf "%s\n" "#define HAVE_SETPPRIV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "priv_basicset" "ac_cv_func_priv_basicset" if test "x$ac_cv_func_priv_basicset" = xyes then : printf "%s\n" "#define HAVE_PRIV_BASICSET 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "priv.h" "ac_cv_header_priv_h" "$ac_includes_default" if test "x$ac_cv_header_priv_h" = xyes then : printf "%s\n" "#define HAVE_PRIV_H 1" >>confdefs.h fi # Check whether --with-solaris-contracts was given. if test ${with_solaris_contracts+y} then : withval=$with_solaris_contracts; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ct_tmpl_activate in -lcontract" >&5 printf %s "checking for ct_tmpl_activate in -lcontract... " >&6; } if test ${ac_cv_lib_contract_ct_tmpl_activate+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lcontract $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char ct_tmpl_activate (); int main (void) { return ct_tmpl_activate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_contract_ct_tmpl_activate=yes else $as_nop ac_cv_lib_contract_ct_tmpl_activate=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_contract_ct_tmpl_activate" >&5 printf "%s\n" "$ac_cv_lib_contract_ct_tmpl_activate" >&6; } if test "x$ac_cv_lib_contract_ct_tmpl_activate" = xyes then : printf "%s\n" "#define USE_SOLARIS_PROCESS_CONTRACTS 1" >>confdefs.h LIBS="$LIBS -lcontract" SPC_MSG="yes" fi fi # Check whether --with-solaris-projects was given. if test ${with_solaris_projects+y} then : withval=$with_solaris_projects; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setproject in -lproject" >&5 printf %s "checking for setproject in -lproject... " >&6; } if test ${ac_cv_lib_project_setproject+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lproject $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char setproject (); int main (void) { return setproject (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_project_setproject=yes else $as_nop ac_cv_lib_project_setproject=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_project_setproject" >&5 printf "%s\n" "$ac_cv_lib_project_setproject" >&6; } if test "x$ac_cv_lib_project_setproject" = xyes then : printf "%s\n" "#define USE_SOLARIS_PROJECTS 1" >>confdefs.h LIBS="$LIBS -lproject" SP_MSG="yes" fi fi # Check whether --with-solaris-privs was given. if test ${with_solaris_privs+y} then : withval=$with_solaris_privs; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Solaris/Illumos privilege support" >&5 printf %s "checking for Solaris/Illumos privilege support... " >&6; } if test "x$ac_cv_func_setppriv" = "xyes" -a \ "x$ac_cv_header_priv_h" = "xyes" ; then SOLARIS_PRIVS=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found" >&5 printf "%s\n" "found" >&6; } printf "%s\n" "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h printf "%s\n" "#define USE_SOLARIS_PRIVS 1" >>confdefs.h SPP_MSG="yes" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 printf "%s\n" "not found" >&6; } as_fn_error $? "*** must have support for Solaris privileges to use --with-solaris-privs" "$LINENO" 5 fi fi TEST_SHELL=$SHELL # let configure find us a capable shell ;; *-*-sunos4*) CPPFLAGS="$CPPFLAGS -DSUNOS4" ac_fn_c_check_func "$LINENO" "getpwanam" "ac_cv_func_getpwanam" if test "x$ac_cv_func_getpwanam" = xyes then : printf "%s\n" "#define HAVE_GETPWANAM 1" >>confdefs.h fi printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h conf_utmp_location=/etc/utmp conf_wtmp_location=/var/adm/wtmp conf_lastlog_location=/var/adm/lastlog printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h ;; *-ncr-sysv*) LIBS="$LIBS -lc89" printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h ;; *-sni-sysv*) # /usr/ucblib MUST NOT be searched on ReliantUNIX { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5 printf %s "checking for dlsym in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlsym+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlsym (); int main (void) { return dlsym (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlsym=yes else $as_nop ac_cv_lib_dl_dlsym=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5 printf "%s\n" "$ac_cv_lib_dl_dlsym" >&6; } if test "x$ac_cv_lib_dl_dlsym" = xyes then : printf "%s\n" "#define HAVE_LIBDL 1" >>confdefs.h LIBS="-ldl $LIBS" fi # -lresolv needs to be at the end of LIBS or DNS lookups break { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5 printf %s "checking for res_query in -lresolv... " >&6; } if test ${ac_cv_lib_resolv_res_query+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char res_query (); int main (void) { return res_query (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_resolv_res_query=yes else $as_nop ac_cv_lib_resolv_res_query=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_query" >&5 printf "%s\n" "$ac_cv_lib_resolv_res_query" >&6; } if test "x$ac_cv_lib_resolv_res_query" = xyes then : LIBS="$LIBS -lresolv" fi IPADDR_IN_DISPLAY=yes printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define IP_TOS_IS_BROKEN 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h 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*) printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h TEST_SHELL=$SHELL # let configure find us a capable shell ;; # UnixWare 7.x, OpenUNIX 8 *-*-sysv5*) CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf" printf "%s\n" "#define UNIXWARE_LONG_PASSWORDS 1" >>confdefs.h printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h printf "%s\n" "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h TEST_SHELL=$SHELL # let configure find us a capable shell case "$host" in *-*-sysv5SCO_SV*) # SCO OpenServer 6.x maildir=/var/spool/mail printf "%s\n" "#define BROKEN_UPDWTMPX 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getluid in -lprot" >&5 printf %s "checking for getluid in -lprot... " >&6; } if test ${ac_cv_lib_prot_getluid+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lprot $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char getluid (); int main (void) { return getluid (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_prot_getluid=yes else $as_nop ac_cv_lib_prot_getluid=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_prot_getluid" >&5 printf "%s\n" "$ac_cv_lib_prot_getluid" >&6; } if test "x$ac_cv_lib_prot_getluid" = xyes then : LIBS="$LIBS -lprot" ac_fn_c_check_func "$LINENO" "getluid" "ac_cv_func_getluid" if test "x$ac_cv_func_getluid" = xyes then : printf "%s\n" "#define HAVE_GETLUID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setluid" "ac_cv_func_setluid" if test "x$ac_cv_func_setluid" = xyes then : printf "%s\n" "#define HAVE_SETLUID 1" >>confdefs.h fi fi ;; *) printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h ;; esac ;; *-*-sysv*) ;; # SCO UNIX and OEM versions of SCO UNIX *-*-sco3.2v4*) as_fn_error $? "\"This Platform is no longer supported.\"" "$LINENO" 5 ;; # 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 printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define HAVE_SECUREWARE 1" >>confdefs.h printf "%s\n" "#define DISABLE_SHADOW 1" >>confdefs.h printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h printf "%s\n" "#define BROKEN_UPDWTMPX 1" >>confdefs.h printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h ac_fn_c_check_func "$LINENO" "getluid" "ac_cv_func_getluid" if test "x$ac_cv_func_getluid" = xyes then : printf "%s\n" "#define HAVE_GETLUID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setluid" "ac_cv_func_setluid" if test "x$ac_cv_func_setluid" = xyes then : printf "%s\n" "#define HAVE_SETLUID 1" >>confdefs.h fi MANTYPE=man TEST_SHELL=$SHELL # let configure find us a capable shell SKIP_DISABLE_LASTLOG_DEFINE=yes ;; *-dec-osf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Digital Unix SIA" >&5 printf %s "checking for Digital Unix SIA... " >&6; } no_osfsia="" # Check whether --with-osfsia was given. if test ${with_osfsia+y} then : withval=$with_osfsia; if test "x$withval" = "xno" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 printf "%s\n" "disabled" >&6; } no_osfsia=1 fi fi if test -z "$no_osfsia" ; then if test -f /etc/sia/matrix.conf; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_OSF_SIA 1" >>confdefs.h printf "%s\n" "#define DISABLE_LOGIN 1" >>confdefs.h printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h LIBS="$LIBS -lsecurity -ldb -lm -laud" SIA_MSG="yes" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define LOCKED_PASSWD_SUBSTR \"Nologin\"" >>confdefs.h fi fi printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h printf "%s\n" "#define BROKEN_READV_COMPARISON 1" >>confdefs.h ;; *-*-nto-qnx*) printf "%s\n" "#define USE_PIPES 1" >>confdefs.h printf "%s\n" "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h printf "%s\n" "#define BROKEN_SHADOW_EXPIRE 1" >>confdefs.h enable_etc_default_login=no # has incompatible /etc/default/login case "$host" in *-*-nto-qnx6*) printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h ;; esac ;; *-*-ultrix*) printf "%s\n" "#define BROKEN_GETGROUPS 1" >>confdefs.h printf "%s\n" "#define NEED_SETPGRP 1" >>confdefs.h printf "%s\n" "#define HAVE_SYS_SYSLOG_H 1" >>confdefs.h printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h # DISABLE_FD_PASSING so that we call setpgrp as root, otherwise we # don't get a controlling tty. printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h # On Ultrix some headers are not protected against multiple includes, # so we create wrappers and put it where the compiler will find it. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: creating compat wrappers for headers" >&5 printf "%s\n" "$as_me: WARNING: creating compat wrappers for headers" >&2;} mkdir -p netinet for header in netinet/ip.h netdb.h resolv.h; do name=`echo $header | tr 'a-z/.' 'A-Z__'` cat >$header <>confdefs.h ;; *-*-gnu*) CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_GNU_SOURCE" ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler and flags for sanity" >&5 printf %s "checking compiler and flags for sanity... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking compiler sanity" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking compiler sanity" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { exit(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } as_fn_error $? "*** compiler cannot create working executables, check config.log ***" "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi # Checks for libraries. ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" if test "x$ac_cv_func_setsockopt" = xyes then : else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5 printf %s "checking for setsockopt in -lsocket... " >&6; } if test ${ac_cv_lib_socket_setsockopt+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char setsockopt (); int main (void) { return setsockopt (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_socket_setsockopt=yes else $as_nop ac_cv_lib_socket_setsockopt=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5 printf "%s\n" "$ac_cv_lib_socket_setsockopt" >&6; } if test "x$ac_cv_lib_socket_setsockopt" = xyes then : printf "%s\n" "#define HAVE_LIBSOCKET 1" >>confdefs.h LIBS="-lsocket $LIBS" fi fi for ac_func in dirname do : ac_fn_c_check_func "$LINENO" "dirname" "ac_cv_func_dirname" if test "x$ac_cv_func_dirname" = xyes then : printf "%s\n" "#define HAVE_DIRNAME 1" >>confdefs.h ac_fn_c_check_header_compile "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default" if test "x$ac_cv_header_libgen_h" = xyes then : printf "%s\n" "#define HAVE_LIBGEN_H 1" >>confdefs.h fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dirname in -lgen" >&5 printf %s "checking for dirname in -lgen... " >&6; } if test ${ac_cv_lib_gen_dirname+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lgen $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dirname (); int main (void) { return dirname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_gen_dirname=yes else $as_nop ac_cv_lib_gen_dirname=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_dirname" >&5 printf "%s\n" "$ac_cv_lib_gen_dirname" >&6; } if test "x$ac_cv_lib_gen_dirname" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for broken dirname" >&5 printf %s "checking for broken dirname... " >&6; } if test ${ac_cv_have_broken_dirname+y} then : printf %s "(cached) " >&6 else $as_nop save_LIBS="$LIBS" LIBS="$LIBS -lgen" if test "$cross_compiling" = yes then : ac_cv_have_broken_dirname="no" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main(int argc, char **argv) { char *s, buf[32]; strncpy(buf,"/etc", 32); s = dirname(buf); if (!s || strncmp(s, "/", 32) != 0) { exit(1); } else { exit(0); } } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_have_broken_dirname="no" else $as_nop ac_cv_have_broken_dirname="yes" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi LIBS="$save_LIBS" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_broken_dirname" >&5 printf "%s\n" "$ac_cv_have_broken_dirname" >&6; } if test "x$ac_cv_have_broken_dirname" = "xno" ; then LIBS="$LIBS -lgen" printf "%s\n" "#define HAVE_DIRNAME 1" >>confdefs.h ac_fn_c_check_header_compile "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default" if test "x$ac_cv_header_libgen_h" = xyes then : printf "%s\n" "#define HAVE_LIBGEN_H 1" >>confdefs.h fi fi fi fi done ac_fn_c_check_func "$LINENO" "getspnam" "ac_cv_func_getspnam" if test "x$ac_cv_func_getspnam" = xyes then : else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getspnam in -lgen" >&5 printf %s "checking for getspnam in -lgen... " >&6; } if test ${ac_cv_lib_gen_getspnam+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lgen $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char getspnam (); int main (void) { return getspnam (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_gen_getspnam=yes else $as_nop ac_cv_lib_gen_getspnam=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_getspnam" >&5 printf "%s\n" "$ac_cv_lib_gen_getspnam" >&6; } if test "x$ac_cv_lib_gen_getspnam" = xyes then : LIBS="$LIBS -lgen" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing basename" >&5 printf %s "checking for library containing basename... " >&6; } if test ${ac_cv_search_basename+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char basename (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_basename=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_basename+y} then : break fi done if test ${ac_cv_search_basename+y} then : else $as_nop ac_cv_search_basename=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_basename" >&5 printf "%s\n" "$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" printf "%s\n" "#define HAVE_BASENAME 1" >>confdefs.h fi zlib=yes # Check whether --with-zlib was given. if test ${with_zlib+y} then : withval=$with_zlib; if test "x$withval" = "xno" ; then zlib=no elif test "x$withval" != "xyes"; then if test -d "$withval/lib"; then if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi else if test -n "${rpath_opt}"; then LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}" else LDFLAGS="-L${withval} ${LDFLAGS}" fi fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi fi # These libraries are needed for anything that links in the channel code. CHANNELLIBS="" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib" >&5 printf %s "checking for zlib... " >&6; } if test "x${zlib}" = "xno"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else saved_LIBS="$LIBS" CHANNELLIBS="$CHANNELLIBS -lz" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define WITH_ZLIB 1" >>confdefs.h ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes then : else $as_nop as_fn_error $? "*** zlib.h missing - please install first or check config.log ***" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5 printf %s "checking for deflate in -lz... " >&6; } if test ${ac_cv_lib_z_deflate+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char deflate (); int main (void) { return deflate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_z_deflate=yes else $as_nop ac_cv_lib_z_deflate=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5 printf "%s\n" "$ac_cv_lib_z_deflate" >&6; } if test "x$ac_cv_lib_z_deflate" = xyes then : printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h LIBS="-lz $LIBS" else $as_nop saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$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 CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char deflate (); int main (void) { return deflate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h else $as_nop as_fn_error $? "*** zlib missing - please install first or check config.log ***" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi # Check whether --with-zlib-version-check was given. if test ${with_zlib_version_check+y} then : withval=$with_zlib_version_check; if test "x$withval" = "xno" ; then zlib_check_nonfatal=1 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for possibly buggy zlib" >&5 printf %s "checking for possibly buggy zlib... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking zlib version" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking zlib version" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { int a=0, b=0, c=0, d=0, n, v; n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d); if (n < 1) exit(1); v = a*1000000 + b*10000 + c*100 + d; fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v); /* 1.1.4 is OK */ if (a == 1 && b == 1 && c >= 4) exit(0); /* 1.2.3 and up are OK */ if (v >= 1020300) exit(0); exit(2); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } if test -z "$zlib_check_nonfatal" ; then as_fn_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." "$LINENO" 5 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: zlib version may have security problems" >&5 printf "%s\n" "$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.beam conftest.$ac_ext fi LIBS="$saved_LIBS" fi ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp" if test "x$ac_cv_func_strcasecmp" = xyes then : else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strcasecmp in -lresolv" >&5 printf %s "checking for strcasecmp in -lresolv... " >&6; } if test ${ac_cv_lib_resolv_strcasecmp+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char strcasecmp (); int main (void) { return strcasecmp (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_resolv_strcasecmp=yes else $as_nop ac_cv_lib_resolv_strcasecmp=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_strcasecmp" >&5 printf "%s\n" "$ac_cv_lib_resolv_strcasecmp" >&6; } if test "x$ac_cv_lib_resolv_strcasecmp" = xyes then : LIBS="$LIBS -lresolv" fi fi for ac_func in utimes do : ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes" if test "x$ac_cv_func_utimes" = xyes then : printf "%s\n" "#define HAVE_UTIMES 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for utimes in -lc89" >&5 printf %s "checking for utimes in -lc89... " >&6; } if test ${ac_cv_lib_c89_utimes+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lc89 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char utimes (); int main (void) { return utimes (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_c89_utimes=yes else $as_nop ac_cv_lib_c89_utimes=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c89_utimes" >&5 printf "%s\n" "$ac_cv_lib_c89_utimes" >&6; } if test "x$ac_cv_lib_c89_utimes" = xyes then : printf "%s\n" "#define HAVE_UTIMES 1" >>confdefs.h LIBS="$LIBS -lc89" fi fi done ac_fn_c_check_header_compile "$LINENO" "bsd/libutil.h" "ac_cv_header_bsd_libutil_h" "$ac_includes_default" if test "x$ac_cv_header_bsd_libutil_h" = xyes then : printf "%s\n" "#define HAVE_BSD_LIBUTIL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "libutil.h" "ac_cv_header_libutil_h" "$ac_includes_default" if test "x$ac_cv_header_libutil_h" = xyes then : printf "%s\n" "#define HAVE_LIBUTIL_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing fmt_scaled" >&5 printf %s "checking for library containing fmt_scaled... " >&6; } if test ${ac_cv_search_fmt_scaled+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char fmt_scaled (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_fmt_scaled=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_fmt_scaled+y} then : break fi done if test ${ac_cv_search_fmt_scaled+y} then : else $as_nop ac_cv_search_fmt_scaled=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fmt_scaled" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing scan_scaled" >&5 printf %s "checking for library containing scan_scaled... " >&6; } if test ${ac_cv_search_scan_scaled+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char scan_scaled (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_scan_scaled=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_scan_scaled+y} then : break fi done if test ${ac_cv_search_scan_scaled+y} then : else $as_nop ac_cv_search_scan_scaled=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_scan_scaled" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing login" >&5 printf %s "checking for library containing login... " >&6; } if test ${ac_cv_search_login+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char login (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_login=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_login+y} then : break fi done if test ${ac_cv_search_login+y} then : else $as_nop ac_cv_search_login=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_login" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing logout" >&5 printf %s "checking for library containing logout... " >&6; } if test ${ac_cv_search_logout+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char logout (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_logout=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_logout+y} then : break fi done if test ${ac_cv_search_logout+y} then : else $as_nop ac_cv_search_logout=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logout" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing logwtmp" >&5 printf %s "checking for library containing logwtmp... " >&6; } if test ${ac_cv_search_logwtmp+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char logwtmp (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_logwtmp=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_logwtmp+y} then : break fi done if test ${ac_cv_search_logwtmp+y} then : else $as_nop ac_cv_search_logwtmp=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logwtmp" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing openpty" >&5 printf %s "checking for library containing openpty... " >&6; } if test ${ac_cv_search_openpty+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char openpty (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_openpty=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_openpty+y} then : break fi done if test ${ac_cv_search_openpty+y} then : else $as_nop ac_cv_search_openpty=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_openpty" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing updwtmp" >&5 printf %s "checking for library containing updwtmp... " >&6; } if test ${ac_cv_search_updwtmp+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char updwtmp (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_updwtmp=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_updwtmp+y} then : break fi done if test ${ac_cv_search_updwtmp+y} then : else $as_nop ac_cv_search_updwtmp=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_updwtmp" >&5 printf "%s\n" "$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 ac_fn_c_check_func "$LINENO" "fmt_scaled" "ac_cv_func_fmt_scaled" if test "x$ac_cv_func_fmt_scaled" = xyes then : printf "%s\n" "#define HAVE_FMT_SCALED 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "scan_scaled" "ac_cv_func_scan_scaled" if test "x$ac_cv_func_scan_scaled" = xyes then : printf "%s\n" "#define HAVE_SCAN_SCALED 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "login" "ac_cv_func_login" if test "x$ac_cv_func_login" = xyes then : printf "%s\n" "#define HAVE_LOGIN 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "logout" "ac_cv_func_logout" if test "x$ac_cv_func_logout" = xyes then : printf "%s\n" "#define HAVE_LOGOUT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "openpty" "ac_cv_func_openpty" if test "x$ac_cv_func_openpty" = xyes then : printf "%s\n" "#define HAVE_OPENPTY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "updwtmp" "ac_cv_func_updwtmp" if test "x$ac_cv_func_updwtmp" = xyes then : printf "%s\n" "#define HAVE_UPDWTMP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "logwtmp" "ac_cv_func_logwtmp" if test "x$ac_cv_func_logwtmp" = xyes then : printf "%s\n" "#define HAVE_LOGWTMP 1" >>confdefs.h fi # On some platforms, inet_ntop and gethostbyname may be found in libresolv # or libnsl. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntop" >&5 printf %s "checking for library containing inet_ntop... " >&6; } if test ${ac_cv_search_inet_ntop+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char inet_ntop (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_inet_ntop=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_inet_ntop+y} then : break fi done if test ${ac_cv_search_inet_ntop+y} then : else $as_nop ac_cv_search_inet_ntop=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_ntop" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 printf %s "checking for library containing gethostbyname... " >&6; } if test ${ac_cv_search_gethostbyname+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gethostbyname (); int main (void) { return gethostbyname (); ; 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_gethostbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_gethostbyname+y} then : break fi done if test ${ac_cv_search_gethostbyname+y} then : else $as_nop ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 printf "%s\n" "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # Some Linux distribtions ship the BSD libc hashing functions in # separate libraries. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing SHA256Update" >&5 printf %s "checking for library containing SHA256Update... " >&6; } if test ${ac_cv_search_SHA256Update+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char SHA256Update (); int main (void) { return SHA256Update (); ; return 0; } _ACEOF for ac_lib in '' md 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_SHA256Update=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_SHA256Update+y} then : break fi done if test ${ac_cv_search_SHA256Update+y} then : else $as_nop ac_cv_search_SHA256Update=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SHA256Update" >&5 printf "%s\n" "$ac_cv_search_SHA256Update" >&6; } ac_res=$ac_cv_search_SHA256Update if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # "Particular Function Checks" # see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" if test "x$ac_cv_func_strftime" = xyes then : printf "%s\n" "#define HAVE_STRFTIME 1" >>confdefs.h else $as_nop # strftime is in -lintl on SCO UNIX. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 printf %s "checking for strftime in -lintl... " >&6; } if test ${ac_cv_lib_intl_strftime+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char strftime (); int main (void) { return strftime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_intl_strftime=yes else $as_nop ac_cv_lib_intl_strftime=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 printf "%s\n" "$ac_cv_lib_intl_strftime" >&6; } if test "x$ac_cv_lib_intl_strftime" = xyes then : printf "%s\n" "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 printf %s "checking for GNU libc compatible malloc... " >&6; } if test ${ac_cv_func_malloc_0_nonnull+y} then : printf %s "(cached) " >&6 else $as_nop if test "$cross_compiling" = yes then : case "$host_os" in # (( # Guess yes on platforms where we know the result. *-gnu* | freebsd* | netbsd* | openbsd* | bitrig* \ | hpux* | solaris* | cygwin* | mingw* | msys* ) ac_cv_func_malloc_0_nonnull=yes ;; # If we don't know, assume the worst. *) ac_cv_func_malloc_0_nonnull=no ;; esac else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { void *p = malloc (0); int result = !p; free (p); return result; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_func_malloc_0_nonnull=yes else $as_nop ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 printf "%s\n" "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes then : printf "%s\n" "#define HAVE_MALLOC 1" >>confdefs.h else $as_nop printf "%s\n" "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac printf "%s\n" "#define malloc rpl_malloc" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 printf %s "checking for GNU libc compatible realloc... " >&6; } if test ${ac_cv_func_realloc_0_nonnull+y} then : printf %s "(cached) " >&6 else $as_nop if test "$cross_compiling" = yes then : case "$host_os" in # (( # Guess yes on platforms where we know the result. *-gnu* | freebsd* | netbsd* | openbsd* | bitrig* \ | hpux* | solaris* | cygwin* | mingw* | msys* ) ac_cv_func_realloc_0_nonnull=yes ;; # If we don't know, assume the worst. *) ac_cv_func_realloc_0_nonnull=no ;; esac else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { void *p = realloc (0, 0); int result = !p; free (p); return result; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_func_realloc_0_nonnull=yes else $as_nop ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 printf "%s\n" "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes then : printf "%s\n" "#define HAVE_REALLOC 1" >>confdefs.h else $as_nop printf "%s\n" "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac printf "%s\n" "#define realloc rpl_realloc" >>confdefs.h fi # autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if calloc(0, N) returns non-null" >&5 printf %s "checking if calloc(0, N) returns non-null... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming same as malloc" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming same as malloc" >&2;} func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { void *p = calloc(0, 1); exit(p == NULL); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : func_calloc_0_nonnull=yes else $as_nop func_calloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $func_calloc_0_nonnull" >&5 printf "%s\n" "$func_calloc_0_nonnull" >&6; } if test "x$func_calloc_0_nonnull" = "xyes"; then printf "%s\n" "#define HAVE_CALLOC 1" >>confdefs.h else printf "%s\n" "#define HAVE_CALLOC 0" >>confdefs.h printf "%s\n" "#define calloc rpl_calloc" >>confdefs.h fi # Check for ALTDIRFUNC glob() extension { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GLOB_ALTDIRFUNC support" >&5 printf %s "checking for GLOB_ALTDIRFUNC support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef GLOB_ALTDIRFUNC FOUNDIT #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "FOUNDIT" >/dev/null 2>&1 then : printf "%s\n" "#define GLOB_HAS_ALTDIRFUNC 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -rf conftest* # Check for g.gl_matchc glob() extension { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gl_matchc field in glob_t" >&5 printf %s "checking for gl_matchc field in glob_t... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { glob_t g; g.gl_matchc = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define GLOB_HAS_GL_MATCHC 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Check for g.gl_statv glob() extension { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gl_statv and GLOB_KEEPSTAT extensions for glob" >&5 printf %s "checking for gl_statv and GLOB_KEEPSTAT extensions for glob... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #ifndef GLOB_KEEPSTAT #error "glob does not support GLOB_KEEPSTAT extension" #endif glob_t g; g.gl_statv = NULL; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define GLOB_HAS_GL_STATV 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_fn_check_decl "$LINENO" "GLOB_NOMATCH" "ac_cv_have_decl_GLOB_NOMATCH" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_GLOB_NOMATCH" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_GLOB_NOMATCH $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "VIS_ALL" "ac_cv_have_decl_VIS_ALL" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_VIS_ALL" = xyes then : else $as_nop printf "%s\n" "#define BROKEN_STRNVIS 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether struct dirent allocates space for d_name" >&5 printf %s "checking whether struct dirent allocates space for d_name... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;} printf "%s\n" "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { struct dirent d; exit(sizeof(d.d_name)<=sizeof(char)); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for /proc/pid/fd directory" >&5 printf %s "checking for /proc/pid/fd directory... " >&6; } if test -d "/proc/$$/fd" ; then printf "%s\n" "#define HAVE_PROC_PID 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Check whether user wants to use ldns LDNS_MSG="no" # Check whether --with-ldns was given. if test ${with_ldns+y} then : withval=$with_ldns; ldns="" if test "x$withval" = "xyes" ; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ldns-config", so it can be a program name with args. set dummy ${ac_tool_prefix}ldns-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_LDNSCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $LDNSCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_LDNSCONFIG="$LDNSCONFIG" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_LDNSCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi LDNSCONFIG=$ac_cv_path_LDNSCONFIG if test -n "$LDNSCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LDNSCONFIG" >&5 printf "%s\n" "$LDNSCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_LDNSCONFIG"; then ac_pt_LDNSCONFIG=$LDNSCONFIG # Extract the first word of "ldns-config", so it can be a program name with args. set dummy ldns-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_LDNSCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_LDNSCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_LDNSCONFIG="$ac_pt_LDNSCONFIG" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_LDNSCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_LDNSCONFIG=$ac_cv_path_ac_pt_LDNSCONFIG if test -n "$ac_pt_LDNSCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LDNSCONFIG" >&5 printf "%s\n" "$ac_pt_LDNSCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_LDNSCONFIG" = x; then LDNSCONFIG="no" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LDNSCONFIG=$ac_pt_LDNSCONFIG fi else LDNSCONFIG="$ac_cv_path_LDNSCONFIG" fi if test "x$LDNSCONFIG" = "xno"; then LIBS="-lldns $LIBS" ldns=yes else LIBS="$LIBS `$LDNSCONFIG --libs`" CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`" ldns=yes fi elif test "x$withval" != "xno" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" LIBS="-lldns $LIBS" ldns=yes fi # Verify that it works. if test "x$ldns" = "xyes" ; then printf "%s\n" "#define HAVE_LDNS 1" >>confdefs.h LDNS_MSG="yes" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ldns support" >&5 printf %s "checking for ldns support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_STDINT_H # include #endif #include int main(void) { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } as_fn_error $? "** Incomplete or missing ldns libraries." "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ 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+y} then : withval=$with_libedit; if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then if test "x$PKGCONFIG" != "xno"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about libedit" >&5 printf %s "checking if $PKGCONFIG knows about libedit... " >&6; } if "$PKGCONFIG" libedit; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } use_pkgconfig_for_libedit=yes else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi else CPPFLAGS="$CPPFLAGS -I${withval}/include" if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi fi if test "x$use_pkgconfig_for_libedit" = "xyes"; then LIBEDIT=`$PKGCONFIG --libs libedit` CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`" else LIBEDIT="-ledit -lcurses" fi OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for el_init in -ledit" >&5 printf %s "checking for el_init in -ledit... " >&6; } if test ${ac_cv_lib_edit_el_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ledit $OTHERLIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char el_init (); int main (void) { return el_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_edit_el_init=yes else $as_nop ac_cv_lib_edit_el_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_el_init" >&5 printf "%s\n" "$ac_cv_lib_edit_el_init" >&6; } if test "x$ac_cv_lib_edit_el_init" = xyes then : printf "%s\n" "#define USE_LIBEDIT 1" >>confdefs.h LIBEDIT_MSG="yes" else $as_nop as_fn_error $? "libedit not found" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libedit version is compatible" >&5 printf %s "checking if libedit version is compatible... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { int i = H_SETSIZE; el_init("", NULL, NULL, NULL); exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } as_fn_error $? "libedit version is not compatible" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi # Check whether user wants wtmpdb support WTMPDB_MSG="no" # Check whether --with-wtmpdb was given. if test ${with_wtmpdb+y} then : withval=$with_wtmpdb; if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then if test "x$PKGCONFIG" != "xno"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about wtmpdb" >&5 printf %s "checking if $PKGCONFIG knows about wtmpdb... " >&6; } if "$PKGCONFIG" libwtmpdb; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } use_pkgconfig_for_libwtmpdb=yes else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi else CPPFLAGS="$CPPFLAGS -I${withval}/include" if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi fi if test "x$use_pkgconfig_for_libwtmpdb" = "xyes"; then LIBWTMPDB=`$PKGCONFIG --libs libwtmpdb` CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libwtmpdb`" else LIBWTMPDB="-lwtmpdb" fi OTHERLIBS=`echo $LIBWTMPDB | sed 's/-lwtmpdb//'` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wtmpdb_login in -lwtmpdb" >&5 printf %s "checking for wtmpdb_login in -lwtmpdb... " >&6; } if test ${ac_cv_lib_wtmpdb_wtmpdb_login+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lwtmpdb $OTHERLIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char wtmpdb_login (); int main (void) { return wtmpdb_login (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_wtmpdb_wtmpdb_login=yes else $as_nop ac_cv_lib_wtmpdb_wtmpdb_login=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wtmpdb_wtmpdb_login" >&5 printf "%s\n" "$ac_cv_lib_wtmpdb_wtmpdb_login" >&6; } if test "x$ac_cv_lib_wtmpdb_wtmpdb_login" = xyes then : printf "%s\n" "#define USE_WTMPDB 1" >>confdefs.h WTMPDB_MSG="yes" else $as_nop as_fn_error $? "libwtmpdb not found" "$LINENO" 5 fi fi fi AUDIT_MODULE=none # Check whether --with-audit was given. if test ${with_audit+y} then : withval=$with_audit; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for supported audit module" >&5 printf %s "checking for supported audit module... " >&6; } case "$withval" in bsm) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: bsm" >&5 printf "%s\n" "bsm" >&6; } AUDIT_MODULE=bsm for ac_header in bsm/audit.h do : ac_fn_c_check_header_compile "$LINENO" "bsm/audit.h" "ac_cv_header_bsm_audit_h" " #ifdef HAVE_TIME_H # include #endif " if test "x$ac_cv_header_bsm_audit_h" = xyes then : printf "%s\n" "#define HAVE_BSM_AUDIT_H 1" >>confdefs.h else $as_nop as_fn_error $? "BSM enabled and bsm/audit.h not found" "$LINENO" 5 fi done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getaudit in -lbsm" >&5 printf %s "checking for getaudit in -lbsm... " >&6; } if test ${ac_cv_lib_bsm_getaudit+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lbsm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char getaudit (); int main (void) { return getaudit (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_bsm_getaudit=yes else $as_nop ac_cv_lib_bsm_getaudit=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsm_getaudit" >&5 printf "%s\n" "$ac_cv_lib_bsm_getaudit" >&6; } if test "x$ac_cv_lib_bsm_getaudit" = xyes then : printf "%s\n" "#define HAVE_LIBBSM 1" >>confdefs.h LIBS="-lbsm $LIBS" else $as_nop as_fn_error $? "BSM enabled and required library not found" "$LINENO" 5 fi for ac_func in getaudit do : ac_fn_c_check_func "$LINENO" "getaudit" "ac_cv_func_getaudit" if test "x$ac_cv_func_getaudit" = xyes then : printf "%s\n" "#define HAVE_GETAUDIT 1" >>confdefs.h else $as_nop as_fn_error $? "BSM enabled and required function not found" "$LINENO" 5 fi done # These are optional ac_fn_c_check_func "$LINENO" "getaudit_addr" "ac_cv_func_getaudit_addr" if test "x$ac_cv_func_getaudit_addr" = xyes then : printf "%s\n" "#define HAVE_GETAUDIT_ADDR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "aug_get_machine" "ac_cv_func_aug_get_machine" if test "x$ac_cv_func_aug_get_machine" = xyes then : printf "%s\n" "#define HAVE_AUG_GET_MACHINE 1" >>confdefs.h fi printf "%s\n" "#define USE_BSM_AUDIT 1" >>confdefs.h if test "$sol2ver" -ge 11; then SSHDLIBS="$SSHDLIBS -lscf" printf "%s\n" "#define BROKEN_BSM_API 1" >>confdefs.h fi ;; linux) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: linux" >&5 printf "%s\n" "linux" >&6; } AUDIT_MODULE=linux ac_fn_c_check_header_compile "$LINENO" "libaudit.h" "ac_cv_header_libaudit_h" "$ac_includes_default" if test "x$ac_cv_header_libaudit_h" = xyes then : printf "%s\n" "#define HAVE_LIBAUDIT_H 1" >>confdefs.h fi SSHDLIBS="$SSHDLIBS -laudit" printf "%s\n" "#define USE_LINUX_AUDIT 1" >>confdefs.h ;; debug) AUDIT_MODULE=debug { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: debug" >&5 printf "%s\n" "debug" >&6; } printf "%s\n" "#define SSH_AUDIT_EVENTS 1" >>confdefs.h ;; no) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; *) as_fn_error $? "Unknown audit module $withval" "$LINENO" 5 ;; esac fi # Check whether --with-pie was given. if test ${with_pie+y} 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc >= 4.x" >&5 printf %s "checking for gcc >= 4.x... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if !defined(__GNUC__) || __GNUC__ < 4 #error gcc is too old #endif _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } use_pie=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "x$use_pie" != "xno"; then SAVED_CFLAGS="$CFLAGS" SAVED_LDFLAGS="$LDFLAGS" { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fPIE" >&5 printf %s "checking if $CC supports compile flag -fPIE... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fPIE" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-fPIE" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -pie" >&5 printf %s "checking if $LD supports link flag -pie... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -pie" _define_flag="" test "x$_define_flag" = "x" && _define_flag="-pie" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include /* Trivial function to help test for -fzero-call-used-regs */ int f(int n) {return rand() % n;} char *f2(char *s, ...) { char ret[64]; va_list args; va_start(args, s); vsnprintf(ret, sizeof(ret), s, args); va_end(args); return strdup(ret); } int i; double d; const char *f3(int s) { i = (int)d; return s ? "good" : "gooder"; } int main(int argc, char **argv) { char b[256], *cp; const char *s; /* 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; (void)argv; f(1); s = f3(f(2)); snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, b, 0) == -1) exit(0); cp = f2("%d %d %d %f %f %lld %lld %s\n", i,j,k,l,m,n,o,s); if (write(1, cp, 0) == -1) exit(0); free(cp); /* * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does * not understand comments and we don't use the "fallthrough" attribute * that it's looking for. */ switch(i){ case 0: j += i; /* FALLTHROUGH */ default: j += k; } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 printf "%s\n" "no, fails at run time" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext } # We use both -fPIE and -pie or neither. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether both -fPIE and -pie are supported" >&5 printf %s "checking whether both -fPIE and -pie are supported... " >&6; } if echo "x $CFLAGS" | grep ' -fPIE' >/dev/null 2>&1 && \ echo "x $LDFLAGS" | grep ' -pie' >/dev/null 2>&1 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } CFLAGS="$SAVED_CFLAGS" LDFLAGS="$SAVED_LDFLAGS" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -fPIC is accepted" >&5 printf %s "checking whether -fPIC is accepted... " >&6; } SAVED_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fPIC" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } PICFLAG="-fPIC"; else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } PICFLAG=""; fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CFLAGS="$SAVED_CFLAGS" ac_fn_c_check_func "$LINENO" "auth_hostok" "ac_cv_func_auth_hostok" if test "x$ac_cv_func_auth_hostok" = xyes then : printf "%s\n" "#define HAVE_AUTH_HOSTOK 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "auth_timeok" "ac_cv_func_auth_timeok" if test "x$ac_cv_func_auth_timeok" = xyes then : printf "%s\n" "#define HAVE_AUTH_TIMEOK 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "Blowfish_initstate" "ac_cv_func_Blowfish_initstate" if test "x$ac_cv_func_Blowfish_initstate" = xyes then : printf "%s\n" "#define HAVE_BLOWFISH_INITSTATE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "Blowfish_expandstate" "ac_cv_func_Blowfish_expandstate" if test "x$ac_cv_func_Blowfish_expandstate" = xyes then : printf "%s\n" "#define HAVE_BLOWFISH_EXPANDSTATE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "Blowfish_expand0state" "ac_cv_func_Blowfish_expand0state" if test "x$ac_cv_func_Blowfish_expand0state" = xyes then : printf "%s\n" "#define HAVE_BLOWFISH_EXPAND0STATE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "Blowfish_stream2word" "ac_cv_func_Blowfish_stream2word" if test "x$ac_cv_func_Blowfish_stream2word" = xyes then : printf "%s\n" "#define HAVE_BLOWFISH_STREAM2WORD 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "SHA256Update" "ac_cv_func_SHA256Update" if test "x$ac_cv_func_SHA256Update" = xyes then : printf "%s\n" "#define HAVE_SHA256UPDATE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "SHA384Update" "ac_cv_func_SHA384Update" if test "x$ac_cv_func_SHA384Update" = xyes then : printf "%s\n" "#define HAVE_SHA384UPDATE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "SHA512Update" "ac_cv_func_SHA512Update" if test "x$ac_cv_func_SHA512Update" = xyes then : printf "%s\n" "#define HAVE_SHA512UPDATE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "asprintf" "ac_cv_func_asprintf" if test "x$ac_cv_func_asprintf" = xyes then : printf "%s\n" "#define HAVE_ASPRINTF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "b64_ntop" "ac_cv_func_b64_ntop" if test "x$ac_cv_func_b64_ntop" = xyes then : printf "%s\n" "#define HAVE_B64_NTOP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "__b64_ntop" "ac_cv_func___b64_ntop" if test "x$ac_cv_func___b64_ntop" = xyes then : printf "%s\n" "#define HAVE___B64_NTOP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "b64_pton" "ac_cv_func_b64_pton" if test "x$ac_cv_func_b64_pton" = xyes then : printf "%s\n" "#define HAVE_B64_PTON 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "__b64_pton" "ac_cv_func___b64_pton" if test "x$ac_cv_func___b64_pton" = xyes then : printf "%s\n" "#define HAVE___B64_PTON 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "bcopy" "ac_cv_func_bcopy" if test "x$ac_cv_func_bcopy" = xyes then : printf "%s\n" "#define HAVE_BCOPY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "bcrypt_pbkdf" "ac_cv_func_bcrypt_pbkdf" if test "x$ac_cv_func_bcrypt_pbkdf" = xyes then : printf "%s\n" "#define HAVE_BCRYPT_PBKDF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "bindresvport_sa" "ac_cv_func_bindresvport_sa" if test "x$ac_cv_func_bindresvport_sa" = xyes then : printf "%s\n" "#define HAVE_BINDRESVPORT_SA 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "blf_enc" "ac_cv_func_blf_enc" if test "x$ac_cv_func_blf_enc" = xyes then : printf "%s\n" "#define HAVE_BLF_ENC 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "bzero" "ac_cv_func_bzero" if test "x$ac_cv_func_bzero" = xyes then : printf "%s\n" "#define HAVE_BZERO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "cap_rights_limit" "ac_cv_func_cap_rights_limit" if test "x$ac_cv_func_cap_rights_limit" = xyes then : printf "%s\n" "#define HAVE_CAP_RIGHTS_LIMIT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "clock" "ac_cv_func_clock" if test "x$ac_cv_func_clock" = xyes then : printf "%s\n" "#define HAVE_CLOCK 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "closefrom" "ac_cv_func_closefrom" if test "x$ac_cv_func_closefrom" = xyes then : printf "%s\n" "#define HAVE_CLOSEFROM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "close_range" "ac_cv_func_close_range" if test "x$ac_cv_func_close_range" = xyes then : printf "%s\n" "#define HAVE_CLOSE_RANGE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "dirfd" "ac_cv_func_dirfd" if test "x$ac_cv_func_dirfd" = xyes then : printf "%s\n" "#define HAVE_DIRFD 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "endgrent" "ac_cv_func_endgrent" if test "x$ac_cv_func_endgrent" = xyes then : printf "%s\n" "#define HAVE_ENDGRENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "err" "ac_cv_func_err" if test "x$ac_cv_func_err" = xyes then : printf "%s\n" "#define HAVE_ERR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "errx" "ac_cv_func_errx" if test "x$ac_cv_func_errx" = xyes then : printf "%s\n" "#define HAVE_ERRX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero" if test "x$ac_cv_func_explicit_bzero" = xyes then : printf "%s\n" "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "explicit_memset" "ac_cv_func_explicit_memset" if test "x$ac_cv_func_explicit_memset" = xyes then : printf "%s\n" "#define HAVE_EXPLICIT_MEMSET 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fchmod" "ac_cv_func_fchmod" if test "x$ac_cv_func_fchmod" = xyes then : printf "%s\n" "#define HAVE_FCHMOD 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fchmodat" "ac_cv_func_fchmodat" if test "x$ac_cv_func_fchmodat" = xyes then : printf "%s\n" "#define HAVE_FCHMODAT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fchown" "ac_cv_func_fchown" if test "x$ac_cv_func_fchown" = xyes then : printf "%s\n" "#define HAVE_FCHOWN 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fchownat" "ac_cv_func_fchownat" if test "x$ac_cv_func_fchownat" = xyes then : printf "%s\n" "#define HAVE_FCHOWNAT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "flock" "ac_cv_func_flock" if test "x$ac_cv_func_flock" = xyes then : printf "%s\n" "#define HAVE_FLOCK 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fnmatch" "ac_cv_func_fnmatch" if test "x$ac_cv_func_fnmatch" = xyes then : printf "%s\n" "#define HAVE_FNMATCH 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "freeaddrinfo" "ac_cv_func_freeaddrinfo" if test "x$ac_cv_func_freeaddrinfo" = xyes then : printf "%s\n" "#define HAVE_FREEADDRINFO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "freezero" "ac_cv_func_freezero" if test "x$ac_cv_func_freezero" = xyes then : printf "%s\n" "#define HAVE_FREEZERO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs" if test "x$ac_cv_func_fstatfs" = xyes then : printf "%s\n" "#define HAVE_FSTATFS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fstatvfs" "ac_cv_func_fstatvfs" if test "x$ac_cv_func_fstatvfs" = xyes then : printf "%s\n" "#define HAVE_FSTATVFS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "futimes" "ac_cv_func_futimes" if test "x$ac_cv_func_futimes" = xyes then : printf "%s\n" "#define HAVE_FUTIMES 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo" if test "x$ac_cv_func_getaddrinfo" = xyes then : printf "%s\n" "#define HAVE_GETADDRINFO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd" if test "x$ac_cv_func_getcwd" = xyes then : printf "%s\n" "#define HAVE_GETCWD 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" if test "x$ac_cv_func_getentropy" = xyes then : printf "%s\n" "#define HAVE_GETENTROPY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist" if test "x$ac_cv_func_getgrouplist" = xyes then : printf "%s\n" "#define HAVE_GETGROUPLIST 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline" if test "x$ac_cv_func_getline" = xyes then : printf "%s\n" "#define HAVE_GETLINE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getnameinfo" "ac_cv_func_getnameinfo" if test "x$ac_cv_func_getnameinfo" = xyes then : printf "%s\n" "#define HAVE_GETNAMEINFO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getopt" "ac_cv_func_getopt" if test "x$ac_cv_func_getopt" = xyes then : printf "%s\n" "#define HAVE_GETOPT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" if test "x$ac_cv_func_getpagesize" = xyes then : printf "%s\n" "#define HAVE_GETPAGESIZE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getpeereid" "ac_cv_func_getpeereid" if test "x$ac_cv_func_getpeereid" = xyes then : printf "%s\n" "#define HAVE_GETPEEREID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getpeerucred" "ac_cv_func_getpeerucred" if test "x$ac_cv_func_getpeerucred" = xyes then : printf "%s\n" "#define HAVE_GETPEERUCRED 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getpgid" "ac_cv_func_getpgid" if test "x$ac_cv_func_getpgid" = xyes then : printf "%s\n" "#define HAVE_GETPGID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "_getpty" "ac_cv_func__getpty" if test "x$ac_cv_func__getpty" = xyes then : printf "%s\n" "#define HAVE__GETPTY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getrlimit" "ac_cv_func_getrlimit" if test "x$ac_cv_func_getrlimit" = xyes then : printf "%s\n" "#define HAVE_GETRLIMIT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getrandom" "ac_cv_func_getrandom" if test "x$ac_cv_func_getrandom" = xyes then : printf "%s\n" "#define HAVE_GETRANDOM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getsid" "ac_cv_func_getsid" if test "x$ac_cv_func_getsid" = xyes then : printf "%s\n" "#define HAVE_GETSID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getttyent" "ac_cv_func_getttyent" if test "x$ac_cv_func_getttyent" = xyes then : printf "%s\n" "#define HAVE_GETTTYENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "glob" "ac_cv_func_glob" if test "x$ac_cv_func_glob" = xyes then : printf "%s\n" "#define HAVE_GLOB 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "group_from_gid" "ac_cv_func_group_from_gid" if test "x$ac_cv_func_group_from_gid" = xyes then : printf "%s\n" "#define HAVE_GROUP_FROM_GID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "inet_aton" "ac_cv_func_inet_aton" if test "x$ac_cv_func_inet_aton" = xyes then : printf "%s\n" "#define HAVE_INET_ATON 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "inet_ntoa" "ac_cv_func_inet_ntoa" if test "x$ac_cv_func_inet_ntoa" = xyes then : printf "%s\n" "#define HAVE_INET_NTOA 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" if test "x$ac_cv_func_inet_ntop" = xyes then : printf "%s\n" "#define HAVE_INET_NTOP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "innetgr" "ac_cv_func_innetgr" if test "x$ac_cv_func_innetgr" = xyes then : printf "%s\n" "#define HAVE_INNETGR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "killpg" "ac_cv_func_killpg" if test "x$ac_cv_func_killpg" = xyes then : printf "%s\n" "#define HAVE_KILLPG 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "llabs" "ac_cv_func_llabs" if test "x$ac_cv_func_llabs" = xyes then : printf "%s\n" "#define HAVE_LLABS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" if test "x$ac_cv_func_localtime_r" = xyes then : printf "%s\n" "#define HAVE_LOCALTIME_R 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "login_getcapbool" "ac_cv_func_login_getcapbool" if test "x$ac_cv_func_login_getcapbool" = xyes then : printf "%s\n" "#define HAVE_LOGIN_GETCAPBOOL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "login_getpwclass" "ac_cv_func_login_getpwclass" if test "x$ac_cv_func_login_getpwclass" = xyes then : printf "%s\n" "#define HAVE_LOGIN_GETPWCLASS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "memmem" "ac_cv_func_memmem" if test "x$ac_cv_func_memmem" = xyes then : printf "%s\n" "#define HAVE_MEMMEM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove" if test "x$ac_cv_func_memmove" = xyes then : printf "%s\n" "#define HAVE_MEMMOVE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "memset_s" "ac_cv_func_memset_s" if test "x$ac_cv_func_memset_s" = xyes then : printf "%s\n" "#define HAVE_MEMSET_S 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "mkdtemp" "ac_cv_func_mkdtemp" if test "x$ac_cv_func_mkdtemp" = xyes then : printf "%s\n" "#define HAVE_MKDTEMP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "ngetaddrinfo" "ac_cv_func_ngetaddrinfo" if test "x$ac_cv_func_ngetaddrinfo" = xyes then : printf "%s\n" "#define HAVE_NGETADDRINFO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "nsleep" "ac_cv_func_nsleep" if test "x$ac_cv_func_nsleep" = xyes then : printf "%s\n" "#define HAVE_NSLEEP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "ogetaddrinfo" "ac_cv_func_ogetaddrinfo" if test "x$ac_cv_func_ogetaddrinfo" = xyes then : printf "%s\n" "#define HAVE_OGETADDRINFO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "openlog_r" "ac_cv_func_openlog_r" if test "x$ac_cv_func_openlog_r" = xyes then : printf "%s\n" "#define HAVE_OPENLOG_R 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "pledge" "ac_cv_func_pledge" if test "x$ac_cv_func_pledge" = xyes then : printf "%s\n" "#define HAVE_PLEDGE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll" if test "x$ac_cv_func_poll" = xyes then : printf "%s\n" "#define HAVE_POLL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "ppoll" "ac_cv_func_ppoll" if test "x$ac_cv_func_ppoll" = xyes then : printf "%s\n" "#define HAVE_PPOLL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "prctl" "ac_cv_func_prctl" if test "x$ac_cv_func_prctl" = xyes then : printf "%s\n" "#define HAVE_PRCTL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "procctl" "ac_cv_func_procctl" if test "x$ac_cv_func_procctl" = xyes then : printf "%s\n" "#define HAVE_PROCCTL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "pselect" "ac_cv_func_pselect" if test "x$ac_cv_func_pselect" = xyes then : printf "%s\n" "#define HAVE_PSELECT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "pstat" "ac_cv_func_pstat" if test "x$ac_cv_func_pstat" = xyes then : printf "%s\n" "#define HAVE_PSTAT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "raise" "ac_cv_func_raise" if test "x$ac_cv_func_raise" = xyes then : printf "%s\n" "#define HAVE_RAISE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "readpassphrase" "ac_cv_func_readpassphrase" if test "x$ac_cv_func_readpassphrase" = xyes then : printf "%s\n" "#define HAVE_READPASSPHRASE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray" if test "x$ac_cv_func_reallocarray" = xyes then : printf "%s\n" "#define HAVE_REALLOCARRAY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath" if test "x$ac_cv_func_realpath" = xyes then : printf "%s\n" "#define HAVE_REALPATH 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "recvmsg" "ac_cv_func_recvmsg" if test "x$ac_cv_func_recvmsg" = xyes then : printf "%s\n" "#define HAVE_RECVMSG 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "recallocarray" "ac_cv_func_recallocarray" if test "x$ac_cv_func_recallocarray" = xyes then : printf "%s\n" "#define HAVE_RECALLOCARRAY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "rresvport_af" "ac_cv_func_rresvport_af" if test "x$ac_cv_func_rresvport_af" = xyes then : printf "%s\n" "#define HAVE_RRESVPORT_AF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "sendmsg" "ac_cv_func_sendmsg" if test "x$ac_cv_func_sendmsg" = xyes then : printf "%s\n" "#define HAVE_SENDMSG 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setdtablesize" "ac_cv_func_setdtablesize" if test "x$ac_cv_func_setdtablesize" = xyes then : printf "%s\n" "#define HAVE_SETDTABLESIZE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setegid" "ac_cv_func_setegid" if test "x$ac_cv_func_setegid" = xyes then : printf "%s\n" "#define HAVE_SETEGID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv" if test "x$ac_cv_func_setenv" = xyes then : printf "%s\n" "#define HAVE_SETENV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "seteuid" "ac_cv_func_seteuid" if test "x$ac_cv_func_seteuid" = xyes then : printf "%s\n" "#define HAVE_SETEUID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setgroupent" "ac_cv_func_setgroupent" if test "x$ac_cv_func_setgroupent" = xyes then : printf "%s\n" "#define HAVE_SETGROUPENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setgroups" "ac_cv_func_setgroups" if test "x$ac_cv_func_setgroups" = xyes then : printf "%s\n" "#define HAVE_SETGROUPS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setlinebuf" "ac_cv_func_setlinebuf" if test "x$ac_cv_func_setlinebuf" = xyes then : printf "%s\n" "#define HAVE_SETLINEBUF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setlogin" "ac_cv_func_setlogin" if test "x$ac_cv_func_setlogin" = xyes then : printf "%s\n" "#define HAVE_SETLOGIN 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setpassent" "ac_cv_func_setpassent" if test "x$ac_cv_func_setpassent" = xyes then : printf "%s\n" "#define HAVE_SETPASSENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setpcred" "ac_cv_func_setpcred" if test "x$ac_cv_func_setpcred" = xyes then : printf "%s\n" "#define HAVE_SETPCRED 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setproctitle" "ac_cv_func_setproctitle" if test "x$ac_cv_func_setproctitle" = xyes then : printf "%s\n" "#define HAVE_SETPROCTITLE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setregid" "ac_cv_func_setregid" if test "x$ac_cv_func_setregid" = xyes then : printf "%s\n" "#define HAVE_SETREGID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setreuid" "ac_cv_func_setreuid" if test "x$ac_cv_func_setreuid" = xyes then : printf "%s\n" "#define HAVE_SETREUID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setrlimit" "ac_cv_func_setrlimit" if test "x$ac_cv_func_setrlimit" = xyes then : printf "%s\n" "#define HAVE_SETRLIMIT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setsid" "ac_cv_func_setsid" if test "x$ac_cv_func_setsid" = xyes then : printf "%s\n" "#define HAVE_SETSID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setvbuf" "ac_cv_func_setvbuf" if test "x$ac_cv_func_setvbuf" = xyes then : printf "%s\n" "#define HAVE_SETVBUF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" if test "x$ac_cv_func_sigaction" = xyes then : printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "sigvec" "ac_cv_func_sigvec" if test "x$ac_cv_func_sigvec" = xyes then : printf "%s\n" "#define HAVE_SIGVEC 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" if test "x$ac_cv_func_snprintf" = xyes then : printf "%s\n" "#define HAVE_SNPRINTF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "socketpair" "ac_cv_func_socketpair" if test "x$ac_cv_func_socketpair" = xyes then : printf "%s\n" "#define HAVE_SOCKETPAIR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "statfs" "ac_cv_func_statfs" if test "x$ac_cv_func_statfs" = xyes then : printf "%s\n" "#define HAVE_STATFS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "statvfs" "ac_cv_func_statvfs" if test "x$ac_cv_func_statvfs" = xyes then : printf "%s\n" "#define HAVE_STATVFS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strcasestr" "ac_cv_func_strcasestr" if test "x$ac_cv_func_strcasestr" = xyes then : printf "%s\n" "#define HAVE_STRCASESTR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" if test "x$ac_cv_func_strdup" = xyes then : printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" if test "x$ac_cv_func_strerror" = xyes then : printf "%s\n" "#define HAVE_STRERROR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat" if test "x$ac_cv_func_strlcat" = xyes then : printf "%s\n" "#define HAVE_STRLCAT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" if test "x$ac_cv_func_strlcpy" = xyes then : printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strmode" "ac_cv_func_strmode" if test "x$ac_cv_func_strmode" = xyes then : printf "%s\n" "#define HAVE_STRMODE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup" if test "x$ac_cv_func_strndup" = xyes then : printf "%s\n" "#define HAVE_STRNDUP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strnlen" "ac_cv_func_strnlen" if test "x$ac_cv_func_strnlen" = xyes then : printf "%s\n" "#define HAVE_STRNLEN 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strnvis" "ac_cv_func_strnvis" if test "x$ac_cv_func_strnvis" = xyes then : printf "%s\n" "#define HAVE_STRNVIS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strptime" "ac_cv_func_strptime" if test "x$ac_cv_func_strptime" = xyes then : printf "%s\n" "#define HAVE_STRPTIME 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strsignal" "ac_cv_func_strsignal" if test "x$ac_cv_func_strsignal" = xyes then : printf "%s\n" "#define HAVE_STRSIGNAL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strtonum" "ac_cv_func_strtonum" if test "x$ac_cv_func_strtonum" = xyes then : printf "%s\n" "#define HAVE_STRTONUM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strtoll" "ac_cv_func_strtoll" if test "x$ac_cv_func_strtoll" = xyes then : printf "%s\n" "#define HAVE_STRTOLL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strtoul" "ac_cv_func_strtoul" if test "x$ac_cv_func_strtoul" = xyes then : printf "%s\n" "#define HAVE_STRTOUL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strtoull" "ac_cv_func_strtoull" if test "x$ac_cv_func_strtoull" = xyes then : printf "%s\n" "#define HAVE_STRTOULL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "sysconf" "ac_cv_func_sysconf" if test "x$ac_cv_func_sysconf" = xyes then : printf "%s\n" "#define HAVE_SYSCONF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "tcgetpgrp" "ac_cv_func_tcgetpgrp" if test "x$ac_cv_func_tcgetpgrp" = xyes then : printf "%s\n" "#define HAVE_TCGETPGRP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "timegm" "ac_cv_func_timegm" if test "x$ac_cv_func_timegm" = xyes then : printf "%s\n" "#define HAVE_TIMEGM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp" if test "x$ac_cv_func_timingsafe_bcmp" = xyes then : printf "%s\n" "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "truncate" "ac_cv_func_truncate" if test "x$ac_cv_func_truncate" = xyes then : printf "%s\n" "#define HAVE_TRUNCATE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" if test "x$ac_cv_func_unsetenv" = xyes then : printf "%s\n" "#define HAVE_UNSETENV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "updwtmpx" "ac_cv_func_updwtmpx" if test "x$ac_cv_func_updwtmpx" = xyes then : printf "%s\n" "#define HAVE_UPDWTMPX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat" if test "x$ac_cv_func_utimensat" = xyes then : printf "%s\n" "#define HAVE_UTIMENSAT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "user_from_uid" "ac_cv_func_user_from_uid" if test "x$ac_cv_func_user_from_uid" = xyes then : printf "%s\n" "#define HAVE_USER_FROM_UID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep" if test "x$ac_cv_func_usleep" = xyes then : printf "%s\n" "#define HAVE_USLEEP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf" if test "x$ac_cv_func_vasprintf" = xyes then : printf "%s\n" "#define HAVE_VASPRINTF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" if test "x$ac_cv_func_vsnprintf" = xyes then : printf "%s\n" "#define HAVE_VSNPRINTF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid" if test "x$ac_cv_func_waitpid" = xyes then : printf "%s\n" "#define HAVE_WAITPID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "warn" "ac_cv_func_warn" if test "x$ac_cv_func_warn" = xyes then : printf "%s\n" "#define HAVE_WARN 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compiler supports __builtin_popcount" >&5 printf %s "checking whether compiler supports __builtin_popcount... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int x = 123, y; y = __builtin_popcount(123); exit(y == 6 ? 0 : -1); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define MISSING_BUILTIN_POPCOUNT 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_fn_check_decl "$LINENO" "bzero" "ac_cv_have_decl_bzero" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_bzero" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_BZERO $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "memmem" "ac_cv_have_decl_memmem" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_memmem" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_MEMMEM $ac_have_decl" >>confdefs.h ac_fn_c_check_func "$LINENO" "mblen" "ac_cv_func_mblen" if test "x$ac_cv_func_mblen" = xyes then : printf "%s\n" "#define HAVE_MBLEN 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "mbtowc" "ac_cv_func_mbtowc" if test "x$ac_cv_func_mbtowc" = xyes then : printf "%s\n" "#define HAVE_MBTOWC 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "nl_langinfo" "ac_cv_func_nl_langinfo" if test "x$ac_cv_func_nl_langinfo" = xyes then : printf "%s\n" "#define HAVE_NL_LANGINFO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "wcwidth" "ac_cv_func_wcwidth" if test "x$ac_cv_func_wcwidth" = xyes then : printf "%s\n" "#define HAVE_WCWIDTH 1" >>confdefs.h fi TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for utf8 locale support" >&5 printf %s "checking for utf8 locale support... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { char *loc = setlocale(LC_CTYPE, "en_US.UTF-8"); if (loc != NULL) exit(0); exit(1); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } TEST_SSH_UTF8=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { return (isblank('a')); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define HAVE_ISBLANK 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext disable_pkcs11= # Check whether --enable-pkcs11 was given. if test ${enable_pkcs11+y} then : enableval=$enable_pkcs11; if test "x$enableval" = "xno" ; then disable_pkcs11=1 fi fi disable_sk= # Check whether --enable-security-key was given. if test ${enable_security_key+y} then : enableval=$enable_security_key; if test "x$enableval" = "xno" ; then disable_sk=1 fi fi enable_sk_internal= # Check whether --with-security-key-builtin was given. if test ${with_security_key_builtin+y} then : withval=$with_security_key_builtin; enable_sk_internal=$withval fi enable_sk_standalone= # Check whether --with-security-key-standalone was given. if test ${with_security_key_standalone+y} then : withval=$with_security_key_standalone; enable_sk_standalone=$withval fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 printf %s "checking for library containing dlopen... " >&6; } if test ${ac_cv_search_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_dlopen+y} then : break fi done if test ${ac_cv_search_dlopen+y} then : else $as_nop ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 printf "%s\n" "$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" fi ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes then : printf "%s\n" "#define HAVE_DLOPEN 1" >>confdefs.h fi ac_fn_check_decl "$LINENO" "RTLD_NOW" "ac_cv_have_decl_RTLD_NOW" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_RTLD_NOW" = xyes then : fi # IRIX has a const char return value for gai_strerror() for ac_func in gai_strerror do : ac_fn_c_check_func "$LINENO" "gai_strerror" "ac_cv_func_gai_strerror" if test "x$ac_cv_func_gai_strerror" = xyes then : printf "%s\n" "#define HAVE_GAI_STRERROR 1" >>confdefs.h printf "%s\n" "#define HAVE_GAI_STRERROR 1" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include const char *gai_strerror(int); int main (void) { char *str; str = gai_strerror(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_CONST_GAI_STRERROR_PROTO 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep" >&5 printf %s "checking for library containing nanosleep... " >&6; } if test ${ac_cv_search_nanosleep+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char nanosleep (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_nanosleep=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_nanosleep+y} then : break fi done if test ${ac_cv_search_nanosleep+y} then : else $as_nop ac_cv_search_nanosleep=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep" >&5 printf "%s\n" "$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" printf "%s\n" "#define HAVE_NANOSLEEP 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 printf %s "checking for library containing clock_gettime... " >&6; } if test ${ac_cv_search_clock_gettime+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char clock_gettime (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_clock_gettime+y} then : break fi done if test ${ac_cv_search_clock_gettime+y} then : else $as_nop ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 printf "%s\n" "$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" printf "%s\n" "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h fi ac_fn_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" " #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_localtime_r" = xyes then : else $as_nop saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -D_REENTRANT" unset ac_cv_have_decl_localtime_r ac_fn_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" " #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_localtime_r" = xyes then : else $as_nop CPPFLAGS="$saved_CPPFLAGS" fi fi ac_fn_check_decl "$LINENO" "strsep" "ac_cv_have_decl_strsep" " #ifdef HAVE_STRING_H # include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_strsep" = xyes then : ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep" if test "x$ac_cv_func_strsep" = xyes then : printf "%s\n" "#define HAVE_STRSEP 1" >>confdefs.h fi fi ac_fn_check_decl "$LINENO" "tcsendbreak" "ac_cv_have_decl_tcsendbreak" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_tcsendbreak" = xyes then : printf "%s\n" "#define HAVE_TCSENDBREAK 1" >>confdefs.h else $as_nop ac_fn_c_check_func "$LINENO" "tcsendbreak" "ac_cv_func_tcsendbreak" if test "x$ac_cv_func_tcsendbreak" = xyes then : printf "%s\n" "#define HAVE_TCSENDBREAK 1" >>confdefs.h fi fi ac_fn_check_decl "$LINENO" "h_errno" "ac_cv_have_decl_h_errno" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_h_errno" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_H_ERRNO $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "SHUT_RD" "ac_cv_have_decl_SHUT_RD" " #include #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_SHUT_RD" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_SHUT_RD $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "getpeereid" "ac_cv_have_decl_getpeereid" " #include #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_getpeereid" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_GETPEEREID $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "O_NONBLOCK" "ac_cv_have_decl_O_NONBLOCK" " #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_FCNTL_H # include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_O_NONBLOCK" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_O_NONBLOCK $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "ftruncate" "ac_cv_have_decl_ftruncate" " #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_ftruncate" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_FTRUNCATE $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "getentropy" "ac_cv_have_decl_getentropy" " #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_getentropy" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_GETENTROPY $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "readv" "ac_cv_have_decl_readv" " #include #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_readv" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_READV $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "writev" "ac_cv_have_decl_writev" " #include #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_writev" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_WRITEV $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "MAXSYMLINKS" "ac_cv_have_decl_MAXSYMLINKS" " #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_MAXSYMLINKS" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_MAXSYMLINKS $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "offsetof" "ac_cv_have_decl_offsetof" " #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_offsetof" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_OFFSETOF $ac_have_decl" >>confdefs.h # extra bits for select(2) ac_fn_check_decl "$LINENO" "howmany" "ac_cv_have_decl_howmany" " #include #include #ifdef HAVE_SYS_SYSMACROS_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_howmany" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_HOWMANY $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "NFDBITS" "ac_cv_have_decl_NFDBITS" " #include #include #ifdef HAVE_SYS_SYSMACROS_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_NFDBITS" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_NFDBITS $ac_have_decl" >>confdefs.h ac_fn_c_check_type "$LINENO" "fd_mask" "ac_cv_type_fd_mask" " #include #include #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif " if test "x$ac_cv_type_fd_mask" = xyes then : printf "%s\n" "#define HAVE_FD_MASK 1" >>confdefs.h fi for ac_func in setresuid do : ac_fn_c_check_func "$LINENO" "setresuid" "ac_cv_func_setresuid" if test "x$ac_cv_func_setresuid" = xyes then : printf "%s\n" "#define HAVE_SETRESUID 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setresuid seems to work" >&5 printf %s "checking if setresuid seems to work... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking setresuid" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { errno=0; setresuid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop printf "%s\n" "#define BROKEN_SETRESUID 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5 printf "%s\n" "not implemented" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi done for ac_func in setresgid do : ac_fn_c_check_func "$LINENO" "setresgid" "ac_cv_func_setresgid" if test "x$ac_cv_func_setresgid" = xyes then : printf "%s\n" "#define HAVE_SETRESGID 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setresgid seems to work" >&5 printf %s "checking if setresgid seems to work... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking setresuid" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { errno=0; setresgid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop printf "%s\n" "#define BROKEN_SETRESGID 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5 printf "%s\n" "not implemented" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working fflush(NULL)" >&5 printf %s "checking for working fflush(NULL)... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming working" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { fflush(NULL); exit(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define FFLUSH_NULL_BUG 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" if test "x$ac_cv_func_gettimeofday" = xyes then : printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "time" "ac_cv_func_time" if test "x$ac_cv_func_time" = xyes then : printf "%s\n" "#define HAVE_TIME 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "endutent" "ac_cv_func_endutent" if test "x$ac_cv_func_endutent" = xyes then : printf "%s\n" "#define HAVE_ENDUTENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getutent" "ac_cv_func_getutent" if test "x$ac_cv_func_getutent" = xyes then : printf "%s\n" "#define HAVE_GETUTENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getutid" "ac_cv_func_getutid" if test "x$ac_cv_func_getutid" = xyes then : printf "%s\n" "#define HAVE_GETUTID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getutline" "ac_cv_func_getutline" if test "x$ac_cv_func_getutline" = xyes then : printf "%s\n" "#define HAVE_GETUTLINE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "pututline" "ac_cv_func_pututline" if test "x$ac_cv_func_pututline" = xyes then : printf "%s\n" "#define HAVE_PUTUTLINE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setutent" "ac_cv_func_setutent" if test "x$ac_cv_func_setutent" = xyes then : printf "%s\n" "#define HAVE_SETUTENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "utmpname" "ac_cv_func_utmpname" if test "x$ac_cv_func_utmpname" = xyes then : printf "%s\n" "#define HAVE_UTMPNAME 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "endutxent" "ac_cv_func_endutxent" if test "x$ac_cv_func_endutxent" = xyes then : printf "%s\n" "#define HAVE_ENDUTXENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getutxent" "ac_cv_func_getutxent" if test "x$ac_cv_func_getutxent" = xyes then : printf "%s\n" "#define HAVE_GETUTXENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getutxid" "ac_cv_func_getutxid" if test "x$ac_cv_func_getutxid" = xyes then : printf "%s\n" "#define HAVE_GETUTXID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getutxline" "ac_cv_func_getutxline" if test "x$ac_cv_func_getutxline" = xyes then : printf "%s\n" "#define HAVE_GETUTXLINE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getutxuser" "ac_cv_func_getutxuser" if test "x$ac_cv_func_getutxuser" = xyes then : printf "%s\n" "#define HAVE_GETUTXUSER 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "pututxline" "ac_cv_func_pututxline" if test "x$ac_cv_func_pututxline" = xyes then : printf "%s\n" "#define HAVE_PUTUTXLINE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setutxdb" "ac_cv_func_setutxdb" if test "x$ac_cv_func_setutxdb" = xyes then : printf "%s\n" "#define HAVE_SETUTXDB 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setutxent" "ac_cv_func_setutxent" if test "x$ac_cv_func_setutxent" = xyes then : printf "%s\n" "#define HAVE_SETUTXENT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "utmpxname" "ac_cv_func_utmpxname" if test "x$ac_cv_func_utmpxname" = xyes then : printf "%s\n" "#define HAVE_UTMPXNAME 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getlastlogxbyname" "ac_cv_func_getlastlogxbyname" if test "x$ac_cv_func_getlastlogxbyname" = xyes then : printf "%s\n" "#define HAVE_GETLASTLOGXBYNAME 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "daemon" "ac_cv_func_daemon" if test "x$ac_cv_func_daemon" = xyes then : printf "%s\n" "#define HAVE_DAEMON 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for daemon in -lbsd" >&5 printf %s "checking for daemon in -lbsd... " >&6; } if test ${ac_cv_lib_bsd_daemon+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char daemon (); int main (void) { return daemon (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_bsd_daemon=yes else $as_nop ac_cv_lib_bsd_daemon=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_daemon" >&5 printf "%s\n" "$ac_cv_lib_bsd_daemon" >&6; } if test "x$ac_cv_lib_bsd_daemon" = xyes then : LIBS="$LIBS -lbsd"; printf "%s\n" "#define HAVE_DAEMON 1" >>confdefs.h fi fi ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" if test "x$ac_cv_func_getpagesize" = xyes then : printf "%s\n" "#define HAVE_GETPAGESIZE 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getpagesize in -lucb" >&5 printf %s "checking for getpagesize in -lucb... " >&6; } if test ${ac_cv_lib_ucb_getpagesize+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lucb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char getpagesize (); int main (void) { return getpagesize (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_ucb_getpagesize=yes else $as_nop ac_cv_lib_ucb_getpagesize=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ucb_getpagesize" >&5 printf "%s\n" "$ac_cv_lib_ucb_getpagesize" >&6; } if test "x$ac_cv_lib_ucb_getpagesize" = xyes then : LIBS="$LIBS -lucb"; printf "%s\n" "#define HAVE_GETPAGESIZE 1" >>confdefs.h fi fi # Check for broken snprintf if test "x$ac_cv_func_snprintf" = "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether snprintf correctly terminates long strings" >&5 printf %s "checking whether snprintf correctly terminates long strings... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { char b[5]; snprintf(b,5,"123456789"); exit(b[4]!='\0'); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&5 printf "%s\n" "$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.beam conftest.$ac_ext fi fi if test "x$ac_cv_func_snprintf" = "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether snprintf understands %zu" >&5 printf %s "checking whether snprintf understands %zu... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main (void) { size_t a = 1, b = 2; char z[128]; snprintf(z, sizeof z, "%zu%zu", a, b); exit(strcmp(z, "12")); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5 printf %s "checking whether vsnprintf returns correct values on overflow... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working vsnprintf()" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working vsnprintf()" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int x_snprintf(char *str, size_t count, const char *fmt, ...) { size_t ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); return ret; } int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&5 printf "%s\n" "$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.beam 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether snprintf can declare const char *fmt" >&5 printf %s "checking whether snprintf can declare const char *fmt... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int snprintf(char *a, size_t b, const char *c, ...) { return 0; } int main (void) { snprintf(0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define SNPRINTF_CONST const" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define SNPRINTF_CONST /* not const */" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether system supports SO_PEERCRED getsockopt" >&5 printf %s "checking whether system supports SO_PEERCRED getsockopt... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { int i = SO_PEERCRED; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_SO_PEERCRED 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } NO_PEERCHECK=1 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test ! -z "$check_for_openpty_ctty_bug"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if openpty correctly handles controlling tty" >&5 printf %s "checking if openpty correctly handles controlling tty... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5 printf "%s\n" "cross-compiling, assuming yes" >&6; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #ifdef HAVE_PTY_H # include #endif #include #include #include int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5 printf %s "checking if getaddrinfo seems to work... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5 printf "%s\n" "cross-compiling, assuming yes" >&6; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include #define TEST_PORT "2222" int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_aix_broken_getaddrinfo" = "x1"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5 printf %s "checking if getaddrinfo seems to work... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming no" >&5 printf "%s\n" "cross-compiling, assuming no" >&6; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include #define TEST_PORT "2222" int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define AIX_GETNAMEINFO_HACK 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test "x$ac_cv_func_getaddrinfo" = "xyes"; then ac_fn_check_decl "$LINENO" "AI_NUMERICSERV" "ac_cv_have_decl_AI_NUMERICSERV" "#include #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_AI_NUMERICSERV" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_AI_NUMERICSERV $ac_have_decl" >>confdefs.h fi if test "x$check_for_conflicting_getspnam" = "x1"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for conflicting getspnam in shadow.h" >&5 printf %s "checking for conflicting getspnam in shadow.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define GETSPNAM_CONFLICTING_DEFS 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "x$ac_cv_func_strnvis" = "xyes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working strnvis" >&5 printf %s "checking for working strnvis... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming broken" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming broken" >&2;} printf "%s\n" "#define BROKEN_STRNVIS 1" >>confdefs.h else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include static void sighandler(int sig) { _exit(1); } int main (void) { char dst[16]; signal(SIGSEGV, sighandler); if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0) exit(0); exit(1) ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define BROKEN_STRNVIS 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if SA_RESTARTed signals interrupt select()" >&5 printf %s "checking if SA_RESTARTed signals interrupt select()... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_SELECT # include #endif #include #include #include #include #include static void sighandler(int sig) { } int main (void) { 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); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define NO_SA_RESTART 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi for ac_func in getpgrp do : ac_fn_c_check_func "$LINENO" "getpgrp" "ac_cv_func_getpgrp" if test "x$ac_cv_func_getpgrp" = xyes then : printf "%s\n" "#define HAVE_GETPGRP 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getpgrp accepts zero args" >&5 printf %s "checking if getpgrp accepts zero args... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { getpgrp(); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define GETPGRP_VOID 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define GETPGRP_VOID 0" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi done # Search for OpenSSL saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" openssl_bin_PATH="$PATH" # Check whether --with-ssl-dir was given. if test ${with_ssl_dir+y} then : withval=$with_ssl_dir; if test "x$openssl" = "xno" ; then as_fn_error $? "cannot use --with-ssl-dir when OpenSSL disabled" "$LINENO" 5 fi if test "x$withval" != "xno" ; then case "$withval" in # Relative paths ./*|../*) withval="`pwd`/$withval" esac if test -d "$withval/lib"; then libcrypto_path="${withval}/lib" elif test -d "$withval/lib64"; then libcrypto_path="$withval/lib64" else # Built but not installed libcrypto_path="${withval}" fi if test -n "${rpath_opt}"; then LDFLAGS="-L${libcrypto_path} ${rpath_opt}${libcrypto_path} ${LDFLAGS}" else LDFLAGS="-L${libcrypto_path} ${LDFLAGS}" fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi if test -x "${withval}/bin/openssl" && \ "${withval}/bin/openssl" version >/dev/null 2>&1; then openssl_bin_PATH="${withval}/bin${PATH_SEPARATOR}${PATH}" elif test -x "${withval}/apps/openssl" && \ "${withval}/apps/openssl" version >/dev/null 2>&1; then openssl_bin_PATH="${withval}/apps${PATH_SEPARATOR}${PATH}" fi fi fi for ac_prog in openssl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_openssl_bin+y} then : printf %s "(cached) " >&6 else $as_nop case $openssl_bin in [\\/]* | ?:[\\/]*) ac_cv_path_openssl_bin="$openssl_bin" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $openssl_bin_PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_openssl_bin="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi openssl_bin=$ac_cv_path_openssl_bin if test -n "$openssl_bin"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $openssl_bin" >&5 printf "%s\n" "$openssl_bin" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$openssl_bin" && break done OPENSSL_BIN=${openssl_bin} # Check whether --with-openssl-header-check was given. if test ${with_openssl_header_check+y} 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+y} then : withval=$with_ssl_engine; if test "x$withval" != "xno" ; then if test "x$openssl" = "xno" ; then as_fn_error $? "cannot use --with-ssl-engine when OpenSSL disabled" "$LINENO" 5 fi openssl_engine=yes fi fi nocrypto_saved_LIBS="$LIBS" if test "x$openssl" = "xyes" ; then LIBS="-lcrypto $LIBS" CHANNELLIBS="-lcrypto $CHANNELLIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char RAND_add (); int main (void) { return RAND_add (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : else $as_nop as_fn_error $? "*** working libcrypto not found, check config.log" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_fn_c_check_header_compile "$LINENO" "openssl/opensslv.h" "ac_cv_header_openssl_opensslv_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_opensslv_h" = xyes then : else $as_nop as_fn_error $? "*** OpenSSL headers missing - please install first or check config.log ***" "$LINENO" 5 fi # Determine OpenSSL header version { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OpenSSL header version" >&5 printf %s "checking OpenSSL header version... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #define DATA "conftest.sslincver" int main (void) { FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); if ((rc = fprintf(fd, "%08lx (%s)\n", (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) < 0) exit(1); exit(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ssl_header_ver=`cat conftest.sslincver` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ssl_header_ver" >&5 printf "%s\n" "$ssl_header_ver" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5 printf "%s\n" "failed" >&6; } as_fn_error $? "OpenSSL version test program failed." "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi # Determining OpenSSL library version is version dependent. ac_fn_c_check_func "$LINENO" "OpenSSL_version" "ac_cv_func_OpenSSL_version" if test "x$ac_cv_func_OpenSSL_version" = xyes then : printf "%s\n" "#define HAVE_OPENSSL_VERSION 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "OpenSSL_version_num" "ac_cv_func_OpenSSL_version_num" if test "x$ac_cv_func_OpenSSL_version_num" = xyes then : printf "%s\n" "#define HAVE_OPENSSL_VERSION_NUM 1" >>confdefs.h fi # Determine OpenSSL library version { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OpenSSL library version" >&5 printf %s "checking OpenSSL library version... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #define DATA "conftest.ssllibver" int main (void) { FILE *f; /* We need these legacy bits to warn for old libcrypto */ #ifndef OPENSSL_VERSION # define OPENSSL_VERSION SSLEAY_VERSION #endif #ifndef HAVE_OPENSSL_VERSION # define OpenSSL_version SSLeay_version #endif #ifndef HAVE_OPENSSL_VERSION_NUM # define OpenSSL_version_num SSLeay #endif if ((f = fopen(DATA, "w")) == NULL) exit(1); if (fprintf(f, "%08lx (%s)", (unsigned long)OpenSSL_version_num(), OpenSSL_version(OPENSSL_VERSION)) < 0) exit(1); #ifdef LIBRESSL_VERSION_NUMBER if (fprintf(f, " libressl-%08lx", LIBRESSL_VERSION_NUMBER) < 0) exit(1); #endif if (fputc('\n', f) == EOF || fclose(f) == EOF) exit(1); exit(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : sslver=`cat conftest.ssllibver` ssl_showver=`echo "$sslver" | sed 's/ libressl-.*//'` # Check version is supported. case "$sslver" in 100*|10100*) # 1.0.x, 1.1.0x as_fn_error $? "OpenSSL >= 1.1.1 required (have \"$ssl_showver\")" "$LINENO" 5 ;; 101*) ;; # 1.1.x 200*) # LibreSSL lver=`echo "$sslver" | sed 's/.*libressl-//'` case "$lver" in 2*|300*) # 2.x, 3.0.0 as_fn_error $? "LibreSSL >= 3.1.0 required (have \"$ssl_showver\")" "$LINENO" 5 ;; *) ;; # Assume all other versions are good. esac ;; 30*) # OpenSSL 3; we use the 1.1x API # https://openssl.org/policies/general/versioning-policy.html CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" ;; *) as_fn_error $? "Unknown/unsupported OpenSSL version (\"$ssl_showver\")" "$LINENO" 5 ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ssl_showver" >&5 printf "%s\n" "$ssl_showver" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 printf "%s\n" "not found" >&6; } as_fn_error $? "OpenSSL library not found." "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi case "$host" in x86_64-*) case "$sslver" in 3000004*) as_fn_error $? "OpenSSL 3.0.4 has a potential RCE in its RSA implementation (CVE-2022-2274)" "$LINENO" 5 ;; esac esac # Sanity check OpenSSL headers { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's headers match the library" >&5 printf %s "checking whether OpenSSL's headers match the library... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main (void) { exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if test "x$openssl_check_nonfatal" = "x"; then as_fn_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. " "$LINENO" 5 else { printf "%s\n" "$as_me:${as_lineno-$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 printf "%s\n" "$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.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL functions will link" >&5 printf %s "checking if programs using OpenSSL functions will link... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { ERR_load_crypto_strings(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LIBS="$LIBS -ldl" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL need -ldl" >&5 printf %s "checking if programs using OpenSSL need -ldl... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { ERR_load_crypto_strings(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CHANNELLIBS="$CHANNELLIBS -ldl" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_fn_c_check_func "$LINENO" "BN_is_prime_ex" "ac_cv_func_BN_is_prime_ex" if test "x$ac_cv_func_BN_is_prime_ex" = xyes then : printf "%s\n" "#define HAVE_BN_IS_PRIME_EX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "DES_crypt" "ac_cv_func_DES_crypt" if test "x$ac_cv_func_DES_crypt" = xyes then : printf "%s\n" "#define HAVE_DES_CRYPT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "DSA_generate_parameters_ex" "ac_cv_func_DSA_generate_parameters_ex" if test "x$ac_cv_func_DSA_generate_parameters_ex" = xyes then : printf "%s\n" "#define HAVE_DSA_GENERATE_PARAMETERS_EX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_DigestSign" "ac_cv_func_EVP_DigestSign" if test "x$ac_cv_func_EVP_DigestSign" = xyes then : printf "%s\n" "#define HAVE_EVP_DIGESTSIGN 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_DigestVerify" "ac_cv_func_EVP_DigestVerify" if test "x$ac_cv_func_EVP_DigestVerify" = xyes then : printf "%s\n" "#define HAVE_EVP_DIGESTVERIFY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_DigestFinal_ex" "ac_cv_func_EVP_DigestFinal_ex" if test "x$ac_cv_func_EVP_DigestFinal_ex" = xyes then : printf "%s\n" "#define HAVE_EVP_DIGESTFINAL_EX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_DigestInit_ex" "ac_cv_func_EVP_DigestInit_ex" if test "x$ac_cv_func_EVP_DigestInit_ex" = xyes then : printf "%s\n" "#define HAVE_EVP_DIGESTINIT_EX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_MD_CTX_cleanup" "ac_cv_func_EVP_MD_CTX_cleanup" if test "x$ac_cv_func_EVP_MD_CTX_cleanup" = xyes then : printf "%s\n" "#define HAVE_EVP_MD_CTX_CLEANUP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_MD_CTX_copy_ex" "ac_cv_func_EVP_MD_CTX_copy_ex" if test "x$ac_cv_func_EVP_MD_CTX_copy_ex" = xyes then : printf "%s\n" "#define HAVE_EVP_MD_CTX_COPY_EX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_MD_CTX_init" "ac_cv_func_EVP_MD_CTX_init" if test "x$ac_cv_func_EVP_MD_CTX_init" = xyes then : printf "%s\n" "#define HAVE_EVP_MD_CTX_INIT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "HMAC_CTX_init" "ac_cv_func_HMAC_CTX_init" if test "x$ac_cv_func_HMAC_CTX_init" = xyes then : printf "%s\n" "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "RSA_generate_key_ex" "ac_cv_func_RSA_generate_key_ex" if test "x$ac_cv_func_RSA_generate_key_ex" = xyes then : printf "%s\n" "#define HAVE_RSA_GENERATE_KEY_EX 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "RSA_get_default_method" "ac_cv_func_RSA_get_default_method" if test "x$ac_cv_func_RSA_get_default_method" = xyes then : printf "%s\n" "#define HAVE_RSA_GET_DEFAULT_METHOD 1" >>confdefs.h fi # OpenSSL_add_all_algorithms may be a macro. ac_fn_c_check_func "$LINENO" "OpenSSL_add_all_algorithms" "ac_cv_func_OpenSSL_add_all_algorithms" if test "x$ac_cv_func_OpenSSL_add_all_algorithms" = xyes then : printf "%s\n" "#define HAVE_OPENSSL_ADD_ALL_ALGORITHMS 1" >>confdefs.h else $as_nop ac_fn_check_decl "$LINENO" "OpenSSL_add_all_algorithms" "ac_cv_have_decl_OpenSSL_add_all_algorithms" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_OpenSSL_add_all_algorithms" = xyes then : printf "%s\n" "#define HAVE_OPENSSL_ADD_ALL_ALGORITHMS 1" >>confdefs.h fi fi # LibreSSL/OpenSSL API differences ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_iv" "ac_cv_func_EVP_CIPHER_CTX_iv" if test "x$ac_cv_func_EVP_CIPHER_CTX_iv" = xyes then : printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_IV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_iv_noconst" "ac_cv_func_EVP_CIPHER_CTX_iv_noconst" if test "x$ac_cv_func_EVP_CIPHER_CTX_iv_noconst" = xyes then : printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_IV_NOCONST 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_get_iv" "ac_cv_func_EVP_CIPHER_CTX_get_iv" if test "x$ac_cv_func_EVP_CIPHER_CTX_get_iv" = xyes then : printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_GET_IV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_get_updated_iv" "ac_cv_func_EVP_CIPHER_CTX_get_updated_iv" if test "x$ac_cv_func_EVP_CIPHER_CTX_get_updated_iv" = xyes then : printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_set_iv" "ac_cv_func_EVP_CIPHER_CTX_set_iv" if test "x$ac_cv_func_EVP_CIPHER_CTX_set_iv" = xyes then : printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_SET_IV 1" >>confdefs.h fi if test "x$openssl_engine" = "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenSSL ENGINE support" >&5 printf %s "checking for OpenSSL ENGINE support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define USE_OPENSSL_ENGINE 1" >>confdefs.h else $as_nop as_fn_error $? "OpenSSL ENGINE support not found" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi # Check for OpenSSL without EVP_aes_{192,256}_cbc { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL lacks support for AES 192/256" >&5 printf %s "checking whether OpenSSL lacks support for AES 192/256... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define OPENSSL_LOBOTOMISED_AES 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if EVP_DigestUpdate returns an int" >&5 printf %s "checking if EVP_DigestUpdate returns an int... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { if(EVP_DigestUpdate(NULL, NULL,0)) exit(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define OPENSSL_EVP_DIGESTUPDATE_VOID 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext # Check for various EVP support in OpenSSL ac_fn_c_check_func "$LINENO" "EVP_sha256" "ac_cv_func_EVP_sha256" if test "x$ac_cv_func_EVP_sha256" = xyes then : printf "%s\n" "#define HAVE_EVP_SHA256 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_sha384" "ac_cv_func_EVP_sha384" if test "x$ac_cv_func_EVP_sha384" = xyes then : printf "%s\n" "#define HAVE_EVP_SHA384 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_sha512" "ac_cv_func_EVP_sha512" if test "x$ac_cv_func_EVP_sha512" = xyes then : printf "%s\n" "#define HAVE_EVP_SHA512 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_chacha20" "ac_cv_func_EVP_chacha20" if test "x$ac_cv_func_EVP_chacha20" = xyes then : printf "%s\n" "#define HAVE_EVP_CHACHA20 1" >>confdefs.h fi # Check complete ECC support in OpenSSL { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5 printf %s "checking whether OpenSSL has NID_X9_62_prime256v1... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } enable_nistp256=1 else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp384r1" >&5 printf %s "checking whether OpenSSL has NID_secp384r1... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include int main (void) { EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); const EVP_MD *m = EVP_sha384(); /* We need this too */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } enable_nistp384=1 else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp521r1" >&5 printf %s "checking whether OpenSSL has NID_secp521r1... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include int main (void) { EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if OpenSSL's NID_secp521r1 is functional" >&5 printf %s "checking if OpenSSL's NID_secp521r1 is functional... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: assuming yes" >&5 printf "%s\n" "$as_me: WARNING: cross-compiling: assuming yes" >&2;} enable_nistp521=1 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include #include int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } enable_nistp521=1 else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \ test x$enable_nistp521 = x1; then printf "%s\n" "#define OPENSSL_HAS_ECC 1" >>confdefs.h ac_fn_c_check_func "$LINENO" "EC_KEY_METHOD_new" "ac_cv_func_EC_KEY_METHOD_new" if test "x$ac_cv_func_EC_KEY_METHOD_new" = xyes then : printf "%s\n" "#define HAVE_EC_KEY_METHOD_NEW 1" >>confdefs.h fi openssl_ecc=yes else openssl_ecc=no fi if test x$enable_nistp256 = x1; then printf "%s\n" "#define OPENSSL_HAS_NISTP256 1" >>confdefs.h 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 printf "%s\n" "#define OPENSSL_HAS_NISTP384 1" >>confdefs.h 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 printf "%s\n" "#define OPENSSL_HAS_NISTP521 1" >>confdefs.h else unsupported_algorithms="$unsupported_algorithms \ ecdh-sha2-nistp521 \ ecdsa-sha2-nistp521 \ ecdsa-sha2-nistp521-cert-v01@openssh.com" fi # Check libcrypto ED25519 support ac_fn_c_check_func "$LINENO" "EVP_PKEY_get_raw_public_key" "ac_cv_func_EVP_PKEY_get_raw_public_key" if test "x$ac_cv_func_EVP_PKEY_get_raw_public_key" = xyes then : printf "%s\n" "#define HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "EVP_PKEY_get_raw_private_key" "ac_cv_func_EVP_PKEY_get_raw_private_key" if test "x$ac_cv_func_EVP_PKEY_get_raw_private_key" = xyes then : printf "%s\n" "#define HAVE_EVP_PKEY_GET_RAW_PRIVATE_KEY 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has ED25519 support" >&5 printf %s "checking whether OpenSSL has ED25519 support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { unsigned char buf[64]; memset(buf, 0, sizeof(buf)); exit(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, buf, sizeof(buf)) == NULL); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define OPENSSL_HAS_ED25519 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi # PKCS11/U2F depend on OpenSSL and dlopen(). enable_pkcs11=yes enable_sk=yes ac_fn_check_decl "$LINENO" "OPENSSL_IS_AWSLC" "ac_cv_have_decl_OPENSSL_IS_AWSLC" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_OPENSSL_IS_AWSLC" = xyes then : enable_pkcs11="disabled; PKCS#11 not supported with AWS-LC" fi if test "x$openssl" != "xyes" ; then enable_pkcs11="disabled; missing libcrypto" fi if test "x$ac_cv_func_dlopen" != "xyes" ; then enable_pkcs11="disabled; missing dlopen(3)" enable_sk="disabled; missing dlopen(3)" 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable PKCS11" >&5 printf %s "checking whether to enable PKCS11... " >&6; } if test "x$enable_pkcs11" = "xyes" ; then printf "%s\n" "#define ENABLE_PKCS11 /**/" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_pkcs11" >&5 printf "%s\n" "$enable_pkcs11" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable U2F" >&5 printf %s "checking whether to enable U2F... " >&6; } if test "x$enable_sk" = "xyes" ; then printf "%s\n" "#define ENABLE_SK /**/" >>confdefs.h SK_DUMMY_LIBRARY=regress/misc/sk-dummy/sk-dummy.so else # Do not try to build sk-dummy library. SK_DUMMY_LIBRARY="" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_sk" >&5 printf "%s\n" "$enable_sk" >&6; } # Now check for built-in security key support. if test "x$enable_sk" = "xyes" -a "x$enable_sk_internal" != "xno" ; then use_pkgconfig_for_libfido2= if test "x$PKGCONFIG" != "xno"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about libfido2" >&5 printf %s "checking if $PKGCONFIG knows about libfido2... " >&6; } if "$PKGCONFIG" libfido2; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } use_pkgconfig_for_libfido2=yes else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } 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//'` fido2_error= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fido_init in -lfido2" >&5 printf %s "checking for fido_init in -lfido2... " >&6; } if test ${ac_cv_lib_fido2_fido_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lfido2 $OTHERLIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char fido_init (); int main (void) { return fido_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_fido2_fido_init=yes else $as_nop ac_cv_lib_fido2_fido_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fido2_fido_init" >&5 printf "%s\n" "$ac_cv_lib_fido2_fido_init" >&6; } if test "x$ac_cv_lib_fido2_fido_init" = xyes then : else $as_nop fido2_error="missing/unusable libfido2" fi ac_fn_c_check_header_compile "$LINENO" "fido.h" "ac_cv_header_fido_h" "$ac_includes_default" if test "x$ac_cv_header_fido_h" = xyes then : else $as_nop fido2_error="missing fido.h from libfido2" fi ac_fn_c_check_header_compile "$LINENO" "fido/credman.h" "ac_cv_header_fido_credman_h" " #include " if test "x$ac_cv_header_fido_credman_h" = xyes then : else $as_nop fido2_error="missing fido/credman.h from libfido2" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for usable libfido2 installation" >&5 printf %s "checking for usable libfido2 installation... " >&6; } if test ! -z "$fido2_error" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $fido2_error" >&5 printf "%s\n" "$fido2_error" >&6; } if test "x$enable_sk_internal" = "xyes" ; then as_fn_error $? "No usable libfido2 library/headers found" "$LINENO" 5 fi LIBFIDO2="" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define ENABLE_SK_INTERNAL /**/" >>confdefs.h enable_sk="built-in" saved_LIBS="$LIBS" LIBS="$LIBFIDO2 $LIBS" ac_fn_c_check_func "$LINENO" "fido_assert_set_clientdata" "ac_cv_func_fido_assert_set_clientdata" if test "x$ac_cv_func_fido_assert_set_clientdata" = xyes then : printf "%s\n" "#define HAVE_FIDO_ASSERT_SET_CLIENTDATA 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fido_cred_prot" "ac_cv_func_fido_cred_prot" if test "x$ac_cv_func_fido_cred_prot" = xyes then : printf "%s\n" "#define HAVE_FIDO_CRED_PROT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fido_cred_set_prot" "ac_cv_func_fido_cred_set_prot" if test "x$ac_cv_func_fido_cred_set_prot" = xyes then : printf "%s\n" "#define HAVE_FIDO_CRED_SET_PROT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fido_cred_set_clientdata" "ac_cv_func_fido_cred_set_clientdata" if test "x$ac_cv_func_fido_cred_set_clientdata" = xyes then : printf "%s\n" "#define HAVE_FIDO_CRED_SET_CLIENTDATA 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fido_dev_get_touch_begin" "ac_cv_func_fido_dev_get_touch_begin" if test "x$ac_cv_func_fido_dev_get_touch_begin" = xyes then : printf "%s\n" "#define HAVE_FIDO_DEV_GET_TOUCH_BEGIN 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fido_dev_get_touch_status" "ac_cv_func_fido_dev_get_touch_status" if test "x$ac_cv_func_fido_dev_get_touch_status" = xyes then : printf "%s\n" "#define HAVE_FIDO_DEV_GET_TOUCH_STATUS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fido_dev_supports_cred_prot" "ac_cv_func_fido_dev_supports_cred_prot" if test "x$ac_cv_func_fido_dev_supports_cred_prot" = xyes then : printf "%s\n" "#define HAVE_FIDO_DEV_SUPPORTS_CRED_PROT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fido_dev_is_winhello" "ac_cv_func_fido_dev_is_winhello" if test "x$ac_cv_func_fido_dev_is_winhello" = xyes then : printf "%s\n" "#define HAVE_FIDO_DEV_IS_WINHELLO 1" >>confdefs.h fi LIBS="$saved_LIBS" fi fi # Check for standalone SecurityKeyProvider { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build standalone sk-libfido2" >&5 printf %s "checking whether to build standalone sk-libfido2... " >&6; } if test "x$enable_sk_standalone" = "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SK_STANDALONE=sk-libfido2$SHLIBEXT else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SK_STANDALONE="" fi ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random" if test "x$ac_cv_func_arc4random" = xyes then : printf "%s\n" "#define HAVE_ARC4RANDOM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "arc4random_buf" "ac_cv_func_arc4random_buf" if test "x$ac_cv_func_arc4random_buf" = xyes then : printf "%s\n" "#define HAVE_ARC4RANDOM_BUF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "arc4random_stir" "ac_cv_func_arc4random_stir" if test "x$ac_cv_func_arc4random_stir" = xyes then : printf "%s\n" "#define HAVE_ARC4RANDOM_STIR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "arc4random_uniform" "ac_cv_func_arc4random_uniform" if test "x$ac_cv_func_arc4random_uniform" = xyes then : printf "%s\n" "#define HAVE_ARC4RANDOM_UNIFORM 1" >>confdefs.h fi ### Configure cryptographic random number support # Check whether OpenSSL seeds itself if test "x$openssl" = "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's PRNG is internally seeded" >&5 printf %s "checking whether OpenSSL's PRNG is internally seeded... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 printf "%s\n" "$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 $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { exit(RAND_status() == 1 ? 0 : 1); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : OPENSSL_SEEDS_ITSELF=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi # PRNGD TCP socket # Check whether --with-prngd-port was given. if test ${with_prngd_port+y} then : withval=$with_prngd_port; case "$withval" in no) withval="" ;; [0-9]*) ;; *) as_fn_error $? "You must specify a numeric port number for --with-prngd-port" "$LINENO" 5 ;; esac if test ! -z "$withval" ; then PRNGD_PORT="$withval" printf "%s\n" "#define PRNGD_PORT $PRNGD_PORT" >>confdefs.h fi fi # PRNGD Unix domain socket # Check whether --with-prngd-socket was given. if test ${with_prngd_socket+y} then : withval=$with_prngd_socket; case "$withval" in yes) withval="/var/run/egd-pool" ;; no) withval="" ;; /*) ;; *) as_fn_error $? "You must specify an absolute path to the entropy socket" "$LINENO" 5 ;; esac if test ! -z "$withval" ; then if test ! -z "$PRNGD_PORT" ; then as_fn_error $? "You may not specify both a PRNGD/EGD port and socket" "$LINENO" 5 fi if test ! -r "$withval" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Entropy socket is not readable" >&5 printf "%s\n" "$as_me: WARNING: Entropy socket is not readable" >&2;} fi PRNGD_SOCKET="$withval" printf "%s\n" "#define PRNGD_SOCKET \"$PRNGD_SOCKET\"" >>confdefs.h fi else $as_nop # Check for existing socket only if we don't have a random device already if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PRNGD/EGD socket" >&5 printf %s "checking for PRNGD/EGD socket... " >&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" printf "%s\n" "#define PRNGD_SOCKET \"$PRNGD_SOCKET\"" >>confdefs.h break; fi done if test ! -z "$PRNGD_SOCKET" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PRNGD_SOCKET" >&5 printf "%s\n" "$PRNGD_SOCKET" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 printf "%s\n" "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 printf "%s\n" "#define OPENSSL_PRNG_ONLY 1" >>confdefs.h RAND_MSG="OpenSSL internal ONLY" elif test "x$openssl" = "xno" ; then { printf "%s\n" "$as_me:${as_lineno-$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 printf "%s\n" "$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 as_fn_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" "$LINENO" 5 fi LIBS="$nocrypto_saved_LIBS" saved_LIBS="$LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5 printf %s "checking for ia_openinfo in -liaf... " >&6; } if test ${ac_cv_lib_iaf_ia_openinfo+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-liaf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char ia_openinfo (); int main (void) { return ia_openinfo (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_iaf_ia_openinfo=yes else $as_nop ac_cv_lib_iaf_ia_openinfo=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iaf_ia_openinfo" >&5 printf "%s\n" "$ac_cv_lib_iaf_ia_openinfo" >&6; } if test "x$ac_cv_lib_iaf_ia_openinfo" = xyes then : LIBS="$LIBS -liaf" for ac_func in set_id do : ac_fn_c_check_func "$LINENO" "set_id" "ac_cv_func_set_id" if test "x$ac_cv_func_set_id" = xyes then : printf "%s\n" "#define HAVE_SET_ID 1" >>confdefs.h SSHDLIBS="$SSHDLIBS -liaf" printf "%s\n" "#define HAVE_LIBIAF 1" >>confdefs.h fi done fi LIBS="$saved_LIBS" # Check for crypt() in libcrypt. If we have it, we only need it for sshd. saved_LIBS="$LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5 printf %s "checking for crypt in -lcrypt... " >&6; } if test ${ac_cv_lib_crypt_crypt+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char crypt (); int main (void) { return crypt (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_crypt_crypt=yes else $as_nop ac_cv_lib_crypt_crypt=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5 printf "%s\n" "$ac_cv_lib_crypt_crypt" >&6; } if test "x$ac_cv_lib_crypt_crypt" = xyes then : LIBS="-lcrypt $LIBS" SSHDLIBS="-lcrypt $SSHDLIBS" fi ac_fn_c_check_func "$LINENO" "crypt" "ac_cv_func_crypt" if test "x$ac_cv_func_crypt" = xyes then : printf "%s\n" "#define HAVE_CRYPT 1" >>confdefs.h fi LIBS="$saved_LIBS" # Check for PAM libs PAM_MSG="no" # Check whether --with-pam was given. if test ${with_pam+y} 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 as_fn_error $? "PAM headers not found" "$LINENO" 5 fi saved_LIBS="$LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else $as_nop ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : printf "%s\n" "#define HAVE_LIBDL 1" >>confdefs.h LIBS="-ldl $LIBS" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pam_set_item in -lpam" >&5 printf %s "checking for pam_set_item in -lpam... " >&6; } if test ${ac_cv_lib_pam_pam_set_item+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpam $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pam_set_item (); int main (void) { return pam_set_item (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pam_pam_set_item=yes else $as_nop ac_cv_lib_pam_pam_set_item=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_set_item" >&5 printf "%s\n" "$ac_cv_lib_pam_pam_set_item" >&6; } if test "x$ac_cv_lib_pam_pam_set_item" = xyes then : printf "%s\n" "#define HAVE_LIBPAM 1" >>confdefs.h LIBS="-lpam $LIBS" else $as_nop as_fn_error $? "*** libpam missing" "$LINENO" 5 fi ac_fn_c_check_func "$LINENO" "pam_getenvlist" "ac_cv_func_pam_getenvlist" if test "x$ac_cv_func_pam_getenvlist" = xyes then : printf "%s\n" "#define HAVE_PAM_GETENVLIST 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "pam_putenv" "ac_cv_func_pam_putenv" if test "x$ac_cv_func_pam_putenv" = xyes then : printf "%s\n" "#define HAVE_PAM_PUTENV 1" >>confdefs.h fi LIBS="$saved_LIBS" PAM_MSG="yes" SSHDLIBS="$SSHDLIBS -lpam" printf "%s\n" "#define USE_PAM 1" >>confdefs.h 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 whether --with-pam-service was given. if test ${with_pam_service+y} then : withval=$with_pam_service; if test "x$withval" != "xno" && \ test "x$withval" != "xyes" ; then printf "%s\n" "#define SSHD_PAM_SERVICE \"$withval\"" >>confdefs.h fi fi # Check for older PAM if test "x$PAM_MSG" = "xyes" ; then # Check PAM strerror arguments (old PAM) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pam_strerror takes only one argument" >&5 printf %s "checking whether pam_strerror takes only one argument... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if defined(HAVE_SECURITY_PAM_APPL_H) #include #elif defined (HAVE_PAM_PAM_APPL_H) #include #endif int main (void) { (void)pam_strerror((pam_handle_t *)NULL, -1); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else $as_nop printf "%s\n" "#define HAVE_OLD_PAM 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } PAM_MSG="yes (old library)" fi rm -f core conftest.err conftest.$ac_objext conftest.beam 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+y} 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 printf "%s\n" "#define SSH_PRIVSEP_USER CYGWIN_SSH_PRIVSEP_USER" >>confdefs.h else printf "%s\n" "#define SSH_PRIVSEP_USER \"$SSH_PRIVSEP_USER\"" >>confdefs.h fi if test "x$have_linux_no_new_privs" = "x1" ; then ac_fn_check_decl "$LINENO" "SECCOMP_MODE_FILTER" "ac_cv_have_decl_SECCOMP_MODE_FILTER" " #include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_SECCOMP_MODE_FILTER" = xyes then : have_seccomp_filter=1 fi fi if test "x$have_seccomp_filter" = "x1" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking kernel for seccomp_filter support" >&5 printf %s "checking kernel for seccomp_filter support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } # Disable seccomp filter as a target have_seccomp_filter=0 fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi ac_fn_c_check_member "$LINENO" "struct pollfd" "fd" "ac_cv_member_struct_pollfd_fd" " #include #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif " if test "x$ac_cv_member_struct_pollfd_fd" = xyes then : printf "%s\n" "#define HAVE_STRUCT_POLLFD_FD 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "nfds_t" "ac_cv_type_nfds_t" " #include #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif " if test "x$ac_cv_type_nfds_t" = xyes then : printf "%s\n" "#define HAVE_NFDS_T 1" >>confdefs.h fi # Decide which sandbox style to use sandbox_arg="" # Check whether --with-sandbox was given. if test ${with_sandbox+y} then : withval=$with_sandbox; if test "x$withval" = "xyes" ; then sandbox_arg="" else sandbox_arg="$withval" fi fi if test "x$sandbox_arg" != "xno"; then # POSIX specifies that poll() "shall fail with EINVAL if the nfds argument # is greater than OPEN_MAX". On some platforms that includes implementions # of select in userspace on top of poll() so check both work with rlimit # NOFILES so check that both work before enabling the rlimit sandbox. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if select and/or poll works with descriptor rlimit" >&5 printf %s "checking if select and/or poll works with descriptor rlimit... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming no" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming no" >&2;} select_works_with_rlimit=no else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef HAVE_SYS_TIME_H # include #endif #include #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_POLL_H # include #elif HAVE_SYS_POLL_H # include #endif #include #include #include int main (void) { struct rlimit rl_zero; int fd, r; fd_set fds; struct timeval tv; #ifdef HAVE_POLL struct pollfd pfd; #endif fd = open("/dev/null", O_RDONLY); FD_ZERO(&fds); FD_SET(fd, &fds); rl_zero.rlim_cur = rl_zero.rlim_max = 0; setrlimit(RLIMIT_FSIZE, &rl_zero); setrlimit(RLIMIT_NOFILE, &rl_zero); tv.tv_sec = 1; tv.tv_usec = 0; r = select(fd+1, &fds, NULL, NULL, &tv); if (r == -1) exit(1); #ifdef HAVE_POLL pfd.fd = fd; pfd.events = POLLIN; r = poll(&pfd, 1, 1); if (r == -1) exit(2); #endif exit(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } select_works_with_rlimit=yes else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setrlimit(RLIMIT_NOFILE,{0,0}) works" >&5 printf %s "checking if setrlimit(RLIMIT_NOFILE,{0,0}) works... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} rlimit_nofile_zero_works=yes else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include int main (void) { struct rlimit rl_zero; int r; rl_zero.rlim_cur = rl_zero.rlim_max = 0; r = setrlimit(RLIMIT_NOFILE, &rl_zero); exit (r == -1 ? 1 : 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } rlimit_nofile_zero_works=yes else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setrlimit RLIMIT_FSIZE works" >&5 printf %s "checking if setrlimit RLIMIT_FSIZE works... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { struct rlimit rl_zero; rl_zero.rlim_cur = rl_zero.rlim_max = 0; exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define SANDBOX_SKIP_RLIMIT_FSIZE 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if 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" && \ as_fn_error $? "Darwin seatbelt sandbox requires sandbox.h and sandbox_init function" "$LINENO" 5 SANDBOX_STYLE="darwin" printf "%s\n" "#define SANDBOX_DARWIN 1" >>confdefs.h 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" && \ as_fn_error $? "seccomp_filter sandbox not supported on $host" "$LINENO" 5 test "x$have_linux_no_new_privs" != "x1" && \ as_fn_error $? "seccomp_filter sandbox requires PR_SET_NO_NEW_PRIVS" "$LINENO" 5 test "x$have_seccomp_filter" != "x1" && \ as_fn_error $? "seccomp_filter sandbox requires seccomp headers" "$LINENO" 5 test "x$ac_cv_func_prctl" != "xyes" && \ as_fn_error $? "seccomp_filter sandbox requires prctl function" "$LINENO" 5 SANDBOX_STYLE="seccomp_filter" printf "%s\n" "#define SANDBOX_SECCOMP_FILTER 1" >>confdefs.h elif test "x$sandbox_arg" = "xcapsicum" || \ ( test -z "$sandbox_arg" && \ test "x$disable_capsicum" != "xyes" && \ test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \ test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \ as_fn_error $? "capsicum sandbox requires sys/capsicum.h header" "$LINENO" 5 test "x$ac_cv_func_cap_rights_limit" != "xyes" && \ as_fn_error $? "capsicum sandbox requires cap_rights_limit function" "$LINENO" 5 SANDBOX_STYLE="capsicum" printf "%s\n" "#define SANDBOX_CAPSICUM 1" >>confdefs.h 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" && \ as_fn_error $? "rlimit sandbox requires setrlimit function" "$LINENO" 5 test "x$select_works_with_rlimit" != "xyes" && \ as_fn_error $? "rlimit sandbox requires select to work with rlimit" "$LINENO" 5 SANDBOX_STYLE="rlimit" printf "%s\n" "#define SANDBOX_RLIMIT 1" >>confdefs.h elif test "x$sandbox_arg" = "xsolaris" || \ ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then SANDBOX_STYLE="solaris" printf "%s\n" "#define SANDBOX_SOLARIS 1" >>confdefs.h elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \ test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then SANDBOX_STYLE="none" printf "%s\n" "#define SANDBOX_NULL 1" >>confdefs.h else as_fn_error $? "unsupported --with-sandbox" "$LINENO" 5 fi # Cheap hack to ensure NEWS-OS libraries are arranged right. if test ! -z "$SONY" ; then LIBS="$LIBS -liberty"; fi # Check for long long datatypes ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" if test "x$ac_cv_type_long_long" = xyes then : printf "%s\n" "#define HAVE_LONG_LONG 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default" if test "x$ac_cv_type_unsigned_long_long" = xyes then : printf "%s\n" "#define HAVE_UNSIGNED_LONG_LONG 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "long double" "ac_cv_type_long_double" "$ac_includes_default" if test "x$ac_cv_type_long_double" = xyes then : printf "%s\n" "#define HAVE_LONG_DOUBLE 1" >>confdefs.h fi # Check datatype sizes # 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. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of short int" >&5 printf %s "checking size of short int... " >&6; } if test ${ac_cv_sizeof_short_int+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short int))" "ac_cv_sizeof_short_int" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_short_int" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (short int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_short_int=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short_int" >&5 printf "%s\n" "$ac_cv_sizeof_short_int" >&6; } printf "%s\n" "#define SIZEOF_SHORT_INT $ac_cv_sizeof_short_int" >>confdefs.h # 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. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 printf %s "checking size of int... " >&6; } if test ${ac_cv_sizeof_int+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_int" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_int=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 printf "%s\n" "$ac_cv_sizeof_int" >&6; } printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h # 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. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long int" >&5 printf %s "checking size of long int... " >&6; } if test ${ac_cv_sizeof_long_int+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long int))" "ac_cv_sizeof_long_int" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_long_int" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long_int=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_int" >&5 printf "%s\n" "$ac_cv_sizeof_long_int" >&6; } printf "%s\n" "#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int" >>confdefs.h # 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. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long int" >&5 printf %s "checking size of long long int... " >&6; } if test ${ac_cv_sizeof_long_long_int+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long int))" "ac_cv_sizeof_long_long_int" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_long_long_int" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long long int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long_long_int=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long_int" >&5 printf "%s\n" "$ac_cv_sizeof_long_long_int" >&6; } printf "%s\n" "#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int" >>confdefs.h # 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. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 printf %s "checking size of time_t... " >&6; } if test ${ac_cv_sizeof_time_t+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" " #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_TIME_H # include #endif " then : else $as_nop if test "$ac_cv_type_time_t" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (time_t) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_time_t=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 printf "%s\n" "$ac_cv_sizeof_time_t" >&6; } printf "%s\n" "#define SIZEOF_TIME_T $ac_cv_sizeof_time_t" >>confdefs.h # Sanity check long long for some platforms (AIX) if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then ac_cv_sizeof_long_long_int=0 fi # compute LLONG_MIN and LLONG_MAX if we don't know them. if test -z "$have_llong_max" && test -z "$have_long_long_max"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for max value of long long" >&5 printf %s "checking for max value of long long... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include /* Why is this so damn hard? */ #ifdef __GNUC__ # undef __GNUC__ #endif #define __USE_ISOC99 #include #define DATA "conftest.llminmax" #define my_abs(a) ((a) < 0 ? ((a) * -1) : (a)) /* * printf in libc on some platforms (eg old Tru64) does not understand %lld so * we do this the hard way. */ static int fprint_ll(FILE *f, long long n) { unsigned int i; int l[sizeof(long long) * 8]; if (n < 0) if (fprintf(f, "-") < 0) return -1; for (i = 0; n != 0; i++) { l[i] = my_abs(n % 10); n /= 10; } do { if (fprintf(f, "%d", l[--i]) < 0) return -1; } while (i != 0); if (fprintf(f, " ") < 0) return -1; return 0; } int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : llong_min=`$AWK '{print $1}' conftest.llminmax` llong_max=`$AWK '{print $2}' conftest.llminmax` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $llong_max" >&5 printf "%s\n" "$llong_max" >&6; } printf "%s\n" "#define LLONG_MAX ${llong_max}LL" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for min value of long long" >&5 printf %s "checking for min value of long long... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $llong_min" >&5 printf "%s\n" "$llong_min" >&6; } printf "%s\n" "#define LLONG_MIN ${llong_min}LL" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 printf "%s\n" "not found" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi ac_fn_check_decl "$LINENO" "UINT32_MAX" "ac_cv_have_decl_UINT32_MAX" " #ifdef HAVE_SYS_LIMITS_H # include #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef HAVE_STDINT_H # include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_UINT32_MAX" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_UINT32_MAX $ac_have_decl" >>confdefs.h # More checks for data types { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_int type" >&5 printf %s "checking for u_int type... " >&6; } if test ${ac_cv_have_u_int+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { u_int a; a = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_u_int="yes" else $as_nop ac_cv_have_u_int="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int" >&5 printf "%s\n" "$ac_cv_have_u_int" >&6; } if test "x$ac_cv_have_u_int" = "xyes" ; then printf "%s\n" "#define HAVE_U_INT 1" >>confdefs.h have_u_int=1 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for intXX_t types" >&5 printf %s "checking for intXX_t types... " >&6; } if test ${ac_cv_have_intxx_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int8_t a; int16_t b; int32_t c; a = b = c = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_intxx_t="yes" else $as_nop ac_cv_have_intxx_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_intxx_t" >&5 printf "%s\n" "$ac_cv_have_intxx_t" >&6; } if test "x$ac_cv_have_intxx_t" = "xyes" ; then printf "%s\n" "#define HAVE_INTXX_T 1" >>confdefs.h have_intxx_t=1 fi if (test -z "$have_intxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for intXX_t types in stdint.h" >&5 printf %s "checking for intXX_t types in stdint.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int8_t a; int16_t b; int32_t c; a = b = c = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_INTXX_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for int64_t type" >&5 printf %s "checking for int64_t type... " >&6; } if test ${ac_cv_have_int64_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef HAVE_STDINT_H # include #endif #include #ifdef HAVE_SYS_BITYPES_H # include #endif int main (void) { int64_t a; a = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_int64_t="yes" else $as_nop ac_cv_have_int64_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_int64_t" >&5 printf "%s\n" "$ac_cv_have_int64_t" >&6; } if test "x$ac_cv_have_int64_t" = "xyes" ; then printf "%s\n" "#define HAVE_INT64_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types" >&5 printf %s "checking for u_intXX_t types... " >&6; } if test ${ac_cv_have_u_intxx_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_u_intxx_t="yes" else $as_nop ac_cv_have_u_intxx_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_intxx_t" >&5 printf "%s\n" "$ac_cv_have_u_intxx_t" >&6; } if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then printf "%s\n" "#define HAVE_U_INTXX_T 1" >>confdefs.h have_u_intxx_t=1 fi if test -z "$have_u_intxx_t" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types in sys/socket.h" >&5 printf %s "checking for u_intXX_t types in sys/socket.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_U_INTXX_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_int64_t types" >&5 printf %s "checking for u_int64_t types... " >&6; } if test ${ac_cv_have_u_int64_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { u_int64_t a; a = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_u_int64_t="yes" else $as_nop ac_cv_have_u_int64_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int64_t" >&5 printf "%s\n" "$ac_cv_have_u_int64_t" >&6; } if test "x$ac_cv_have_u_int64_t" = "xyes" ; then printf "%s\n" "#define HAVE_U_INT64_T 1" >>confdefs.h have_u_int64_t=1 fi if (test -z "$have_u_int64_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_int64_t type in sys/bitypes.h" >&5 printf %s "checking for u_int64_t type in sys/bitypes.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { u_int64_t a; a = 1 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_U_INT64_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test -z "$have_u_intxx_t" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types" >&5 printf %s "checking for uintXX_t types... " >&6; } if test ${ac_cv_have_uintxx_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_uintxx_t="yes" else $as_nop ac_cv_have_uintxx_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_uintxx_t" >&5 printf "%s\n" "$ac_cv_have_uintxx_t" >&6; } if test "x$ac_cv_have_uintxx_t" = "xyes" ; then printf "%s\n" "#define HAVE_UINTXX_T 1" >>confdefs.h fi fi if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in stdint.h" >&5 printf %s "checking for uintXX_t types in stdint.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_UINTXX_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_inttypes_h" = "xyes") then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in inttypes.h" >&5 printf %s "checking for uintXX_t types in inttypes.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_UINTXX_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5 printf %s "checking for intXX_t and u_intXX_t types in sys/bitypes.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { 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 if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_U_INTXX_T 1" >>confdefs.h printf "%s\n" "#define HAVE_INTXX_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_char" >&5 printf %s "checking for u_char... " >&6; } if test ${ac_cv_have_u_char+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { u_char foo; foo = 125; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_u_char="yes" else $as_nop ac_cv_have_u_char="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_char" >&5 printf "%s\n" "$ac_cv_have_u_char" >&6; } if test "x$ac_cv_have_u_char" = "xyes" ; then printf "%s\n" "#define HAVE_U_CHAR 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" " #include #ifdef HAVE_STDINT_H # include #endif " if test "x$ac_cv_type_intmax_t" = xyes then : printf "%s\n" "#define HAVE_INTMAX_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" " #include #ifdef HAVE_STDINT_H # include #endif " if test "x$ac_cv_type_uintmax_t" = xyes then : printf "%s\n" "#define HAVE_UINTMAX_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include #include " if test "x$ac_cv_type_socklen_t" = xyes then : else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5 printf %s "checking for socklen_t equivalent... " >&6; } if test ${curl_cv_socklen_t_equiv+y} then : printf %s "(cached) " >&6 else $as_nop # 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int getpeername (int, $arg2 *, $t *); int main (void) { $t len; getpeername(0,0,&len); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : curl_cv_socklen_t_equiv="$t" break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done done if test "x$curl_cv_socklen_t_equiv" = x; then as_fn_error $? "Cannot find a type to use in place of socklen_t" "$LINENO" 5 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_socklen_t_equiv" >&5 printf "%s\n" "$curl_cv_socklen_t_equiv" >&6; } printf "%s\n" "#define socklen_t $curl_cv_socklen_t_equiv" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "sig_atomic_t" "ac_cv_type_sig_atomic_t" "#include " if test "x$ac_cv_type_sig_atomic_t" = xyes then : printf "%s\n" "#define HAVE_SIG_ATOMIC_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "sighandler_t" "ac_cv_type_sighandler_t" "#include " if test "x$ac_cv_type_sighandler_t" = xyes then : printf "%s\n" "#define HAVE_SIGHANDLER_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "fsblkcnt_t" "ac_cv_type_fsblkcnt_t" " #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif " if test "x$ac_cv_type_fsblkcnt_t" = xyes then : printf "%s\n" "#define HAVE_FSBLKCNT_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "fsfilcnt_t" "ac_cv_type_fsfilcnt_t" " #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif " if test "x$ac_cv_type_fsfilcnt_t" = xyes then : printf "%s\n" "#define HAVE_FSFILCNT_T 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct statfs" "f_files" "ac_cv_member_struct_statfs_f_files" " #include #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif " if test "x$ac_cv_member_struct_statfs_f_files" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STATFS_F_FILES 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct statfs" "f_flags" "ac_cv_member_struct_statfs_f_flags" " #include #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif " if test "x$ac_cv_member_struct_statfs_f_flags" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STATFS_F_FLAGS 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" "#include #include " if test "x$ac_cv_type_in_addr_t" = xyes then : printf "%s\n" "#define HAVE_IN_ADDR_T 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" "#include #include " if test "x$ac_cv_type_in_port_t" = xyes then : printf "%s\n" "#define HAVE_IN_PORT_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for size_t" >&5 printf %s "checking for size_t... " >&6; } if test ${ac_cv_have_size_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { size_t foo; foo = 1235; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_size_t="yes" else $as_nop ac_cv_have_size_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_size_t" >&5 printf "%s\n" "$ac_cv_have_size_t" >&6; } if test "x$ac_cv_have_size_t" = "xyes" ; then printf "%s\n" "#define HAVE_SIZE_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ssize_t" >&5 printf %s "checking for ssize_t... " >&6; } if test ${ac_cv_have_ssize_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { ssize_t foo; foo = 1235; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_ssize_t="yes" else $as_nop ac_cv_have_ssize_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ssize_t" >&5 printf "%s\n" "$ac_cv_have_ssize_t" >&6; } if test "x$ac_cv_have_ssize_t" = "xyes" ; then printf "%s\n" "#define HAVE_SSIZE_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_t" >&5 printf %s "checking for clock_t... " >&6; } if test ${ac_cv_have_clock_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { clock_t foo; foo = 1235; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_clock_t="yes" else $as_nop ac_cv_have_clock_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_clock_t" >&5 printf "%s\n" "$ac_cv_have_clock_t" >&6; } if test "x$ac_cv_have_clock_t" = "xyes" ; then printf "%s\n" "#define HAVE_CLOCK_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sa_family_t" >&5 printf %s "checking for sa_family_t... " >&6; } if test ${ac_cv_have_sa_family_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { sa_family_t foo; foo = 1235; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_sa_family_t="yes" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { sa_family_t foo; foo = 1235; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_sa_family_t="yes" else $as_nop ac_cv_have_sa_family_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_sa_family_t" >&5 printf "%s\n" "$ac_cv_have_sa_family_t" >&6; } if test "x$ac_cv_have_sa_family_t" = "xyes" ; then printf "%s\n" "#define HAVE_SA_FAMILY_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pid_t" >&5 printf %s "checking for pid_t... " >&6; } if test ${ac_cv_have_pid_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pid_t foo; foo = 1235; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_pid_t="yes" else $as_nop ac_cv_have_pid_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pid_t" >&5 printf "%s\n" "$ac_cv_have_pid_t" >&6; } if test "x$ac_cv_have_pid_t" = "xyes" ; then printf "%s\n" "#define HAVE_PID_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mode_t" >&5 printf %s "checking for mode_t... " >&6; } if test ${ac_cv_have_mode_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { mode_t foo; foo = 1235; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_mode_t="yes" else $as_nop ac_cv_have_mode_t="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_mode_t" >&5 printf "%s\n" "$ac_cv_have_mode_t" >&6; } if test "x$ac_cv_have_mode_t" = "xyes" ; then printf "%s\n" "#define HAVE_MODE_T 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_storage" >&5 printf %s "checking for struct sockaddr_storage... " >&6; } if test ${ac_cv_have_struct_sockaddr_storage+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct sockaddr_storage s; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_struct_sockaddr_storage="yes" else $as_nop ac_cv_have_struct_sockaddr_storage="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_storage" >&5 printf "%s\n" "$ac_cv_have_struct_sockaddr_storage" >&6; } if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_in6" >&5 printf %s "checking for struct sockaddr_in6... " >&6; } if test ${ac_cv_have_struct_sockaddr_in6+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct sockaddr_in6 s; s.sin6_family = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_struct_sockaddr_in6="yes" else $as_nop ac_cv_have_struct_sockaddr_in6="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_in6" >&5 printf "%s\n" "$ac_cv_have_struct_sockaddr_in6" >&6; } if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct in6_addr" >&5 printf %s "checking for struct in6_addr... " >&6; } if test ${ac_cv_have_struct_in6_addr+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct in6_addr s; s.s6_addr[0] = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_struct_in6_addr="yes" else $as_nop ac_cv_have_struct_in6_addr="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_in6_addr" >&5 printf "%s\n" "$ac_cv_have_struct_in6_addr" >&6; } if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_scope_id" "ac_cv_member_struct_sockaddr_in6_sin6_scope_id" " #ifdef HAVE_SYS_TYPES_H #include #endif #include " if test "x$ac_cv_member_struct_sockaddr_in6_sin6_scope_id" = xyes then : printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1" >>confdefs.h fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct addrinfo" >&5 printf %s "checking for struct addrinfo... " >&6; } if test ${ac_cv_have_struct_addrinfo+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main (void) { struct addrinfo s; s.ai_flags = AI_PASSIVE; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_struct_addrinfo="yes" else $as_nop ac_cv_have_struct_addrinfo="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_addrinfo" >&5 printf "%s\n" "$ac_cv_have_struct_addrinfo" >&6; } if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_ADDRINFO 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct timeval" >&5 printf %s "checking for struct timeval... " >&6; } if test ${ac_cv_have_struct_timeval+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { struct timeval tv; tv.tv_sec = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_struct_timeval="yes" else $as_nop ac_cv_have_struct_timeval="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_timeval" >&5 printf "%s\n" "$ac_cv_have_struct_timeval" >&6; } if test "x$ac_cv_have_struct_timeval" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_TIMEVAL 1" >>confdefs.h have_struct_timeval=1 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct timespec" >&5 printf %s "checking for struct timespec... " >&6; } if test ${ac_cv_have_struct_timespec+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_TIME_H # include #endif int main (void) { struct timespec ts; ts.tv_sec = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_struct_timespec="yes" else $as_nop ac_cv_have_struct_timespec="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_timespec" >&5 printf "%s\n" "$ac_cv_have_struct_timespec" >&6; } if test "x$ac_cv_have_struct_timespec" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_TIMESPEC 1" >>confdefs.h have_struct_timespec=1 fi # We need int64_t or else certain parts of the compile will fail. if test "x$ac_cv_have_int64_t" = "xno" && \ test "x$ac_cv_sizeof_long_int" != "x8" && \ test "x$ac_cv_sizeof_long_long_int" = "x0" ; then echo "OpenSSH requires int64_t support. Contact your vendor or install" echo "an alternative compiler (I.E., GCC) before continuing." echo "" exit 1; else if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #ifdef HAVE_SNPRINTF int main(void) { char buf[50]; char expected_out[50]; int mazsize = 50 ; #if (SIZEOF_LONG_INT == 8) long int num = 0x7fffffffffffffff; #else long long num = 0x7fffffffffffffffll; #endif strcpy(expected_out, "9223372036854775807"); #if (SIZEOF_LONG_INT == 8) snprintf(buf, mazsize, "%ld", num); #else snprintf(buf, mazsize, "%lld", num); #endif if(strcmp(buf, expected_out) != 0) exit(1); exit(0); } #else int main(void) { exit(0); } #endif _ACEOF if ac_fn_c_try_run "$LINENO" then : true else $as_nop printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmp.h" >&5 printf %s "checking for ut_host field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_host" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_HOST_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmpx.h" >&5 printf %s "checking for ut_host field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_host" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_HOST_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for syslen field in utmpx.h" >&5 printf %s "checking for syslen field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "syslen" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_SYSLEN_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_pid field in utmp.h" >&5 printf %s "checking for ut_pid field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_pid" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_PID_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmp.h" >&5 printf %s "checking for ut_type field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_type" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_TYPE_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmpx.h" >&5 printf %s "checking for ut_type field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_type" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_TYPE_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmp.h" >&5 printf %s "checking for ut_tv field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_tv" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_TV_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmp.h" >&5 printf %s "checking for ut_id field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_id" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_ID_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmpx.h" >&5 printf %s "checking for ut_id field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_id" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_ID_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmp.h" >&5 printf %s "checking for ut_addr field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_addr" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_ADDR_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmpx.h" >&5 printf %s "checking for ut_addr field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_addr" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_ADDR_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmp.h" >&5 printf %s "checking for ut_addr_v6 field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_addr_v6" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_ADDR_V6_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmpx.h" >&5 printf %s "checking for ut_addr_v6 field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_addr_v6" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_ADDR_V6_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_exit field in utmp.h" >&5 printf %s "checking for ut_exit field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_exit" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_EXIT_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmp.h" >&5 printf %s "checking for ut_time field in utmp.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_time" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_TIME_IN_UTMP 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmpx.h" >&5 printf %s "checking for ut_time field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_time" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_TIME_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmpx.h" >&5 printf %s "checking for ut_tv field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_tv" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_TV_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # look for field 'ut_ss' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_ss { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_ss field in utmpx.h" >&5 printf %s "checking for ut_ss field in utmpx.h... " >&6; } if eval test \${$ossh_varname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ut_ss" >/dev/null 2>&1 then : eval "$ossh_varname=yes" else $as_nop eval "$ossh_varname=no" fi rm -rf conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 printf "%s\n" "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then printf "%s\n" "#define HAVE_SS_IN_UTMPX 1" >>confdefs.h fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_blksize" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STAT_ST_BLKSIZE 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_mtim" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIM 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct stat" "st_mtime" "ac_cv_member_struct_stat_st_mtime" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_mtime" = xyes then : printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIME 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_gecos" "ac_cv_member_struct_passwd_pw_gecos" " #include #include " if test "x$ac_cv_member_struct_passwd_pw_gecos" = xyes then : printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_GECOS 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_class" "ac_cv_member_struct_passwd_pw_class" " #include #include " if test "x$ac_cv_member_struct_passwd_pw_class" = xyes then : printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_CLASS 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_change" "ac_cv_member_struct_passwd_pw_change" " #include #include " if test "x$ac_cv_member_struct_passwd_pw_change" = xyes then : printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_CHANGE 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_expire" "ac_cv_member_struct_passwd_pw_expire" " #include #include " if test "x$ac_cv_member_struct_passwd_pw_expire" = xyes then : printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_EXPIRE 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct __res_state" "retrans" "ac_cv_member_struct___res_state_retrans" " #include #if HAVE_SYS_TYPES_H # include #endif #include #include #include " if test "x$ac_cv_member_struct___res_state_retrans" = xyes then : else $as_nop printf "%s\n" "#define __res_state state" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" " #include #include #include " if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes then : printf "%s\n" "#define SOCK_HAS_LEN 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ss_family field in struct sockaddr_storage" >&5 printf %s "checking for ss_family field in struct sockaddr_storage... " >&6; } if test ${ac_cv_have_ss_family_in_struct_ss+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct sockaddr_storage s; s.ss_family = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_ss_family_in_struct_ss="yes" else $as_nop ac_cv_have_ss_family_in_struct_ss="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ss_family_in_struct_ss" >&5 printf "%s\n" "$ac_cv_have_ss_family_in_struct_ss" >&6; } if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then printf "%s\n" "#define HAVE_SS_FAMILY_IN_SS 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __ss_family field in struct sockaddr_storage" >&5 printf %s "checking for __ss_family field in struct sockaddr_storage... " >&6; } if test ${ac_cv_have___ss_family_in_struct_ss+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct sockaddr_storage s; s.__ss_family = 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have___ss_family_in_struct_ss="yes" else $as_nop ac_cv_have___ss_family_in_struct_ss="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___ss_family_in_struct_ss" >&5 printf "%s\n" "$ac_cv_have___ss_family_in_struct_ss" >&6; } if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then printf "%s\n" "#define HAVE___SS_FAMILY_IN_SS 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for msg_accrights field in struct msghdr" >&5 printf %s "checking for msg_accrights field in struct msghdr... " >&6; } if test ${ac_cv_have_accrights_in_msghdr+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main (void) { #ifdef msg_accrights #error "msg_accrights is a macro" exit(1); #endif struct msghdr m; m.msg_accrights = 0; exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_accrights_in_msghdr="yes" else $as_nop ac_cv_have_accrights_in_msghdr="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_accrights_in_msghdr" >&5 printf "%s\n" "$ac_cv_have_accrights_in_msghdr" >&6; } if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then printf "%s\n" "#define HAVE_ACCRIGHTS_IN_MSGHDR 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if struct statvfs.f_fsid is integral type" >&5 printf %s "checking if struct statvfs.f_fsid is integral type... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif int main (void) { struct statvfs s; s.f_fsid = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if fsid_t has member val" >&5 printf %s "checking if fsid_t has member val... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { fsid_t t; t.val[0] = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define FSID_HAS_VAL 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if f_fsid has member __val" >&5 printf %s "checking if f_fsid has member __val... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { fsid_t t; t.__val[0] = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define FSID_HAS___VAL 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for msg_control field in struct msghdr" >&5 printf %s "checking for msg_control field in struct msghdr... " >&6; } if test ${ac_cv_have_control_in_msghdr+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main (void) { #ifdef msg_control #error "msg_control is a macro" exit(1); #endif struct msghdr m; m.msg_control = 0; exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_have_control_in_msghdr="yes" else $as_nop ac_cv_have_control_in_msghdr="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_control_in_msghdr" >&5 printf "%s\n" "$ac_cv_have_control_in_msghdr" >&6; } if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then printf "%s\n" "#define HAVE_CONTROL_IN_MSGHDR 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libc defines __progname" >&5 printf %s "checking if libc defines __progname... " >&6; } if test ${ac_cv_libc_defines___progname+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { extern char *__progname; printf("%s", __progname); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_libc_defines___progname="yes" else $as_nop ac_cv_libc_defines___progname="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines___progname" >&5 printf "%s\n" "$ac_cv_libc_defines___progname" >&6; } if test "x$ac_cv_libc_defines___progname" = "xyes" ; then printf "%s\n" "#define HAVE___PROGNAME 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __FUNCTION__" >&5 printf %s "checking whether $CC implements __FUNCTION__... " >&6; } if test ${ac_cv_cc_implements___FUNCTION__+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { printf("%s", __FUNCTION__); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_cc_implements___FUNCTION__="yes" else $as_nop ac_cv_cc_implements___FUNCTION__="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___FUNCTION__" >&5 printf "%s\n" "$ac_cv_cc_implements___FUNCTION__" >&6; } if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then printf "%s\n" "#define HAVE___FUNCTION__ 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __func__" >&5 printf %s "checking whether $CC implements __func__... " >&6; } if test ${ac_cv_cc_implements___func__+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { printf("%s", __func__); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_cc_implements___func__="yes" else $as_nop ac_cv_cc_implements___func__="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___func__" >&5 printf "%s\n" "$ac_cv_cc_implements___func__" >&6; } if test "x$ac_cv_cc_implements___func__" = "xyes" ; then printf "%s\n" "#define HAVE___func__ 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether va_copy exists" >&5 printf %s "checking whether va_copy exists... " >&6; } if test ${ac_cv_have_va_copy+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include va_list x,y; int main (void) { va_copy(x,y); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_have_va_copy="yes" else $as_nop ac_cv_have_va_copy="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_va_copy" >&5 printf "%s\n" "$ac_cv_have_va_copy" >&6; } if test "x$ac_cv_have_va_copy" = "xyes" ; then printf "%s\n" "#define HAVE_VA_COPY 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether __va_copy exists" >&5 printf %s "checking whether __va_copy exists... " >&6; } if test ${ac_cv_have___va_copy+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include va_list x,y; int main (void) { __va_copy(x,y); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_have___va_copy="yes" else $as_nop ac_cv_have___va_copy="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___va_copy" >&5 printf "%s\n" "$ac_cv_have___va_copy" >&6; } if test "x$ac_cv_have___va_copy" = "xyes" ; then printf "%s\n" "#define HAVE___VA_COPY 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether getopt has optreset support" >&5 printf %s "checking whether getopt has optreset support... " >&6; } if test ${ac_cv_have_getopt_optreset+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { extern int optreset; optreset = 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_have_getopt_optreset="yes" else $as_nop ac_cv_have_getopt_optreset="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_getopt_optreset" >&5 printf "%s\n" "$ac_cv_have_getopt_optreset" >&6; } if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then printf "%s\n" "#define HAVE_GETOPT_OPTRESET 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_errlist" >&5 printf %s "checking if libc defines sys_errlist... " >&6; } if test ${ac_cv_libc_defines_sys_errlist+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_libc_defines_sys_errlist="yes" else $as_nop ac_cv_libc_defines_sys_errlist="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_errlist" >&5 printf "%s\n" "$ac_cv_libc_defines_sys_errlist" >&6; } if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then printf "%s\n" "#define HAVE_SYS_ERRLIST 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_nerr" >&5 printf %s "checking if libc defines sys_nerr... " >&6; } if test ${ac_cv_libc_defines_sys_nerr+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { extern int sys_nerr; printf("%i", sys_nerr); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_libc_defines_sys_nerr="yes" else $as_nop ac_cv_libc_defines_sys_nerr="no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_nerr" >&5 printf "%s\n" "$ac_cv_libc_defines_sys_nerr" >&6; } if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then printf "%s\n" "#define HAVE_SYS_NERR 1" >>confdefs.h fi # Check libraries needed by DNS fingerprint support { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing getrrsetbyname" >&5 printf %s "checking for library containing getrrsetbyname... " >&6; } if test ${ac_cv_search_getrrsetbyname+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char getrrsetbyname (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_getrrsetbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_getrrsetbyname+y} then : break fi done if test ${ac_cv_search_getrrsetbyname+y} then : else $as_nop ac_cv_search_getrrsetbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getrrsetbyname" >&5 printf "%s\n" "$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" printf "%s\n" "#define HAVE_GETRRSETBYNAME 1" >>confdefs.h else $as_nop # Needed by our getrrsetbyname() { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing res_query" >&5 printf %s "checking for library containing res_query... " >&6; } if test ${ac_cv_search_res_query+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char res_query (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_res_query=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_res_query+y} then : break fi done if test ${ac_cv_search_res_query+y} then : else $as_nop ac_cv_search_res_query=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_res_query" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5 printf %s "checking for library containing dn_expand... " >&6; } if test ${ac_cv_search_dn_expand+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dn_expand (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_dn_expand=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_dn_expand+y} then : break fi done if test ${ac_cv_search_dn_expand+y} then : else $as_nop ac_cv_search_dn_expand=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if res_query will link" >&5 printf %s "checking if res_query will link... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include int main (void) { res_query (0, 0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } saved_LIBS="$LIBS" LIBS="$LIBS -lresolv" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5 printf %s "checking for res_query in -lresolv... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include int main (void) { res_query (0, 0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop LIBS="$saved_LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_fn_c_check_func "$LINENO" "_getshort" "ac_cv_func__getshort" if test "x$ac_cv_func__getshort" = xyes then : printf "%s\n" "#define HAVE__GETSHORT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "_getlong" "ac_cv_func__getlong" if test "x$ac_cv_func__getlong" = xyes then : printf "%s\n" "#define HAVE__GETLONG 1" >>confdefs.h fi ac_fn_check_decl "$LINENO" "_getshort" "ac_cv_have_decl__getshort" "#include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl__getshort" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL__GETSHORT $ac_have_decl" >>confdefs.h ac_fn_check_decl "$LINENO" "_getlong" "ac_cv_have_decl__getlong" "#include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl__getlong" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL__GETLONG $ac_have_decl" >>confdefs.h ac_fn_c_check_member "$LINENO" "HEADER" "ad" "ac_cv_member_HEADER_ad" "#include " if test "x$ac_cv_member_HEADER_ad" = xyes then : printf "%s\n" "#define HAVE_HEADER_AD 1" >>confdefs.h fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if struct __res_state _res is an extern" >&5 printf %s "checking if struct __res_state _res is an extern... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if HAVE_SYS_TYPES_H # include #endif #include #include #include extern struct __res_state _res; int main (void) { struct __res_state *volatile p = &_res; /* force resolution of _res */ return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE__RES_EXTERN 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ 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+y} then : withval=$with_selinux; if test "x$withval" != "xno" ; then save_LIBS="$LIBS" printf "%s\n" "#define WITH_SELINUX 1" >>confdefs.h SELINUX_MSG="yes" ac_fn_c_check_header_compile "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default" if test "x$ac_cv_header_selinux_selinux_h" = xyes then : else $as_nop as_fn_error $? "SELinux support requires selinux.h header" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setexeccon in -lselinux" >&5 printf %s "checking for setexeccon in -lselinux... " >&6; } if test ${ac_cv_lib_selinux_setexeccon+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lselinux $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char setexeccon (); int main (void) { return setexeccon (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_selinux_setexeccon=yes else $as_nop ac_cv_lib_selinux_setexeccon=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_setexeccon" >&5 printf "%s\n" "$ac_cv_lib_selinux_setexeccon" >&6; } if test "x$ac_cv_lib_selinux_setexeccon" = xyes then : LIBSELINUX="-lselinux" LIBS="$LIBS -lselinux" else $as_nop as_fn_error $? "SELinux support requires libselinux library" "$LINENO" 5 fi ac_fn_c_check_func "$LINENO" "getseuserbyname" "ac_cv_func_getseuserbyname" if test "x$ac_cv_func_getseuserbyname" = xyes then : printf "%s\n" "#define HAVE_GETSEUSERBYNAME 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "get_default_context_with_level" "ac_cv_func_get_default_context_with_level" if test "x$ac_cv_func_get_default_context_with_level" = xyes then : printf "%s\n" "#define HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL 1" >>confdefs.h fi LIBS="$save_LIBS $LIBSELINUX" fi fi # Check whether user wants Kerberos 5 support KRB5_MSG="no" # Check whether --with-kerberos5 was given. if test ${with_kerberos5+y} then : withval=$with_kerberos5; if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then KRB5ROOT="/usr/local" else KRB5ROOT=${withval} fi printf "%s\n" "#define KRB5 1" >>confdefs.h KRB5_MSG="yes" use_pkgconfig_for_krb5= if test "x$PKGCONFIG" != "xno"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about kerberos5" >&5 printf %s "checking if $PKGCONFIG knows about kerberos5... " >&6; } if "$PKGCONFIG" krb5; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } use_pkgconfig_for_krb5=yes else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test "x$use_pkgconfig_for_krb5" = "xyes"; then K5CFLAGS=`$PKGCONFIG --cflags krb5` K5LIBS=`$PKGCONFIG --libs krb5` CPPFLAGS="$CPPFLAGS $K5CFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5 printf %s "checking for gssapi support... " >&6; } if "$PKGCONFIG" krb5-gssapi; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define GSSAPI 1" >>confdefs.h GSSCFLAGS="`$PKGCONFIG --cflags krb5-gssapi`" GSSLIBS="`$PKGCONFIG --libs krb5-gssapi`" CPPFLAGS="$CPPFLAGS $GSSCFLAGS" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 printf %s "checking whether we are using Heimdal... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { char *tmp = heimdal_version; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HEIMDAL 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext else if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}krb5-config", so it can be a program name with args. set dummy ${ac_tool_prefix}krb5-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_KRB5CONF+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_KRB5CONF="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi KRB5CONF=$ac_cv_path_KRB5CONF if test -n "$KRB5CONF"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $KRB5CONF" >&5 printf "%s\n" "$KRB5CONF" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_KRB5CONF"; then ac_pt_KRB5CONF=$KRB5CONF # Extract the first word of "krb5-config", so it can be a program name with args. set dummy krb5-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_KRB5CONF+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_KRB5CONF in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_KRB5CONF="$ac_pt_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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_KRB5CONF="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_KRB5CONF=$ac_cv_path_ac_pt_KRB5CONF if test -n "$ac_pt_KRB5CONF"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_KRB5CONF" >&5 printf "%s\n" "$ac_pt_KRB5CONF" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_KRB5CONF" = x; then KRB5CONF="$KRB5ROOT/bin/krb5-config" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac KRB5CONF=$ac_pt_KRB5CONF fi else KRB5CONF="$ac_cv_path_KRB5CONF" fi if test -x $KRB5CONF ; then K5CFLAGS="`$KRB5CONF --cflags`" K5LIBS="`$KRB5CONF --libs`" CPPFLAGS="$CPPFLAGS $K5CFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5 printf %s "checking for gssapi support... " >&6; } if $KRB5CONF | grep gssapi >/dev/null ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define GSSAPI 1" >>confdefs.h GSSCFLAGS="`$KRB5CONF --cflags gssapi`" GSSLIBS="`$KRB5CONF --libs gssapi`" CPPFLAGS="$CPPFLAGS $GSSCFLAGS" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 printf %s "checking whether we are using Heimdal... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { char *tmp = heimdal_version; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HEIMDAL 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext else CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 printf %s "checking whether we are using Heimdal... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { char *tmp = heimdal_version; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HEIMDAL 1" >>confdefs.h K5LIBS="-lkrb5" K5LIBS="$K5LIBS -lcom_err -lasn1" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for net_write in -lroken" >&5 printf %s "checking for net_write in -lroken... " >&6; } if test ${ac_cv_lib_roken_net_write+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lroken $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char net_write (); int main (void) { return net_write (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_roken_net_write=yes else $as_nop ac_cv_lib_roken_net_write=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_roken_net_write" >&5 printf "%s\n" "$ac_cv_lib_roken_net_write" >&6; } if test "x$ac_cv_lib_roken_net_write" = xyes then : K5LIBS="$K5LIBS -lroken" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for des_cbc_encrypt in -ldes" >&5 printf %s "checking for des_cbc_encrypt in -ldes... " >&6; } if test ${ac_cv_lib_des_des_cbc_encrypt+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldes $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char des_cbc_encrypt (); int main (void) { return des_cbc_encrypt (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_des_des_cbc_encrypt=yes else $as_nop ac_cv_lib_des_des_cbc_encrypt=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_des_des_cbc_encrypt" >&5 printf "%s\n" "$ac_cv_lib_des_des_cbc_encrypt" >&6; } if test "x$ac_cv_lib_des_des_cbc_encrypt" = xyes then : K5LIBS="$K5LIBS -ldes" fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } K5LIBS="-lkrb5 -lk5crypto -lcom_err" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5 printf %s "checking for library containing dn_expand... " >&6; } if test ${ac_cv_search_dn_expand+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dn_expand (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_dn_expand=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_dn_expand+y} then : break fi done if test ${ac_cv_search_dn_expand+y} then : else $as_nop ac_cv_search_dn_expand=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi_krb5" >&5 printf %s "checking for gss_init_sec_context in -lgssapi_krb5... " >&6; } if test ${ac_cv_lib_gssapi_krb5_gss_init_sec_context+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lgssapi_krb5 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gss_init_sec_context (); int main (void) { return gss_init_sec_context (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_gssapi_krb5_gss_init_sec_context=yes else $as_nop ac_cv_lib_gssapi_krb5_gss_init_sec_context=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&5 printf "%s\n" "$ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&6; } if test "x$ac_cv_lib_gssapi_krb5_gss_init_sec_context" = xyes then : printf "%s\n" "#define GSSAPI 1" >>confdefs.h GSSLIBS="-lgssapi_krb5" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi" >&5 printf %s "checking for gss_init_sec_context in -lgssapi... " >&6; } if test ${ac_cv_lib_gssapi_gss_init_sec_context+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lgssapi $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gss_init_sec_context (); int main (void) { return gss_init_sec_context (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_gssapi_gss_init_sec_context=yes else $as_nop ac_cv_lib_gssapi_gss_init_sec_context=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5 printf "%s\n" "$ac_cv_lib_gssapi_gss_init_sec_context" >&6; } if test "x$ac_cv_lib_gssapi_gss_init_sec_context" = xyes then : printf "%s\n" "#define GSSAPI 1" >>confdefs.h GSSLIBS="-lgssapi" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgss" >&5 printf %s "checking for gss_init_sec_context in -lgss... " >&6; } if test ${ac_cv_lib_gss_gss_init_sec_context+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lgss $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gss_init_sec_context (); int main (void) { return gss_init_sec_context (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_gss_gss_init_sec_context=yes else $as_nop ac_cv_lib_gss_gss_init_sec_context=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gss_gss_init_sec_context" >&5 printf "%s\n" "$ac_cv_lib_gss_gss_init_sec_context" >&6; } if test "x$ac_cv_lib_gss_gss_init_sec_context" = xyes then : printf "%s\n" "#define GSSAPI 1" >>confdefs.h GSSLIBS="-lgss" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api library - build may fail" >&5 printf "%s\n" "$as_me: WARNING: Cannot find any suitable gss-api library - build may fail" >&2;} fi fi fi ac_fn_c_check_header_compile "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_h" = xyes then : else $as_nop unset ac_cv_header_gssapi_h CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" for ac_header in gssapi.h do : ac_fn_c_check_header_compile "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_h" = xyes then : printf "%s\n" "#define HAVE_GSSAPI_H 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api header - build may fail" >&5 printf "%s\n" "$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" ac_fn_c_check_header_compile "$LINENO" "gssapi_krb5.h" "ac_cv_header_gssapi_krb5_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_krb5_h" = xyes then : else $as_nop CPPFLAGS="$oldCPP" fi fi fi if test -n "${rpath_opt}" ; then LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib" fi if test ! -z "$blibpath" ; then blibpath="$blibpath:${KRB5ROOT}/lib" fi ac_fn_c_check_header_compile "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_h" = xyes then : printf "%s\n" "#define HAVE_GSSAPI_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi.h" "ac_cv_header_gssapi_gssapi_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_gssapi_h" = xyes then : printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "gssapi_krb5.h" "ac_cv_header_gssapi_krb5_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_krb5_h" = xyes then : printf "%s\n" "#define HAVE_GSSAPI_KRB5_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi_krb5.h" "ac_cv_header_gssapi_gssapi_krb5_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_gssapi_krb5_h" = xyes then : printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_KRB5_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "gssapi_generic.h" "ac_cv_header_gssapi_generic_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_generic_h" = xyes then : printf "%s\n" "#define HAVE_GSSAPI_GENERIC_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi_generic.h" "ac_cv_header_gssapi_gssapi_generic_h" "$ac_includes_default" if test "x$ac_cv_header_gssapi_gssapi_generic_h" = xyes then : printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_GENERIC_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing k_hasafs" >&5 printf %s "checking for library containing k_hasafs... " >&6; } if test ${ac_cv_search_k_hasafs+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char k_hasafs (); int main (void) { 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 if ac_fn_c_try_link "$LINENO" then : ac_cv_search_k_hasafs=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_k_hasafs+y} then : break fi done if test ${ac_cv_search_k_hasafs+y} then : else $as_nop ac_cv_search_k_hasafs=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_k_hasafs" >&5 printf "%s\n" "$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" printf "%s\n" "#define USE_AFS 1" >>confdefs.h fi ac_fn_check_decl "$LINENO" "GSS_C_NT_HOSTBASED_SERVICE" "ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" " #ifdef HAVE_GSSAPI_H # include #elif defined(HAVE_GSSAPI_GSSAPI_H) # include #endif #ifdef HAVE_GSSAPI_GENERIC_H # include #elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) # include #endif " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi printf "%s\n" "#define HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE $ac_have_decl" >>confdefs.h saved_LIBS="$LIBS" LIBS="$LIBS $K5LIBS" ac_fn_c_check_func "$LINENO" "krb5_cc_new_unique" "ac_cv_func_krb5_cc_new_unique" if test "x$ac_cv_func_krb5_cc_new_unique" = xyes then : printf "%s\n" "#define HAVE_KRB5_CC_NEW_UNIQUE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "krb5_get_error_message" "ac_cv_func_krb5_get_error_message" if test "x$ac_cv_func_krb5_get_error_message" = xyes then : printf "%s\n" "#define HAVE_KRB5_GET_ERROR_MESSAGE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "krb5_free_error_message" "ac_cv_func_krb5_free_error_message" if test "x$ac_cv_func_krb5_free_error_message" = xyes then : printf "%s\n" "#define HAVE_KRB5_FREE_ERROR_MESSAGE 1" >>confdefs.h fi 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+y} 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+y} then : withval=$with_xauth; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then xauth_path=$withval fi else $as_nop 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_xauth_path+y} then : printf %s "(cached) " >&6 else $as_nop 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_xauth_path="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $xauth_path" >&5 printf "%s\n" "$xauth_path" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "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+y} then : enableval=$enable_strip; if test "x$enableval" = "xno" ; then STRIP_OPT= fi fi if test -z "$xauth_path" ; then XAUTH_PATH="undefined" else printf "%s\n" "#define XAUTH_PATH \"$xauth_path\"" >>confdefs.h XAUTH_PATH=$xauth_path fi # Check for mail directory # Check whether --with-maildir was given. if test ${with_maildir+y} then : withval=$with_maildir; if test "X$withval" != X && test "x$withval" != xno && \ test "x${withval}" != xyes; then printf "%s\n" "#define MAIL_DIRECTORY \"$withval\"" >>confdefs.h fi else $as_nop if test "X$maildir" != "X"; then printf "%s\n" "#define MAIL_DIRECTORY \"$maildir\"" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking Discovering system mail directory" >&5 printf %s "checking Discovering system mail directory... " >&6; } if test "$cross_compiling" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&5 printf "%s\n" "$as_me: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&2;} else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_MAILLOCK_H #include #endif #define DATA "conftest.maildir" int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : maildir_what=`awk -F: '{print $1}' conftest.maildir` maildir=`awk -F: '{print $2}' conftest.maildir \ | sed 's|/$||'` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using: $maildir from $maildir_what" >&5 printf "%s\n" "Using: $maildir from $maildir_what" >&6; } if test "x$maildir_what" != "x_PATH_MAILDIR"; then printf "%s\n" "#define MAIL_DIRECTORY \"$maildir\"" >>confdefs.h fi else $as_nop if test "X$ac_status" = "X2";then # our test program didn't find it. Default to /var/spool/mail { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using: default value of /var/spool/mail" >&5 printf "%s\n" "Using: default value of /var/spool/mail" >&6; } printf "%s\n" "#define MAIL_DIRECTORY \"/var/spool/mail\"" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: *** not found ***" >&5 printf "%s\n" "*** not found ***" >&6; } fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi # maildir if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptmx test" >&5 printf "%s\n" "$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 as_ac_File=`printf "%s\n" "ac_cv_file_"/dev/ptmx"" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptmx\"" >&5 printf %s "checking for \"/dev/ptmx\"... " >&6; } if eval test \${$as_ac_File+y} then : printf %s "(cached) " >&6 else $as_nop test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r ""/dev/ptmx""; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi eval ac_res=\$$as_ac_File { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_File"\" = x"yes" then : printf "%s\n" "#define HAVE_DEV_PTMX 1" >>confdefs.h have_dev_ptmx=1 fi fi fi if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then as_ac_File=`printf "%s\n" "ac_cv_file_"/dev/ptc"" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptc\"" >&5 printf %s "checking for \"/dev/ptc\"... " >&6; } if eval test \${$as_ac_File+y} then : printf %s "(cached) " >&6 else $as_nop test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r ""/dev/ptc""; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi eval ac_res=\$$as_ac_File { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_File"\" = x"yes" then : printf "%s\n" "#define HAVE_DEV_PTS_AND_PTC 1" >>confdefs.h have_dev_ptc=1 fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptc test" >&5 printf "%s\n" "$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+y} then : withval=$with_mantype; case "$withval" in man|cat|doc) MANTYPE=$withval ;; *) as_fn_error $? "invalid man type: $withval" "$LINENO" 5 ;; esac fi if test -z "$MANTYPE"; then if ${MANDOC} ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=doc elif ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=doc elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=man else MANTYPE=cat fi fi if test "$MANTYPE" = "doc"; then mansubdir=man; else mansubdir=$MANTYPE; fi # Whether to disable shadow password support # Check whether --with-shadow was given. if test ${with_shadow+y} then : withval=$with_shadow; if test "x$withval" = "xno" ; then printf "%s\n" "#define DISABLE_SHADOW 1" >>confdefs.h disable_shadow=yes fi fi if test -z "$disable_shadow" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the systems has expire shadow information" >&5 printf %s "checking if the systems has expire shadow information... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct spwd sp; int main (void) { sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : sp_expire_available=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test "x$sp_expire_available" = "xyes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAS_SHADOW_EXPIRE 1" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi # Use ip address instead of hostname in $DISPLAY if test ! -z "$IPADDR_IN_DISPLAY" ; then DISPLAY_HACK_MSG="yes" printf "%s\n" "#define IPADDR_IN_DISPLAY 1" >>confdefs.h else DISPLAY_HACK_MSG="no" # Check whether --with-ipaddr-display was given. if test ${with_ipaddr_display+y} then : withval=$with_ipaddr_display; if test "x$withval" != "xno" ; then printf "%s\n" "#define IPADDR_IN_DISPLAY 1" >>confdefs.h 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+y} then : enableval=$enable_etc_default_login; if test "x$enableval" = "xno"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: /etc/default/login handling disabled" >&5 printf "%s\n" "$as_me: /etc/default/login handling disabled" >&6;} etc_default_login=no else etc_default_login=yes fi else $as_nop if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking /etc/default/login" >&5 printf "%s\n" "$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 as_ac_File=`printf "%s\n" "ac_cv_file_"/etc/default/login"" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for \"/etc/default/login\"" >&5 printf %s "checking for \"/etc/default/login\"... " >&6; } if eval test \${$as_ac_File+y} then : printf %s "(cached) " >&6 else $as_nop test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r ""/etc/default/login""; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi eval ac_res=\$$as_ac_File { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_File"\" = x"yes" then : external_path_file=/etc/default/login fi if test "x$external_path_file" = "x/etc/default/login"; then printf "%s\n" "#define HAVE_ETC_DEFAULT_LOGIN 1" >>confdefs.h 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+y} then : withval=$with_default_path; if test "x$external_path_file" = "x/etc/login.conf" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-default-path=PATH has no effect on this system. Edit /etc/login.conf instead." >&5 printf "%s\n" "$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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-default-path=PATH will only be used if PATH is not defined in $external_path_file ." >&5 printf "%s\n" "$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 $as_nop if test "x$external_path_file" = "x/etc/login.conf" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Make sure the path to scp is in /etc/login.conf" >&5 printf "%s\n" "$as_me: WARNING: Make sure the path to scp is in /etc/login.conf" >&2;} else if test ! -z "$external_path_file" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: If PATH is defined in $external_path_file, ensure the path to scp is included, otherwise scp will not work." >&5 printf "%s\n" "$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 $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* find out what STDPATH is */ #include #include #ifdef HAVE_PATHS_H # include #endif #ifndef _PATH_STDPATH # ifdef _PATH_USERPATH /* Irix */ # define _PATH_STDPATH _PATH_USERPATH # else # define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" # endif #endif #include #include #include #define DATA "conftest.stdpath" int main (void) { 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 if ac_fn_c_try_run "$LINENO" then : user_path=`cat conftest.stdpath` else $as_nop 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.beam 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Adding $t_bindir to USER_PATH so scp will work" >&5 printf "%s\n" "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 printf "%s\n" "#define USER_PATH \"$user_path\"" >>confdefs.h fi # Set superuser path separately to user path # Check whether --with-superuser-path was given. if test ${with_superuser_path+y} then : withval=$with_superuser_path; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then printf "%s\n" "#define SUPERUSER_PATH \"$withval\"" >>confdefs.h superuser_path=$withval fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we need to convert IPv4 in IPv6-mapped addresses" >&5 printf %s "checking if we need to convert IPv4 in IPv6-mapped addresses... " >&6; } IPV4_IN6_HACK_MSG="no" # Check whether --with-4in6 was given. if test ${with_4in6+y} then : withval=$with_4in6; if test "x$withval" != "xno" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define IPV4_IN_IPV6 1" >>confdefs.h IPV4_IN6_HACK_MSG="yes" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else $as_nop if test "x$inet6_default_4in6" = "xyes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 printf "%s\n" "yes (default)" >&6; } printf "%s\n" "#define IPV4_IN_IPV6 1" >>confdefs.h IPV4_IN6_HACK_MSG="yes" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no (default)" >&5 printf "%s\n" "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+y} then : withval=$with_bsd_auth; if test "x$withval" != "xno" ; then printf "%s\n" "#define BSD_AUTH 1" >>confdefs.h 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+y} 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ** no $piddir directory on this system **" >&5 printf "%s\n" "$as_me: WARNING: ** no $piddir directory on this system **" >&2;} fi fi fi printf "%s\n" "#define _PATH_SSH_PIDDIR \"$piddir\"" >>confdefs.h # Check whether --enable-fd-passing was given. if test ${enable_fd_passing+y} then : enableval=$enable_fd_passing; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h fi fi # Check whether --enable-lastlog was given. if test ${enable_lastlog+y} then : enableval=$enable_lastlog; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h fi fi # Check whether --enable-utmp was given. if test ${enable_utmp+y} then : enableval=$enable_utmp; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h fi fi # Check whether --enable-utmpx was given. if test ${enable_utmpx+y} then : enableval=$enable_utmpx; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h fi fi # Check whether --enable-wtmp was given. if test ${enable_wtmp+y} then : enableval=$enable_wtmp; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h fi fi # Check whether --enable-wtmpx was given. if test ${enable_wtmpx+y} then : enableval=$enable_wtmpx; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_WTMPX 1" >>confdefs.h fi fi # Check whether --enable-libutil was given. if test ${enable_libutil+y} then : enableval=$enable_libutil; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_LOGIN 1" >>confdefs.h fi fi # Check whether --enable-pututline was given. if test ${enable_pututline+y} then : enableval=$enable_pututline; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_PUTUTLINE 1" >>confdefs.h fi fi # Check whether --enable-pututxline was given. if test ${enable_pututxline+y} then : enableval=$enable_pututxline; if test "x$enableval" = "xno" ; then printf "%s\n" "#define DISABLE_PUTUTXLINE 1" >>confdefs.h fi fi # Check whether --with-lastlog was given. if test ${with_lastlog+y} then : withval=$with_lastlog; if test "x$withval" = "xno" ; then printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h elif test -n "$withval" && test "x${withval}" != "xyes"; then conf_lastlog_location=$withval fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines LASTLOG_FILE" >&5 printf %s "checking if your system defines LASTLOG_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_LOGIN_H # include #endif int main (void) { char *lastlog = LASTLOG_FILE; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines _PATH_LASTLOG" >&5 printf %s "checking if your system defines _PATH_LASTLOG... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif int main (void) { char *lastlog = _PATH_LASTLOG; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } system_lastlog_path=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ** Cannot find lastlog **" >&5 printf "%s\n" "$as_me: WARNING: ** Cannot find lastlog **" >&2;} fi fi fi if test -n "$conf_lastlog_location"; then printf "%s\n" "#define CONF_LASTLOG_FILE \"$conf_lastlog_location\"" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines UTMP_FILE" >&5 printf %s "checking if your system defines UTMP_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_PATHS_H # include #endif int main (void) { char *utmp = UTMP_FILE; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } system_utmp_path=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam 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 printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h fi fi fi if test -n "$conf_utmp_location"; then printf "%s\n" "#define CONF_UTMP_FILE \"$conf_utmp_location\"" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMP_FILE" >&5 printf %s "checking if your system defines WTMP_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_PATHS_H # include #endif int main (void) { char *wtmp = WTMP_FILE; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } system_wtmp_path=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam 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 printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h fi fi fi if test -n "$conf_wtmp_location"; then printf "%s\n" "#define CONF_WTMP_FILE \"$conf_wtmp_location\"" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMPX_FILE" >&5 printf %s "checking if your system defines WTMPX_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_PATHS_H # include #endif int main (void) { char *wtmpx = WTMPX_FILE; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } system_wtmpx_path=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test -z "$conf_wtmpx_location"; then if test x"$system_wtmpx_path" = x"no" ; then printf "%s\n" "#define DISABLE_WTMPX 1" >>confdefs.h fi else printf "%s\n" "#define CONF_WTMPX_FILE \"$conf_wtmpx_location\"" >>confdefs.h fi if test ! -z "$blibpath" ; then LDFLAGS="$LDFLAGS $blibflags$blibpath" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&5 printf "%s\n" "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;} fi ac_fn_c_check_member "$LINENO" "struct lastlog" "ll_line" "ac_cv_member_struct_lastlog_ll_line" " #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_LASTLOG_H #include #endif " if test "x$ac_cv_member_struct_lastlog_ll_line" = xyes then : else $as_nop if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h fi fi ac_fn_c_check_member "$LINENO" "struct utmp" "ut_line" "ac_cv_member_struct_utmp_ut_line" " #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_LASTLOG_H #include #endif " if test "x$ac_cv_member_struct_utmp_ut_line" = xyes then : else $as_nop printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h fi CFLAGS="$CFLAGS $werror_flags" if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then TEST_SSH_IPV6=no else TEST_SSH_IPV6=yes fi ac_fn_check_decl "$LINENO" "BROKEN_GETADDRINFO" "ac_cv_have_decl_BROKEN_GETADDRINFO" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_BROKEN_GETADDRINFO" = xyes then : TEST_SSH_IPV6=no fi TEST_SSH_IPV6=$TEST_SSH_IPV6 TEST_SSH_UTF8=$TEST_SSH_UTF8 TEST_MALLOC_OPTIONS=$TEST_MALLOC_OPTIONS UNSUPPORTED_ALGORITHMS=$unsupported_algorithms DEPEND=$(cat $srcdir/.depend) # Binaries for interop tests. # Extract the first word of "plink", so it can be a program name with args. set dummy plink; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PLINK+y} then : printf %s "(cached) " >&6 else $as_nop case $PLINK in [\\/]* | ?:[\\/]*) ac_cv_path_PLINK="$PLINK" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PLINK="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PLINK=$ac_cv_path_PLINK if test -n "$PLINK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PLINK" >&5 printf "%s\n" "$PLINK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "puttygen", so it can be a program name with args. set dummy puttygen; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PUTTYGEN+y} then : printf %s "(cached) " >&6 else $as_nop case $PUTTYGEN in [\\/]* | ?:[\\/]*) ac_cv_path_PUTTYGEN="$PUTTYGEN" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PUTTYGEN="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PUTTYGEN=$ac_cv_path_PUTTYGEN if test -n "$PUTTYGEN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PUTTYGEN" >&5 printf "%s\n" "$PUTTYGEN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "conch", so it can be a program name with args. set dummy conch; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_CONCH+y} then : printf %s "(cached) " >&6 else $as_nop case $CONCH in [\\/]* | ?:[\\/]*) ac_cv_path_CONCH="$CONCH" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_CONCH="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi CONCH=$ac_cv_path_CONCH if test -n "$CONCH"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CONCH" >&5 printf "%s\n" "$CONCH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "dropbear", so it can be a program name with args. set dummy dropbear; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_DROPBEAR+y} then : printf %s "(cached) " >&6 else $as_nop case $DROPBEAR in [\\/]* | ?:[\\/]*) ac_cv_path_DROPBEAR="$DROPBEAR" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_DROPBEAR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi DROPBEAR=$ac_cv_path_DROPBEAR if test -n "$DROPBEAR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DROPBEAR" >&5 printf "%s\n" "$DROPBEAR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "dbclient", so it can be a program name with args. set dummy dbclient; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_DBCLIENT+y} then : printf %s "(cached) " >&6 else $as_nop case $DBCLIENT in [\\/]* | ?:[\\/]*) ac_cv_path_DBCLIENT="$DBCLIENT" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_DBCLIENT="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi DBCLIENT=$ac_cv_path_DBCLIENT if test -n "$DBCLIENT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DBCLIENT" >&5 printf "%s\n" "$DBCLIENT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "dropbearkey", so it can be a program name with args. set dummy dropbearkey; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_DROPBEARKEY+y} then : printf %s "(cached) " >&6 else $as_nop case $DROPBEARKEY in [\\/]* | ?:[\\/]*) ac_cv_path_DROPBEARKEY="$DROPBEARKEY" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_DROPBEARKEY="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi DROPBEARKEY=$ac_cv_path_DROPBEARKEY if test -n "$DROPBEARKEY"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DROPBEARKEY" >&5 printf "%s\n" "$DROPBEARKEY" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "dropbearconvert", so it can be a program name with args. set dummy dropbearconvert; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_DROPBEARCONVERT+y} then : printf %s "(cached) " >&6 else $as_nop case $DROPBEARCONVERT in [\\/]* | ?:[\\/]*) ac_cv_path_DROPBEARCONVERT="$DROPBEARCONVERT" # 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 case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_DROPBEARCONVERT="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi DROPBEARCONVERT=$ac_cv_path_DROPBEARCONVERT if test -n "$DROPBEARCONVERT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DROPBEARCONVERT" >&5 printf "%s\n" "$DROPBEARCONVERT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi CFLAGS="${CFLAGS} ${CFLAGS_AFTER}" LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}" # Make a copy of CFLAGS/LDFLAGS without PIE options. LDFLAGS_NOPIE=`echo "$LDFLAGS" | sed 's/^-pie //;s/ -pie//g'` CFLAGS_NOPIE=`echo "$CFLAGS" | sed 's/^-fPIE //;s/ -fPIE//g'` 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_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; 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+y} || &/ 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 if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$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= U= 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=`printf "%s\n" "$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. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $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} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac 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 printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith 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 if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # 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 # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' 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 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then 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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$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 || printf "%s\n" 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" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # 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 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=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.71. 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 case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent 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 ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ OpenSSH config.status Portable configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 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' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. 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=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= 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 ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$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. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append 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 || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # 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" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; 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+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || 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= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries 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[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # 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. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[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="$ac_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 || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append 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 '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; 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 || printf "%s\n" 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"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$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 ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # 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= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 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 || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;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 s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$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 "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # 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 || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} 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 " libedit support: $LIBEDIT_MSG" echo " libldns support: $LDNS_MSG" echo " Solaris process contract support: $SPC_MSG" echo " Solaris project support: $SP_MSG" echo " Solaris privilege support: $SPP_MSG" echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" echo " U2F/FIDO support: $enable_sk" echo "" echo " Host: ${host}" echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" echo " Libraries: ${LIBS}" if test ! -z "${CHANNELLIBS}"; then echo " +for channels: ${CHANNELLIBS}" fi if test ! -z "${LIBFIDO2}"; then echo " +for FIDO2: ${LIBFIDO2}" fi if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" fi echo "" if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then echo "SVR4 style packages are supported with \"make package\"" echo "" fi if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " echo "Example PAM control files can be found in the contrib/ " echo "subdirectory" echo "" fi if test ! -z "$NO_PEERCHECK" ; then echo "WARNING: the operating system that you are using does not" echo "appear to support getpeereid(), getpeerucred() or the" echo "SO_PEERCRED getsockopt() option. These facilities are used to" echo "enforce security checks to prevent unauthorised connections to" echo "ssh-agent. Their absence increases the risk that a malicious" echo "user can connect to your agent." echo "" fi if test "$AUDIT_MODULE" = "bsm" ; then echo "WARNING: BSM audit support is currently considered EXPERIMENTAL." echo "See the Solaris section in README.platform for details." fi openssh-10.0p1/PaxHeaders.10889/configure.ac100644 001750 001750 0000000003614775415623 0015442xustar0030 atime=1744182234.558422418 openssh-10.0p1/configure.ac010064400017500001750000004734741477541562300140500ustar00djmdjm# # Copyright (c) 1999-2004 Damien Miller # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([ssh.c]) # Check for stale configure as early as possible. for i in $srcdir/configure.ac $srcdir/m4/*.m4; do if test "$i" -nt "$srcdir/configure"; then AC_MSG_ERROR([$i newer than configure, run autoreconf]) fi done AC_LANG([C]) AC_CONFIG_HEADERS([config.h]) AC_PROG_CC([cc gcc clang]) # XXX relax this after reimplementing logit() etc. AC_MSG_CHECKING([if $CC supports C99-style variadic macros]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ int f(int a, int b, int c) { return a + b + c; } #define F(a, ...) f(a, __VA_ARGS__) ]], [[return F(1, 2, -3);]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_ERROR([*** OpenSSH requires support for C99-style variadic macros]) ] ) AC_CANONICAL_HOST AC_C_BIGENDIAN # Checks for programs. AC_PROG_AWK AC_PROG_CPP AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_EGREP AC_PROG_MKDIR_P AC_CHECK_TOOLS([AR], [ar]) AC_PATH_PROG([CAT], [cat]) AC_PATH_PROG([KILL], [kill]) AC_PATH_PROG([SED], [sed]) AC_PATH_PROG([TEST_MINUS_S_SH], [bash]) AC_PATH_PROG([TEST_MINUS_S_SH], [ksh]) AC_PATH_PROG([TEST_MINUS_S_SH], [sh]) AC_PATH_PROG([SH], [bash]) AC_PATH_PROG([SH], [ksh]) AC_PATH_PROG([SH], [sh]) AC_PATH_PROG([GROFF], [groff]) AC_PATH_PROG([NROFF], [nroff awf]) AC_PATH_PROG([MANDOC], [mandoc]) AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) AC_SUBST([TEST_SHELL], [sh]) dnl select manpage formatter to be used to build "cat" format pages. if test "x$MANDOC" != "x" ; then MANFMT="$MANDOC" elif test "x$NROFF" != "x" ; then MANFMT="$NROFF -mandoc" elif test "x$GROFF" != "x" ; then MANFMT="$GROFF -mandoc -Tascii" else AC_MSG_WARN([no manpage formatter found]) MANFMT="false" fi AC_SUBST([MANFMT]) dnl for buildpkg.sh AC_PATH_PROG([PATH_GROUPADD_PROG], [groupadd], [groupadd], [/usr/sbin${PATH_SEPARATOR}/etc]) AC_PATH_PROG([PATH_USERADD_PROG], [useradd], [useradd], [/usr/sbin${PATH_SEPARATOR}/etc]) AC_CHECK_PROG([MAKE_PACKAGE_SUPPORTED], [pkgmk], [yes], [no]) if test -x /sbin/sh; then AC_SUBST([STARTUP_SCRIPT_SHELL], [/sbin/sh]) else AC_SUBST([STARTUP_SCRIPT_SHELL], [/bin/sh]) fi # System features AC_SYS_LARGEFILE if test -z "$AR" ; then AC_MSG_ERROR([*** 'ar' missing, please install or fix your \$PATH ***]) fi AC_PATH_PROG([PATH_PASSWD_PROG], [passwd]) if test ! -z "$PATH_PASSWD_PROG" ; then AC_DEFINE_UNQUOTED([_PATH_PASSWD_PROG], ["$PATH_PASSWD_PROG"], [Full path of your "passwd" program]) fi dnl Since autoconf doesn't support it very well, we no longer allow users to dnl override LD, however keeping the hook here for now in case there's a use dnl use case we overlooked and someone needs to re-enable it. Unless a good dnl reason is found we'll be removing this in future. LD="$CC" AC_SUBST([LD]) AC_C_INLINE AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include ]) AC_CHECK_DECL([LONG_LONG_MAX], [have_long_long_max=1], , [#include ]) AC_CHECK_DECL([RLIMIT_NPROC], [AC_DEFINE([HAVE_RLIMIT_NPROC], [], [sys/resource.h has RLIMIT_NPROC])], , [ #include #include ]) AC_CHECK_DECL([PR_SET_NO_NEW_PRIVS], [have_linux_no_new_privs=1], , [ #include #include ]) openssl=yes openssl_bin=openssl AC_ARG_WITH([openssl], [ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ], [ if test "x$withval" = "xno" ; then openssl=no openssl_bin="" fi ] ) AC_MSG_CHECKING([whether OpenSSL will be used for cryptography]) if test "x$openssl" = "xyes" ; then AC_MSG_RESULT([yes]) AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography]) else AC_MSG_RESULT([no]) fi use_stack_protector=1 use_toolchain_hardening=1 use_retpoline=1 AC_ARG_WITH([stackprotect], [ --without-stackprotect Don't use compiler's stack protection], [ if test "x$withval" = "xno"; then use_stack_protector=0 fi ]) AC_ARG_WITH([hardening], [ --without-hardening Don't use toolchain hardening flags], [ if test "x$withval" = "xno"; then use_toolchain_hardening=0 fi ]) AC_ARG_WITH([retpoline], [ --without-retpoline Enable retpoline spectre mitigation], [ if test "x$withval" = "xno"; then use_retpoline=0 fi ]) # We use -Werror for the tests only so that we catch warnings like "this is # on by default" for things like -fPIE. AC_MSG_CHECKING([if $CC supports -Werror]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror" AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])], [ AC_MSG_RESULT([yes]) WERROR="-Werror"], [ AC_MSG_RESULT([no]) WERROR="" ] ) CFLAGS="$saved_CFLAGS" if test "$GCC" = "yes" || test "$GCC" = "egcs"; then AC_MSG_CHECKING([gcc version]) GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'` case "$GCC_VER" in 1.*) no_attrib_nonnull=1 ;; 2.8* | 2.9*) no_attrib_nonnull=1 ;; 2.*) no_attrib_nonnull=1 ;; *) ;; esac AC_MSG_RESULT([$GCC_VER]) AC_MSG_CHECKING([clang version]) ver="`$CC -v 2>&1`" if echo "$ver" | grep "Apple" >/dev/null; then CLANG_VER=apple-`echo "$ver" | grep 'clang version' | \ $SED 's/.*clang version //g' | $AWK '{print $1}'` else CLANG_VER=`echo "$ver" | grep 'clang version' | \ $SED 's/.*clang version //g' | $AWK '{print $1}'` fi AC_MSG_RESULT([$CLANG_VER]) OSSH_CHECK_CFLAG_COMPILE([-pipe]) OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option]) OSSH_CHECK_CFLAG_COMPILE([-Wno-error=format-truncation]) OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments]) OSSH_CHECK_CFLAG_COMPILE([-Wall]) OSSH_CHECK_CFLAG_COMPILE([-Wextra]) OSSH_CHECK_CFLAG_COMPILE([-Wpointer-arith]) OSSH_CHECK_CFLAG_COMPILE([-Wuninitialized]) OSSH_CHECK_CFLAG_COMPILE([-Wsign-compare]) OSSH_CHECK_CFLAG_COMPILE([-Wformat-security]) OSSH_CHECK_CFLAG_COMPILE([-Wsizeof-pointer-memaccess]) OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-parameter], [-Wno-unused-parameter]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result]) OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough]) OSSH_CHECK_CFLAG_COMPILE([-Wmisleading-indentation]) OSSH_CHECK_CFLAG_COMPILE([-Wbitwise-instead-of-logical]) OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing]) if test "x$use_toolchain_hardening" = "x1"; then OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack]) # NB. -ftrapv expects certain support functions to be present in # the compiler library (libgcc or similar) to detect integer operations # that can overflow. We must check that the result of enabling it # actually links. The test program compiled/linked includes a number # of integer operations that should exercise this. OSSH_CHECK_CFLAG_LINK([-ftrapv]) # clang 15 seems to have a bug in -fzero-call-used-regs=all. See # https://bugzilla.mindrot.org/show_bug.cgi?id=3475 and # https://github.com/llvm/llvm-project/issues/59242 # clang 17 has a different bug that causes an ICE when using this # flag at all (https://bugzilla.mindrot.org/show_bug.cgi?id=3629) case "$CLANG_VER" in apple-15*) OSSH_CHECK_CFLAG_LINK([-fzero-call-used-regs=used]) ;; 17*) ;; *) OSSH_CHECK_CFLAG_LINK([-fzero-call-used-regs=used]) ;; esac OSSH_CHECK_CFLAG_COMPILE([-ftrivial-auto-var-init=zero]) fi if test "x$use_retpoline" = "x1"; then OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang OSSH_CHECK_LDFLAG_LINK([-Wl,-z,retpolineplt]) fi AC_MSG_CHECKING([if $CC accepts -fno-builtin-memset]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-builtin-memset" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char b[10]; memset(b, 0, sizeof(b)); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" ] ) # -fstack-protector-all doesn't always work for some GCC versions # and/or platforms, so we test if we can. If it's not supported # on a given platform gcc will emit a warning so we use -Werror. if test "x$use_stack_protector" = "x1"; then for t in -fstack-protector-strong -fstack-protector-all \ -fstack-protector; do AC_MSG_CHECKING([if $CC supports $t]) saved_CFLAGS="$CFLAGS" saved_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $t -Werror" LDFLAGS="$LDFLAGS $t -Werror" AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} ]], [[ char x[256]; snprintf(x, sizeof(x), "XXX%d", func(1)); ]])], [ AC_MSG_RESULT([yes]) CFLAGS="$saved_CFLAGS $t" LDFLAGS="$saved_LDFLAGS $t" AC_MSG_CHECKING([if $t works]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} ]], [[ char x[256]; snprintf(x, sizeof(x), "XXX%d", func(1)); ]])], [ AC_MSG_RESULT([yes]) break ], [ AC_MSG_RESULT([no]) ], [ AC_MSG_WARN([cross compiling: cannot test]) break ] ) ], [ AC_MSG_RESULT([no]) ] ) CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" done fi if test -z "$have_llong_max"; then # retry LLONG_MAX with -std=gnu99, needed on some Linuxes unset ac_cv_have_decl_LLONG_MAX saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -std=gnu99" AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], [CFLAGS="$saved_CFLAGS"], [#include ] ) fi fi AC_MSG_CHECKING([if compiler allows __attribute__ on return types]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include __attribute__((__unused__)) static void foo(void){return;}]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE(NO_ATTRIBUTE_ON_RETURN_TYPE, 1, [compiler does not accept __attribute__ on return types]) ] ) AC_MSG_CHECKING([if compiler allows __attribute__ prototype args]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE(NO_ATTRIBUTE_ON_PROTOTYPE_ARGS, 1, [compiler does not accept __attribute__ on prototype args]) ] ) AC_MSG_CHECKING([if compiler supports variable length arrays]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[ int i; for (i=0; i<3; i++){int a[i]; a[i-1]=0;} exit(0); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE(VARIABLE_LENGTH_ARRAYS, [1], [compiler supports variable length arrays]) ], [ AC_MSG_RESULT([no]) ] ) AC_MSG_CHECKING([if compiler accepts variable declarations after code]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[ int a; a = 1; int b = 1; exit(a-b); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE(VARIABLE_DECLARATION_AFTER_CODE, [1], [compiler variable declarations after code]) ], [ AC_MSG_RESULT([no]) ] ) if test "x$no_attrib_nonnull" != "x1" ; then AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull]) fi AC_ARG_WITH([rpath], [ --without-rpath Disable auto-added -R linker paths], [ if test "x$withval" = "xno" ; then rpath_opt="" elif test "x$withval" = "xyes" ; then rpath_opt="-R" else rpath_opt="$withval" fi ] ) # Allow user to specify flags AC_ARG_WITH([cflags], [ --with-cflags Specify additional flags to pass to compiler], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then CFLAGS="$CFLAGS $withval" fi ] ) AC_ARG_WITH([cflags-after], [ --with-cflags-after Specify additional flags to pass to compiler after configure], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then CFLAGS_AFTER="$withval" fi ] ) AC_ARG_WITH([cppflags], [ --with-cppflags Specify additional flags to pass to preprocessor] , [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then CPPFLAGS="$CPPFLAGS $withval" fi ] ) AC_ARG_WITH([ldflags], [ --with-ldflags Specify additional flags to pass to linker], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then LDFLAGS="$LDFLAGS $withval" fi ] ) AC_ARG_WITH([ldflags-after], [ --with-ldflags-after Specify additional flags to pass to linker after configure], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then LDFLAGS_AFTER="$withval" fi ] ) AC_ARG_WITH([libs], [ --with-libs Specify additional libraries to link with], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then LIBS="$LIBS $withval" fi ] ) AC_ARG_WITH([Werror], [ --with-Werror Build main code with -Werror], [ if test -n "$withval" && test "x$withval" != "xno"; then werror_flags="-Werror" if test "x${withval}" != "xyes"; then werror_flags="$withval" fi fi ] ) dnl On some old platforms, sys/stat.h requires sys/types.h, but autoconf-2.71's dnl AC_CHECK_INCLUDES_DEFAULT checks for them in the opposite order. If we dnl haven't detected it, recheck. if test "x$ac_cv_header_sys_stat_h" != "xyes"; then unset ac_cv_header_sys_stat_h AC_CHECK_HEADERS([sys/stat.h]) fi AC_CHECK_HEADERS([ \ blf.h \ bstring.h \ crypt.h \ crypto/sha2.h \ dirent.h \ endian.h \ elf.h \ err.h \ features.h \ fcntl.h \ floatingpoint.h \ fnmatch.h \ getopt.h \ glob.h \ ia.h \ iaf.h \ ifaddrs.h \ inttypes.h \ langinfo.h \ limits.h \ locale.h \ login.h \ maillock.h \ ndir.h \ net/if_tun.h \ netdb.h \ netgroup.h \ pam/pam_appl.h \ paths.h \ poll.h \ pty.h \ readpassphrase.h \ rpc/types.h \ security/pam_appl.h \ sha2.h \ shadow.h \ stddef.h \ stdint.h \ string.h \ strings.h \ sys/bitypes.h \ sys/byteorder.h \ sys/bsdtty.h \ sys/cdefs.h \ sys/dir.h \ sys/file.h \ sys/mman.h \ sys/label.h \ sys/ndir.h \ sys/param.h \ sys/poll.h \ sys/prctl.h \ sys/procctl.h \ sys/pstat.h \ sys/ptrace.h \ sys/random.h \ sys/select.h \ sys/stream.h \ sys/stropts.h \ sys/strtio.h \ sys/statvfs.h \ sys/sysmacros.h \ sys/time.h \ sys/timers.h \ sys/vfs.h \ time.h \ tmpdir.h \ ttyent.h \ ucred.h \ unistd.h \ usersec.h \ util.h \ utime.h \ utmp.h \ utmpx.h \ vis.h \ wchar.h \ ]) AC_CHECK_DECLS([le32toh, le64toh, htole64], [], [], [ #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_ENDIAN_H # include #endif ]) # On some platforms (eg SunOS4) sys/audit.h requires sys/[time|types|label.h] # to be included first. AC_CHECK_HEADERS([sys/audit.h], [], [], [ #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_LABEL_H # include #endif ]) # sys/capsicum.h requires sys/types.h AC_CHECK_HEADERS([sys/capsicum.h capsicum_helpers.h], [], [], [ #ifdef HAVE_SYS_TYPES_H # include #endif ]) AC_MSG_CHECKING([for caph_cache_tzdata]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[caph_cache_tzdata();]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_CAPH_CACHE_TZDATA], [1], [Define if you have caph_cache_tzdata]) ], [ AC_MSG_RESULT([no]) ] ) # net/route.h requires sys/socket.h and sys/types.h. # sys/sysctl.h also requires sys/param.h AC_CHECK_HEADERS([net/route.h sys/sysctl.h], [], [], [ #ifdef HAVE_SYS_TYPES_H # include #endif #include #include ]) # lastlog.h requires sys/time.h to be included first on Solaris AC_CHECK_HEADERS([lastlog.h], [], [], [ #ifdef HAVE_SYS_TIME_H # include #endif ]) # sys/ptms.h requires sys/stream.h to be included first on Solaris AC_CHECK_HEADERS([sys/ptms.h], [], [], [ #ifdef HAVE_SYS_STREAM_H # include #endif ]) # login_cap.h requires sys/types.h on NetBSD AC_CHECK_HEADERS([login_cap.h], [], [], [ #include ]) # older BSDs need sys/param.h before sys/mount.h AC_CHECK_HEADERS([sys/mount.h], [], [], [ #include ]) # Android requires sys/socket.h to be included before sys/un.h AC_CHECK_HEADERS([sys/un.h], [], [], [ #include #include ]) # Messages for features tested for in target-specific section SIA_MSG="no" SPC_MSG="no" SP_MSG="no" SPP_MSG="no" # Support for Solaris/Illumos privileges (this test is used by both # the --with-solaris-privs option and --with-sandbox=solaris). SOLARIS_PRIVS="no" # Default shared library extension SHLIBEXT=".so" # Check for some target-specific stuff case "$host" in *-*-aix*) # Some versions of VAC won't allow macro redefinitions at # -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that # particularly with older versions of vac or xlc. # It also throws errors about null macro arguments, but these are # not fatal. AC_MSG_CHECKING([if compiler allows macro redefinitions]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include #define testmacro foo #define testmacro bar]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`" CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`" CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`" ] ) AC_MSG_CHECKING([how to specify blibpath for linker ($LD)]) if (test -z "$blibpath"); then blibpath="/usr/lib:/lib" fi saved_LDFLAGS="$LDFLAGS" if test "$GCC" = "yes"; then flags="-Wl,-blibpath: -Wl,-rpath, -blibpath:" else flags="-blibpath: -Wl,-blibpath: -Wl,-rpath," fi for tryflags in $flags ;do if (test -z "$blibflags"); then LDFLAGS="$saved_LDFLAGS $tryflags$blibpath" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [blibflags=$tryflags], []) fi done if (test -z "$blibflags"); then AC_MSG_RESULT([not found]) AC_MSG_ERROR([*** must be able to specify blibpath on AIX - check config.log]) else AC_MSG_RESULT([$blibflags]) fi LDFLAGS="$saved_LDFLAGS" dnl Check for authenticate. Might be in libs.a on older AIXes AC_CHECK_FUNC([authenticate], [AC_DEFINE([WITH_AIXAUTHENTICATE], [1], [Define if you want to enable AIX4's authenticate function])], [AC_CHECK_LIB([s], [authenticate], [ AC_DEFINE([WITH_AIXAUTHENTICATE]) LIBS="$LIBS -ls" ]) ]) dnl Check for various auth function declarations in headers. AC_CHECK_DECLS([authenticate, loginrestrictions, loginsuccess, passwdexpired, setauthdb], , , [#include ]) dnl Check if loginfailed is declared and takes 4 arguments (AIX >= 5.2) AC_CHECK_DECLS([loginfailed], [AC_MSG_CHECKING([if loginfailed takes 4 arguments]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ (void)loginfailed("user","host","tty",0); ]])], [AC_MSG_RESULT([yes]) AC_DEFINE([AIX_LOGINFAILED_4ARG], [1], [Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2)])], [AC_MSG_RESULT([no]) ])], [], [#include ] ) AC_CHECK_FUNCS([getgrset setauthdb]) AC_CHECK_DECL([F_CLOSEM], AC_DEFINE([HAVE_FCNTL_CLOSEM], [1], [Use F_CLOSEM fcntl for closefrom]), [], [ #include #include ] ) check_for_aix_broken_getaddrinfo=1 AC_DEFINE([SETEUID_BREAKS_SETUID], [1], [Define if your platform breaks doing a seteuid before a setuid]) AC_DEFINE([BROKEN_SETREUID], [1], [Define if your setreuid() is broken]) AC_DEFINE([BROKEN_SETREGID], [1], [Define if your setregid() is broken]) dnl AIX handles lastlog as part of its login message AC_DEFINE([DISABLE_LASTLOG], [1], [Define if you don't want to use lastlog]) AC_DEFINE([LOGIN_NEEDS_UTMPX], [1], [Some systems need a utmpx entry for /bin/login to work]) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV], [Define to a Set Process Title type if your system is supported by bsd-setproctitle.c]) AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1], [AIX 5.2 and 5.3 (and presumably newer) require this]) AC_DEFINE([PTY_ZEROREAD], [1], [read(1) can return 0 for a non-closed fd]) AC_DEFINE([PLATFORM_SYS_DIR_UID], 2, [System dirs owned by bin (uid 2)]) AC_DEFINE([BROKEN_STRNDUP], 1, [strndup broken, see APAR IY61211]) AC_DEFINE([BROKEN_STRNLEN], 1, [strnlen broken, see APAR IY62551]) ;; *-*-android*) AC_DEFINE([DISABLE_UTMP], [1], [Define if you don't want to use utmp]) AC_DEFINE([DISABLE_WTMP], [1], [Define if you don't want to use wtmp]) ;; *-*-cygwin*) LIBS="$LIBS /usr/lib/textreadmode.o" AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin]) AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()]) AC_DEFINE([NO_UID_RESTORATION_TEST], [1], [Define to disable UID restoration test]) AC_DEFINE([DISABLE_SHADOW], [1], [Define if you want to disable shadow passwords]) AC_DEFINE([NO_X11_UNIX_SOCKETS], [1], [Define if X11 doesn't support AF_UNIX sockets on that system]) AC_DEFINE([DISABLE_FD_PASSING], [1], [Define if your platform needs to skip post auth file descriptor passing]) AC_DEFINE([SSH_IOBUFSZ], [65535], [Windows is sensitive to read buffer size]) AC_DEFINE([FILESYSTEM_NO_BACKSLASH], [1], [File names may not contain backslash characters]) # Cygwin defines optargs, optargs as declspec(dllimport) for historical # reasons which cause compile warnings, so we disable those warnings. OSSH_CHECK_CFLAG_COMPILE([-Wno-attributes]) SHLIBEXT=".dll" ;; *-*-dgux*) AC_DEFINE([IP_TOS_IS_BROKEN], [1], [Define if your system choked on IP TOS setting]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) ;; *-*-darwin*) use_pie=auto AC_MSG_CHECKING([if we have working getaddrinfo]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) exit(0); else exit(1); } ]])], [AC_MSG_RESULT([working])], [AC_MSG_RESULT([buggy]) AC_DEFINE([BROKEN_GETADDRINFO], [1], [getaddrinfo is broken (if present)]) ], [AC_MSG_RESULT([assume it is working])]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect]) AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1], [Define if your resolver libs need this for getrrsetbyname]) AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_DEFINE([SSH_TUN_COMPAT_AF], [1], [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) [#include ] AC_DEFINE([LASTLOG_WRITE_PUTUTXLINE], [1], [Define if pututxline updates lastlog too]) ) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV], [Define to a Set Process Title type if your system is supported by bsd-setproctitle.c]) AC_CHECK_FUNCS([sandbox_init]) AC_CHECK_HEADERS([sandbox.h]) AC_CHECK_LIB([sandbox], [sandbox_apply], [ SSHDLIBS="$SSHDLIBS -lsandbox" ]) # proc_pidinfo()-based closefrom() replacement. AC_CHECK_HEADERS([libproc.h]) AC_CHECK_FUNCS([proc_pidinfo]) # poll(2) is broken for character-special devices (at least). # cf. Apple bug 3710161 (not public, but searchable) AC_DEFINE([BROKEN_POLL], [1], [System poll(2) implementation is broken]) SHLIBEXT=".dylib" ;; *-*-dragonfly*) SSHDLIBS="$SSHDLIBS" TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-haiku*) LIBS="$LIBS -lbsd " CFLAGS="$CFLAGS -D_BSD_SOURCE" AC_CHECK_LIB([network], [socket]) AC_DEFINE([HAVE_U_INT64_T]) AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx]) MANTYPE=man ;; *-*-hpux*) # first we define all of the options common to all HP-UX releases CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" IPADDR_IN_DISPLAY=yes AC_DEFINE([USE_PIPES]) AC_DEFINE([LOGIN_NEEDS_UTMPX]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*"], [String used in /etc/passwd to denote locked account]) AC_DEFINE([SPT_TYPE], [SPT_PSTAT]) AC_DEFINE([PLATFORM_SYS_DIR_UID], 2, [System dirs owned by bin (uid 2)]) maildir="/var/mail" LIBS="$LIBS -lsec" AC_CHECK_LIB([xnet], [t_error], , [AC_MSG_ERROR([*** -lxnet needed on HP-UX - check config.log ***])]) # next, we define all of the options specific to major releases case "$host" in *-*-hpux10*) if test -z "$GCC"; then CFLAGS="$CFLAGS -Ae" fi AC_DEFINE([BROKEN_GETLINE], [1], [getline is not what we expect]) ;; *-*-hpux11*) AC_DEFINE([PAM_SUN_CODEBASE], [1], [Define if you are using Solaris-derived PAM which passes pam_messages to the conversation function with an extra level of indirection]) AC_DEFINE([DISABLE_UTMP], [1], [Define if you don't want to use utmp]) AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins]) check_for_hpux_broken_getaddrinfo=1 check_for_conflicting_getspnam=1 ;; esac # lastly, we define options specific to minor releases case "$host" in *-*-hpux10.26) AC_DEFINE([HAVE_SECUREWARE], [1], [Define if you have SecureWare-based protected password database]) disable_ptmx_check=yes LIBS="$LIBS -lsecpw" ;; esac ;; *-*-irix5*) PATH="$PATH:/usr/etc" AC_DEFINE([BROKEN_INET_NTOA], [1], [Define if you system's inet_ntoa is busted (e.g. Irix gcc issue)]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([WITH_ABBREV_NO_TTY], [1], [Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) ;; *-*-irix6*) PATH="$PATH:/usr/etc" AC_DEFINE([WITH_IRIX_ARRAY], [1], [Define if you have/want arrays (cluster-wide session management, not C arrays)]) AC_DEFINE([WITH_IRIX_PROJECT], [1], [Define if you want IRIX project management]) AC_DEFINE([WITH_IRIX_AUDIT], [1], [Define if you want IRIX audit trails]) AC_CHECK_FUNC([jlimit_startjob], [AC_DEFINE([WITH_IRIX_JOBS], [1], [Define if you want IRIX kernel jobs])]) AC_DEFINE([BROKEN_INET_NTOA]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([BROKEN_UPDWTMPX], [1], [updwtmpx is broken (if present)]) AC_DEFINE([WITH_ABBREV_NO_TTY]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) ;; *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu) AC_DEFINE([PAM_TTY_KLUDGE]) AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"]) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV]) AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts]) AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins]) ;; *-*-linux*) no_dev_ptmx=1 use_pie=auto check_for_openpty_ctty_bug=1 dnl Target SUSv3/POSIX.1-2001 plus BSD specifics. dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE dnl _GNU_SOURCE is needed for setres*id prototypes. CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_GNU_SOURCE" AC_DEFINE([BROKEN_CLOSEFROM], [1], [broken in chroots on older kernels]) AC_DEFINE([PAM_TTY_KLUDGE], [1], [Work around problematic Linux PAM modules handling of PAM_TTY]) AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"], [String used in /etc/passwd to denote locked account]) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV]) AC_DEFINE([LINK_OPNOTSUPP_ERRNO], [EPERM], [Define to whatever link() returns for "not supported" if it doesn't return EOPNOTSUPP.]) AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts]) AC_DEFINE([USE_BTMP]) AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer]) AC_ARG_WITH([linux-memlock-onfault], [ --with-linux-memlock-onfault Enables memory locking on Linux], [ if test "x$withval" != "xno" ; then AC_MSG_CHECKING([for MCL_ONFAULT]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM( [[ #include ]], [[ mlockall(MCL_FUTURE | MCL_ONFAULT); ]], )], [ AC_MSG_RESULT([supported]) AC_DEFINE([LINUX_MEMLOCK_ONFAULT], [1], [Lock all memory to protect sshd against Linux kcompactd] )], [ AC_MSG_RESULT([not supported]) AC_MSG_ERROR([MCL_ONFAULT is not available on your system]) ]) fi ], ) AC_DEFINE([SYSTEMD_NOTIFY], [1], [Have sshd notify systemd on start/reload]) inet6_default_4in6=yes case `uname -r` in 1.*|2.0.*) AC_DEFINE([BROKEN_CMSG_TYPE], [1], [Define if cmsg_type is not passed correctly]) ;; esac # tun(4) forwarding compat code AC_CHECK_HEADERS([linux/if_tun.h]) if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then AC_DEFINE([SSH_TUN_LINUX], [1], [Open tunnel devices the Linux tun/tap way]) AC_DEFINE([SSH_TUN_COMPAT_AF], [1], [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) fi AC_CHECK_HEADER([linux/if.h], AC_DEFINE([SYS_RDOMAIN_LINUX], [1], [Support routing domains using Linux VRF]), [], [ #ifdef HAVE_SYS_TYPES_H # include #endif ]) AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h linux/audit.h], [], [], [#include ]) # Obtain MIPS ABI case "$host" in mips*) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if _MIPS_SIM != _ABIO32 #error #endif ]])],[mips_abi="o32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if _MIPS_SIM != _ABIN32 #error #endif ]])],[mips_abi="n32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if _MIPS_SIM != _ABI64 #error #endif ]])],[mips_abi="n64"],[AC_MSG_ERROR([unknown MIPS ABI]) ]) ]) ]) ;; esac AC_MSG_CHECKING([for seccomp architecture]) seccomp_audit_arch= case "$host" in x86_64-*) seccomp_audit_arch=AUDIT_ARCH_X86_64 ;; i*86-*) seccomp_audit_arch=AUDIT_ARCH_I386 ;; arm*-*) seccomp_audit_arch=AUDIT_ARCH_ARM ;; aarch64*-*) seccomp_audit_arch=AUDIT_ARCH_AARCH64 ;; s390x-*) seccomp_audit_arch=AUDIT_ARCH_S390X ;; s390-*) seccomp_audit_arch=AUDIT_ARCH_S390 ;; powerpc-*) seccomp_audit_arch=AUDIT_ARCH_PPC ;; powerpc64-*) seccomp_audit_arch=AUDIT_ARCH_PPC64 ;; powerpc64le-*) seccomp_audit_arch=AUDIT_ARCH_PPC64LE ;; mips-*) seccomp_audit_arch=AUDIT_ARCH_MIPS ;; mipsel-*) seccomp_audit_arch=AUDIT_ARCH_MIPSEL ;; mips64-*) case "$mips_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPS64N32 ;; "n64") seccomp_audit_arch=AUDIT_ARCH_MIPS64 ;; esac ;; mips64el-*) case "$mips_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32 ;; "n64") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64 ;; esac ;; riscv64-*) seccomp_audit_arch=AUDIT_ARCH_RISCV64 ;; esac if test "x$seccomp_audit_arch" != "x" ; then AC_MSG_RESULT(["$seccomp_audit_arch"]) AC_DEFINE_UNQUOTED([SECCOMP_AUDIT_ARCH], [$seccomp_audit_arch], [Specify the system call convention in use]) else AC_MSG_RESULT([architecture not supported]) fi ;; *-*-minix) AC_DEFINE([SETEUID_BREAKS_SETUID]) # poll(2) seems to choke on /dev/null; "Bad file descriptor" AC_DEFINE([BROKEN_POLL], [1], [System poll(2) implementation is broken]) ;; mips-sony-bsd|mips-sony-newsos4) AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to acquire controlling tty]) SONY=1 ;; *-*-netbsd*) if test "x$withval" != "xno" ; then rpath_opt="-R" fi CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE" AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_CHECK_HEADER([net/if_tap.h], , AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support])) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) TEST_MALLOC_OPTIONS="AJRX" AC_DEFINE([BROKEN_READ_COMPARISON], [1], [NetBSD read function is sometimes redirected, breaking atomicio comparisons against it]) ;; *-*-freebsd*) AC_DEFINE([LOCKED_PASSWD_PREFIX], ["*LOCKED*"], [Account locked with pw(1)]) AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_CHECK_HEADER([net/if_tap.h], , AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support])) AC_DEFINE([BROKEN_GLOB], [1], [FreeBSD glob does not do what we need]) TEST_MALLOC_OPTIONS="AJRX" # Preauth crypto occasionally uses file descriptors for crypto offload # and will crash if they cannot be opened. AC_DEFINE([SANDBOX_SKIP_RLIMIT_NOFILE], [1], [define if setrlimit RLIMIT_NOFILE breaks things]) case "$host" in *-*-freebsd9.*|*-*-freebsd10.*) # Capsicum on 9 and 10 do not allow ppoll() so don't auto-enable. disable_capsicum=yes esac ;; *-*-bsdi*) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) ;; *-next-*) conf_lastlog_location="/usr/adm/lastlog" conf_utmp_location=/etc/utmp conf_wtmp_location=/usr/adm/wtmp maildir=/usr/spool/mail AC_DEFINE([HAVE_NEXT], [1], [Define if you are on NeXT]) AC_DEFINE([USE_PIPES]) AC_DEFINE([BROKEN_SAVED_UIDS], [1], [Needed for NeXT]) ;; *-*-openbsd*) use_pie=auto AC_DEFINE([HAVE_ATTRIBUTE__SENTINEL__], [1], [OpenBSD's gcc has sentinel]) AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD's gcc has bounded]) AC_DEFINE([SSH_TUN_OPENBSD], [1], [Open tunnel devices the OpenBSD way]) AC_DEFINE([SYSLOG_R_SAFE_IN_SIGHAND], [1], [syslog_r function is safe to use in in a signal handler]) TEST_MALLOC_OPTIONS="SJRU" ;; *-*-solaris*) if test "x$withval" != "xno" ; then rpath_opt="-R" fi AC_DEFINE([PAM_SUN_CODEBASE]) AC_DEFINE([LOGIN_NEEDS_UTMPX]) AC_DEFINE([PAM_TTY_KLUDGE]) AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1], [Define if pam_chauthtok wants real uid set to the unpriv'ed user]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) # Pushing STREAMS modules will cause sshd to acquire a controlling tty. AC_DEFINE([SSHD_ACQUIRES_CTTY], [1], [Define if sshd somehow reacquires a controlling TTY after setsid()]) AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd in case the name is longer than 8 chars]) AC_DEFINE([BROKEN_TCGETATTR_ICANON], [1], [tcgetattr with ICANON may hang]) external_path_file=/etc/default/login # hardwire lastlog location (can't detect it on some versions) conf_lastlog_location="/var/adm/lastlog" AC_MSG_CHECKING([for obsolete utmp and wtmp in solaris2.x]) sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'` if test "$sol2ver" -ge 8; then AC_MSG_RESULT([yes]) AC_DEFINE([DISABLE_UTMP]) AC_DEFINE([DISABLE_WTMP], [1], [Define if you don't want to use wtmp]) else AC_MSG_RESULT([no]) fi AC_CHECK_FUNCS([setpflags]) AC_CHECK_FUNCS([setppriv]) AC_CHECK_FUNCS([priv_basicset]) AC_CHECK_HEADERS([priv.h]) AC_ARG_WITH([solaris-contracts], [ --with-solaris-contracts Enable Solaris process contracts (experimental)], [ AC_CHECK_LIB([contract], [ct_tmpl_activate], [ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1], [Define if you have Solaris process contracts]) LIBS="$LIBS -lcontract" SPC_MSG="yes" ], ) ], ) AC_ARG_WITH([solaris-projects], [ --with-solaris-projects Enable Solaris projects (experimental)], [ AC_CHECK_LIB([project], [setproject], [ AC_DEFINE([USE_SOLARIS_PROJECTS], [1], [Define if you have Solaris projects]) LIBS="$LIBS -lproject" SP_MSG="yes" ], ) ], ) AC_ARG_WITH([solaris-privs], [ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)], [ AC_MSG_CHECKING([for Solaris/Illumos privilege support]) if test "x$ac_cv_func_setppriv" = "xyes" -a \ "x$ac_cv_header_priv_h" = "xyes" ; then SOLARIS_PRIVS=yes AC_MSG_RESULT([found]) AC_DEFINE([NO_UID_RESTORATION_TEST], [1], [Define to disable UID restoration test]) AC_DEFINE([USE_SOLARIS_PRIVS], [1], [Define if you have Solaris privileges]) SPP_MSG="yes" else AC_MSG_RESULT([not found]) AC_MSG_ERROR([*** must have support for Solaris privileges to use --with-solaris-privs]) fi ], ) TEST_SHELL=$SHELL # let configure find us a capable shell ;; *-*-sunos4*) CPPFLAGS="$CPPFLAGS -DSUNOS4" AC_CHECK_FUNCS([getpwanam]) AC_DEFINE([PAM_SUN_CODEBASE]) conf_utmp_location=/etc/utmp conf_wtmp_location=/var/adm/wtmp conf_lastlog_location=/var/adm/lastlog AC_DEFINE([USE_PIPES]) AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx]) ;; *-ncr-sysv*) LIBS="$LIBS -lc89" AC_DEFINE([USE_PIPES]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) ;; *-sni-sysv*) # /usr/ucblib MUST NOT be searched on ReliantUNIX AC_CHECK_LIB([dl], [dlsym], ,) # -lresolv needs to be at the end of LIBS or DNS lookups break AC_CHECK_LIB([resolv], [res_query], [ LIBS="$LIBS -lresolv" ]) IPADDR_IN_DISPLAY=yes AC_DEFINE([USE_PIPES]) AC_DEFINE([IP_TOS_IS_BROKEN]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) external_path_file=/etc/default/login # /usr/ucblib/libucb.a no longer needed on ReliantUNIX # Attention: always take care to bind libsocket and libnsl before libc, # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog ;; # UnixWare 1.x, UnixWare 2.x, and others based on code from Univel. *-*-sysv4.2*) AC_DEFINE([USE_PIPES]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) TEST_SHELL=$SHELL # let configure find us a capable shell ;; # UnixWare 7.x, OpenUNIX 8 *-*-sysv5*) CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf" AC_DEFINE([UNIXWARE_LONG_PASSWORDS], [1], [Support passwords > 8 chars]) AC_DEFINE([USE_PIPES]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_GETADDRINFO]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([PASSWD_NEEDS_USERNAME]) AC_DEFINE([BROKEN_TCGETATTR_ICANON]) TEST_SHELL=$SHELL # let configure find us a capable shell case "$host" in *-*-sysv5SCO_SV*) # SCO OpenServer 6.x maildir=/var/spool/mail AC_DEFINE([BROKEN_UPDWTMPX]) AC_CHECK_LIB([prot], [getluid], [ LIBS="$LIBS -lprot" AC_CHECK_FUNCS([getluid setluid], , , [-lprot]) ], , ) ;; *) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) ;; esac ;; *-*-sysv*) ;; # SCO UNIX and OEM versions of SCO UNIX *-*-sco3.2v4*) AC_MSG_ERROR("This Platform is no longer supported.") ;; # SCO OpenServer 5.x *-*-sco3.2v5*) if test -z "$GCC"; then CFLAGS="$CFLAGS -belf" fi LIBS="$LIBS -lprot -lx -ltinfo -lm" no_dev_ptmx=1 AC_DEFINE([USE_PIPES]) AC_DEFINE([HAVE_SECUREWARE]) AC_DEFINE([DISABLE_SHADOW]) AC_DEFINE([DISABLE_FD_PASSING]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_GETADDRINFO]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([WITH_ABBREV_NO_TTY]) AC_DEFINE([BROKEN_UPDWTMPX]) AC_DEFINE([PASSWD_NEEDS_USERNAME]) AC_CHECK_FUNCS([getluid setluid]) MANTYPE=man TEST_SHELL=$SHELL # let configure find us a capable shell SKIP_DISABLE_LASTLOG_DEFINE=yes ;; *-dec-osf*) AC_MSG_CHECKING([for Digital Unix SIA]) no_osfsia="" AC_ARG_WITH([osfsia], [ --with-osfsia Enable Digital Unix SIA], [ if test "x$withval" = "xno" ; then AC_MSG_RESULT([disabled]) no_osfsia=1 fi ], ) if test -z "$no_osfsia" ; then if test -f /etc/sia/matrix.conf; then AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_OSF_SIA], [1], [Define if you have Digital Unix Security Integration Architecture]) AC_DEFINE([DISABLE_LOGIN], [1], [Define if you don't want to use your system's login() call]) AC_DEFINE([DISABLE_FD_PASSING]) LIBS="$LIBS -lsecurity -ldb -lm -laud" SIA_MSG="yes" else AC_MSG_RESULT([no]) AC_DEFINE([LOCKED_PASSWD_SUBSTR], ["Nologin"], [String used in /etc/passwd to denote locked account]) fi fi AC_DEFINE([BROKEN_GETADDRINFO]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([BROKEN_READV_COMPARISON], [1], [Can't do comparisons on readv]) ;; *-*-nto-qnx*) AC_DEFINE([USE_PIPES]) AC_DEFINE([NO_X11_UNIX_SOCKETS]) AC_DEFINE([DISABLE_LASTLOG]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) AC_DEFINE([BROKEN_SHADOW_EXPIRE], [1], [QNX shadow support is broken]) enable_etc_default_login=no # has incompatible /etc/default/login case "$host" in *-*-nto-qnx6*) AC_DEFINE([DISABLE_FD_PASSING]) ;; esac ;; *-*-ultrix*) AC_DEFINE([BROKEN_GETGROUPS], [1], [getgroups(0,NULL) will return -1]) AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to for controlling tty]) AC_DEFINE([HAVE_SYS_SYSLOG_H], [1], [Force use of sys/syslog.h on Ultrix]) AC_DEFINE([DISABLE_UTMPX], [1], [Disable utmpx]) # DISABLE_FD_PASSING so that we call setpgrp as root, otherwise we # don't get a controlling tty. AC_DEFINE([DISABLE_FD_PASSING], [1], [Need to call setpgrp as root]) # On Ultrix some headers are not protected against multiple includes, # so we create wrappers and put it where the compiler will find it. AC_MSG_WARN([creating compat wrappers for headers]) mkdir -p netinet for header in netinet/ip.h netdb.h resolv.h; do name=`echo $header | tr 'a-z/.' 'A-Z__'` cat >$header < ]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([*** compiler cannot create working executables, check config.log ***]) ], [ AC_MSG_WARN([cross compiling: not checking compiler sanity]) ] ) dnl Checks for header files. # Checks for libraries. AC_CHECK_FUNC([setsockopt], , [AC_CHECK_LIB([socket], [setsockopt])]) dnl IRIX and Solaris 2.5.1 have dirname() in libgen AC_CHECK_FUNCS([dirname], [AC_CHECK_HEADERS([libgen.h])] , [ AC_CHECK_LIB([gen], [dirname], [ AC_CACHE_CHECK([for broken dirname], ac_cv_have_broken_dirname, [ save_LIBS="$LIBS" LIBS="$LIBS -lgen" AC_RUN_IFELSE( [AC_LANG_SOURCE([[ #include #include #include int main(int argc, char **argv) { char *s, buf[32]; strncpy(buf,"/etc", 32); s = dirname(buf); if (!s || strncmp(s, "/", 32) != 0) { exit(1); } else { exit(0); } } ]])], [ ac_cv_have_broken_dirname="no" ], [ ac_cv_have_broken_dirname="yes" ], [ ac_cv_have_broken_dirname="no" ], ) LIBS="$save_LIBS" ]) if test "x$ac_cv_have_broken_dirname" = "xno" ; then LIBS="$LIBS -lgen" AC_DEFINE([HAVE_DIRNAME]) AC_CHECK_HEADERS([libgen.h]) fi ]) ]) AC_CHECK_FUNC([getspnam], , [AC_CHECK_LIB([gen], [getspnam], [LIBS="$LIBS -lgen"])]) AC_SEARCH_LIBS([basename], [gen], [AC_DEFINE([HAVE_BASENAME], [1], [Define if you have the basename function.])]) dnl zlib defaults to enabled zlib=yes AC_ARG_WITH([zlib], [ --with-zlib=PATH Use zlib in PATH], [ if test "x$withval" = "xno" ; then zlib=no elif test "x$withval" != "xyes"; then if test -d "$withval/lib"; then if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi else if test -n "${rpath_opt}"; then LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}" else LDFLAGS="-L${withval} ${LDFLAGS}" fi fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi ] ) # These libraries are needed for anything that links in the channel code. CHANNELLIBS="" AC_MSG_CHECKING([for zlib]) if test "x${zlib}" = "xno"; then AC_MSG_RESULT([no]) else saved_LIBS="$LIBS" CHANNELLIBS="$CHANNELLIBS -lz" AC_MSG_RESULT([yes]) AC_DEFINE([WITH_ZLIB], [1], [Enable zlib]) AC_CHECK_HEADER([zlib.h], ,[AC_MSG_ERROR([*** zlib.h missing - please install first or check config.log ***])]) AC_CHECK_LIB([z], [deflate], [], [ saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" dnl Check default zlib install dir if test -n "${rpath_opt}"; then LDFLAGS="-L/usr/local/lib ${rpath_opt}/usr/local/lib ${saved_LDFLAGS}" else LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}" fi CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}" AC_TRY_LINK_FUNC([deflate], [AC_DEFINE([HAVE_LIBZ])], [ AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***]) ] ) ] ) AC_ARG_WITH([zlib-version-check], [ --without-zlib-version-check Disable zlib version check], [ if test "x$withval" = "xno" ; then zlib_check_nonfatal=1 fi ] ) AC_MSG_CHECKING([for possibly buggy zlib]) AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]], [[ int a=0, b=0, c=0, d=0, n, v; n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d); if (n < 1) exit(1); v = a*1000000 + b*10000 + c*100 + d; fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v); /* 1.1.4 is OK */ if (a == 1 && b == 1 && c >= 4) exit(0); /* 1.2.3 and up are OK */ if (v >= 1020300) exit(0); exit(2); ]])], AC_MSG_RESULT([no]), [ AC_MSG_RESULT([yes]) if test -z "$zlib_check_nonfatal" ; then AC_MSG_ERROR([*** zlib too old - check config.log *** Your reported zlib version has known security problems. It's possible your vendor has fixed these problems without changing the version number. If you are sure this is the case, you can disable the check by running "./configure --without-zlib-version-check". If you are in doubt, upgrade zlib to version 1.2.3 or greater. See http://www.gzip.org/zlib/ for details.]) else AC_MSG_WARN([zlib version may have security problems]) fi ], [ AC_MSG_WARN([cross compiling: not checking zlib version]) ] ) LIBS="$saved_LIBS" fi dnl UnixWare 2.x AC_CHECK_FUNC([strcasecmp], [], [ AC_CHECK_LIB([resolv], [strcasecmp], [LIBS="$LIBS -lresolv"]) ] ) AC_CHECK_FUNCS([utimes], [], [ AC_CHECK_LIB([c89], [utimes], [AC_DEFINE([HAVE_UTIMES]) LIBS="$LIBS -lc89"]) ] ) dnl Checks for libutil functions AC_CHECK_HEADERS([bsd/libutil.h libutil.h]) AC_SEARCH_LIBS([fmt_scaled], [util bsd]) AC_SEARCH_LIBS([scan_scaled], [util bsd]) AC_SEARCH_LIBS([login], [util bsd]) AC_SEARCH_LIBS([logout], [util bsd]) AC_SEARCH_LIBS([logwtmp], [util bsd]) AC_SEARCH_LIBS([openpty], [util bsd]) AC_SEARCH_LIBS([updwtmp], [util bsd]) AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp]) # On some platforms, inet_ntop and gethostbyname may be found in libresolv # or libnsl. AC_SEARCH_LIBS([inet_ntop], [resolv nsl]) AC_SEARCH_LIBS([gethostbyname], [resolv nsl]) # Some Linux distribtions ship the BSD libc hashing functions in # separate libraries. AC_SEARCH_LIBS([SHA256Update], [md bsd]) # "Particular Function Checks" # see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html AC_FUNC_STRFTIME AC_FUNC_MALLOC AC_FUNC_REALLOC # autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL; AC_MSG_CHECKING([if calloc(0, N) returns non-null]) AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ void *p = calloc(0, 1); exit(p == NULL); ]] )], [ func_calloc_0_nonnull=yes ], [ func_calloc_0_nonnull=no ], [ AC_MSG_WARN([cross compiling: assuming same as malloc]) func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull"] ) AC_MSG_RESULT([$func_calloc_0_nonnull]) if test "x$func_calloc_0_nonnull" = "xyes"; then AC_DEFINE(HAVE_CALLOC, 1, [calloc(0, x) returns non-null]) else AC_DEFINE(HAVE_CALLOC, 0, [calloc(0, x) returns NULL]) AC_DEFINE(calloc, rpl_calloc, [Define to rpl_calloc if the replacement function should be used.]) fi # Check for ALTDIRFUNC glob() extension AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support]) AC_EGREP_CPP([FOUNDIT], [ #include #ifdef GLOB_ALTDIRFUNC FOUNDIT #endif ], [ AC_DEFINE([GLOB_HAS_ALTDIRFUNC], [1], [Define if your system glob() function has the GLOB_ALTDIRFUNC extension]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ] ) # Check for g.gl_matchc glob() extension AC_MSG_CHECKING([for gl_matchc field in glob_t]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ glob_t g; g.gl_matchc = 1; ]])], [ AC_DEFINE([GLOB_HAS_GL_MATCHC], [1], [Define if your system glob() function has gl_matchc options in glob_t]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) # Check for g.gl_statv glob() extension AC_MSG_CHECKING([for gl_statv and GLOB_KEEPSTAT extensions for glob]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ #ifndef GLOB_KEEPSTAT #error "glob does not support GLOB_KEEPSTAT extension" #endif glob_t g; g.gl_statv = NULL; ]])], [ AC_DEFINE([GLOB_HAS_GL_STATV], [1], [Define if your system glob() function has gl_statv options in glob_t]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) AC_CHECK_DECLS([GLOB_NOMATCH], , , [#include ]) AC_CHECK_DECL([VIS_ALL], , AC_DEFINE(BROKEN_STRNVIS, 1, [missing VIS_ALL]), [#include ]) AC_MSG_CHECKING([whether struct dirent allocates space for d_name]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ struct dirent d; exit(sizeof(d.d_name)<=sizeof(char)); ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME], [1], [Define if your struct dirent expects you to allocate extra space for d_name]) ], [ AC_MSG_WARN([cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME]) AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME]) ] ) AC_MSG_CHECKING([for /proc/pid/fd directory]) if test -d "/proc/$$/fd" ; then AC_DEFINE([HAVE_PROC_PID], [1], [Define if you have /proc/$pid/fd]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi # Check whether user wants to use ldns LDNS_MSG="no" AC_ARG_WITH(ldns, [ --with-ldns[[=PATH]] Use ldns for DNSSEC support (optionally in PATH)], [ ldns="" if test "x$withval" = "xyes" ; then AC_PATH_TOOL([LDNSCONFIG], [ldns-config], [no]) if test "x$LDNSCONFIG" = "xno"; then LIBS="-lldns $LIBS" ldns=yes else LIBS="$LIBS `$LDNSCONFIG --libs`" CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`" ldns=yes fi elif test "x$withval" != "xno" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" LIBS="-lldns $LIBS" ldns=yes fi # Verify that it works. if test "x$ldns" = "xyes" ; then AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support]) LDNS_MSG="yes" AC_MSG_CHECKING([for ldns support]) AC_LINK_IFELSE( [AC_LANG_SOURCE([[ #include #include #ifdef HAVE_STDINT_H # include #endif #include int main(void) { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); } ]]) ], [AC_MSG_RESULT(yes)], [ AC_MSG_RESULT(no) AC_MSG_ERROR([** Incomplete or missing ldns libraries.]) ]) fi ]) # Check whether user wants libedit support LIBEDIT_MSG="no" AC_ARG_WITH([libedit], [ --with-libedit[[=PATH]] Enable libedit support for sftp], [ if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then if test "x$PKGCONFIG" != "xno"; then AC_MSG_CHECKING([if $PKGCONFIG knows about libedit]) if "$PKGCONFIG" libedit; then AC_MSG_RESULT([yes]) use_pkgconfig_for_libedit=yes else AC_MSG_RESULT([no]) fi fi else CPPFLAGS="$CPPFLAGS -I${withval}/include" if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi fi if test "x$use_pkgconfig_for_libedit" = "xyes"; then LIBEDIT=`$PKGCONFIG --libs libedit` CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`" else LIBEDIT="-ledit -lcurses" fi OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'` AC_CHECK_LIB([edit], [el_init], [ AC_DEFINE([USE_LIBEDIT], [1], [Use libedit for sftp]) LIBEDIT_MSG="yes" AC_SUBST([LIBEDIT]) ], [ AC_MSG_ERROR([libedit not found]) ], [ $OTHERLIBS ] ) AC_MSG_CHECKING([if libedit version is compatible]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[ int i = H_SETSIZE; el_init("", NULL, NULL, NULL); exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([libedit version is not compatible]) ] ) fi ] ) # Check whether user wants wtmpdb support WTMPDB_MSG="no" AC_ARG_WITH([wtmpdb], [ --with-wtmpdb[[=PATH]] Enable wtmpdb support for sshd], [ if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then if test "x$PKGCONFIG" != "xno"; then AC_MSG_CHECKING([if $PKGCONFIG knows about wtmpdb]) if "$PKGCONFIG" libwtmpdb; then AC_MSG_RESULT([yes]) use_pkgconfig_for_libwtmpdb=yes else AC_MSG_RESULT([no]) fi fi else CPPFLAGS="$CPPFLAGS -I${withval}/include" if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi fi if test "x$use_pkgconfig_for_libwtmpdb" = "xyes"; then LIBWTMPDB=`$PKGCONFIG --libs libwtmpdb` CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libwtmpdb`" else LIBWTMPDB="-lwtmpdb" fi OTHERLIBS=`echo $LIBWTMPDB | sed 's/-lwtmpdb//'` AC_CHECK_LIB([wtmpdb], [wtmpdb_login], [ AC_DEFINE([USE_WTMPDB], [1], [Use libwtmpdb for sshd]) WTMPDB_MSG="yes" AC_SUBST([LIBWTMPDB]) ], [ AC_MSG_ERROR([libwtmpdb not found]) ], [ $OTHERLIBS ] ) fi ] ) AUDIT_MODULE=none AC_ARG_WITH([audit], [ --with-audit=module Enable audit support (modules=debug,bsm,linux)], [ AC_MSG_CHECKING([for supported audit module]) case "$withval" in bsm) AC_MSG_RESULT([bsm]) AUDIT_MODULE=bsm dnl Checks for headers, libs and functions AC_CHECK_HEADERS([bsm/audit.h], [], [AC_MSG_ERROR([BSM enabled and bsm/audit.h not found])], [ #ifdef HAVE_TIME_H # include #endif ] ) AC_CHECK_LIB([bsm], [getaudit], [], [AC_MSG_ERROR([BSM enabled and required library not found])]) AC_CHECK_FUNCS([getaudit], [], [AC_MSG_ERROR([BSM enabled and required function not found])]) # These are optional AC_CHECK_FUNCS([getaudit_addr aug_get_machine]) AC_DEFINE([USE_BSM_AUDIT], [1], [Use BSM audit module]) if test "$sol2ver" -ge 11; then SSHDLIBS="$SSHDLIBS -lscf" AC_DEFINE([BROKEN_BSM_API], [1], [The system has incomplete BSM API]) fi ;; linux) AC_MSG_RESULT([linux]) AUDIT_MODULE=linux dnl Checks for headers, libs and functions AC_CHECK_HEADERS([libaudit.h]) SSHDLIBS="$SSHDLIBS -laudit" AC_DEFINE([USE_LINUX_AUDIT], [1], [Use Linux audit module]) ;; debug) AUDIT_MODULE=debug AC_MSG_RESULT([debug]) AC_DEFINE([SSH_AUDIT_EVENTS], [1], [Use audit debugging module]) ;; no) AC_MSG_RESULT([no]) ;; *) AC_MSG_ERROR([Unknown audit module $withval]) ;; esac ] ) AC_ARG_WITH([pie], [ --with-pie Build Position Independent Executables if possible], [ if test "x$withval" = "xno"; then use_pie=no fi if test "x$withval" = "xyes"; then use_pie=yes fi ] ) if test "x$use_pie" = "x"; then use_pie=no fi if test "x$use_toolchain_hardening" != "x1" && test "x$use_pie" = "xauto"; then # Turn off automatic PIE when toolchain hardening is off. use_pie=no fi if test "x$use_pie" = "xauto"; then # Automatic PIE requires gcc >= 4.x AC_MSG_CHECKING([for gcc >= 4.x]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #if !defined(__GNUC__) || __GNUC__ < 4 #error gcc is too old #endif ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) use_pie=no ] ) fi if test "x$use_pie" != "xno"; then SAVED_CFLAGS="$CFLAGS" SAVED_LDFLAGS="$LDFLAGS" OSSH_CHECK_CFLAG_COMPILE([-fPIE]) OSSH_CHECK_LDFLAG_LINK([-pie]) # We use both -fPIE and -pie or neither. AC_MSG_CHECKING([whether both -fPIE and -pie are supported]) if echo "x $CFLAGS" | grep ' -fPIE' >/dev/null 2>&1 && \ echo "x $LDFLAGS" | grep ' -pie' >/dev/null 2>&1 ; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) CFLAGS="$SAVED_CFLAGS" LDFLAGS="$SAVED_LDFLAGS" fi fi AC_MSG_CHECKING([whether -fPIC is accepted]) SAVED_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fPIC" AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ exit(0); ]] )], [AC_MSG_RESULT([yes]) PICFLAG="-fPIC"; ], [AC_MSG_RESULT([no]) PICFLAG=""; ]) CFLAGS="$SAVED_CFLAGS" AC_SUBST([PICFLAG]) dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS([ \ auth_hostok \ auth_timeok \ Blowfish_initstate \ Blowfish_expandstate \ Blowfish_expand0state \ Blowfish_stream2word \ SHA256Update \ SHA384Update \ SHA512Update \ asprintf \ b64_ntop \ __b64_ntop \ b64_pton \ __b64_pton \ bcopy \ bcrypt_pbkdf \ bindresvport_sa \ blf_enc \ bzero \ cap_rights_limit \ clock \ closefrom \ close_range \ dirfd \ endgrent \ err \ errx \ explicit_bzero \ explicit_memset \ fchmod \ fchmodat \ fchown \ fchownat \ flock \ fnmatch \ freeaddrinfo \ freezero \ fstatfs \ fstatvfs \ futimes \ getaddrinfo \ getcwd \ getentropy \ getgrouplist \ getline \ getnameinfo \ getopt \ getpagesize \ getpeereid \ getpeerucred \ getpgid \ _getpty \ getrlimit \ getrandom \ getsid \ getttyent \ glob \ group_from_gid \ inet_aton \ inet_ntoa \ inet_ntop \ innetgr \ killpg \ llabs \ localtime_r \ login_getcapbool \ login_getpwclass \ memmem \ memmove \ memset_s \ mkdtemp \ ngetaddrinfo \ nsleep \ ogetaddrinfo \ openlog_r \ pledge \ poll \ ppoll \ prctl \ procctl \ pselect \ pstat \ raise \ readpassphrase \ reallocarray \ realpath \ recvmsg \ recallocarray \ rresvport_af \ sendmsg \ setdtablesize \ setegid \ setenv \ seteuid \ setgroupent \ setgroups \ setlinebuf \ setlogin \ setpassent\ setpcred \ setproctitle \ setregid \ setreuid \ setrlimit \ setsid \ setvbuf \ sigaction \ sigvec \ snprintf \ socketpair \ statfs \ statvfs \ strcasestr \ strdup \ strerror \ strlcat \ strlcpy \ strmode \ strndup \ strnlen \ strnvis \ strptime \ strsignal \ strtonum \ strtoll \ strtoul \ strtoull \ sysconf \ tcgetpgrp \ timegm \ timingsafe_bcmp \ truncate \ unsetenv \ updwtmpx \ utimensat \ user_from_uid \ usleep \ vasprintf \ vsnprintf \ waitpid \ warn \ ]) AC_MSG_CHECKING([whether compiler supports __builtin_popcount]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ int x = 123, y; y = __builtin_popcount(123); exit(y == 6 ? 0 : -1); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([MISSING_BUILTIN_POPCOUNT], [1], [Define if your compiler lacks __builtin_popcount]) ] ) AC_CHECK_DECLS([bzero, memmem]) dnl Wide character support. AC_CHECK_FUNCS([mblen mbtowc nl_langinfo wcwidth]) TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes} AC_MSG_CHECKING([for utf8 locale support]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[ char *loc = setlocale(LC_CTYPE, "en_US.UTF-8"); if (loc != NULL) exit(0); exit(1); ]])], AC_MSG_RESULT(yes), [AC_MSG_RESULT(no) TEST_SSH_UTF8=no], AC_MSG_WARN([cross compiling: assuming yes]) ) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ return (isblank('a')); ]])], [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) disable_pkcs11= AC_ARG_ENABLE([pkcs11], [ --disable-pkcs11 disable PKCS#11 support code [no]], [ if test "x$enableval" = "xno" ; then disable_pkcs11=1 fi ] ) disable_sk= AC_ARG_ENABLE([security-key], [ --disable-security-key disable U2F/FIDO support code [no]], [ if test "x$enableval" = "xno" ; then disable_sk=1 fi ] ) enable_sk_internal= AC_ARG_WITH([security-key-builtin], [ --with-security-key-builtin include builtin U2F/FIDO support], [ enable_sk_internal=$withval ] ) enable_sk_standalone= AC_ARG_WITH([security-key-standalone], [ --with-security-key-standalone build standalone sk-libfido2 SecurityKeyProvider], [ enable_sk_standalone=$withval ] ) AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include const char *gai_strerror(int); ]], [[ char *str; str = gai_strerror(0); ]])], [ AC_DEFINE([HAVE_CONST_GAI_STRERROR_PROTO], [1], [Define if gai_strerror() returns const char *])], [])]) AC_SEARCH_LIBS([nanosleep], [rt posix4], [AC_DEFINE([HAVE_NANOSLEEP], [1], [Some systems put nanosleep outside of libc])]) AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Have clock_gettime])]) dnl check if we need -D_REENTRANT for localtime_r declaration. AC_CHECK_DECL([localtime_r], [], [ saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -D_REENTRANT" unset ac_cv_have_decl_localtime_r AC_CHECK_DECL([localtime_r], [], [ CPPFLAGS="$saved_CPPFLAGS" ], [ #include ] ) ], [ #include ] ) dnl Make sure prototypes are defined for these before using them. AC_CHECK_DECL([strsep], [AC_CHECK_FUNCS([strsep])], [], [ #ifdef HAVE_STRING_H # include #endif ]) dnl tcsendbreak might be a macro AC_CHECK_DECL([tcsendbreak], [AC_DEFINE([HAVE_TCSENDBREAK])], [AC_CHECK_FUNCS([tcsendbreak])], [#include ] ) AC_CHECK_DECLS([h_errno], , ,[#include ]) AC_CHECK_DECLS([SHUT_RD, getpeereid], , , [ #include #include #include ]) AC_CHECK_DECLS([O_NONBLOCK], , , [ #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_FCNTL_H # include #endif ]) AC_CHECK_DECLS([ftruncate, getentropy], , , [ #include #include ]) AC_CHECK_DECLS([readv, writev], , , [ #include #include #include ]) AC_CHECK_DECLS([MAXSYMLINKS], , , [ #include ]) AC_CHECK_DECLS([offsetof], , , [ #include ]) # extra bits for select(2) AC_CHECK_DECLS([howmany, NFDBITS], [], [], [[ #include #include #ifdef HAVE_SYS_SYSMACROS_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif ]]) AC_CHECK_TYPES([fd_mask], [], [], [[ #include #include #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif ]]) AC_CHECK_FUNCS([setresuid], [ dnl Some platorms have setresuid that isn't implemented, test for this AC_MSG_CHECKING([if setresuid seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ errno=0; setresuid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0); ]])], [AC_MSG_RESULT([yes])], [AC_DEFINE([BROKEN_SETRESUID], [1], [Define if your setresuid() is broken]) AC_MSG_RESULT([not implemented])], [AC_MSG_WARN([cross compiling: not checking setresuid])] ) ]) AC_CHECK_FUNCS([setresgid], [ dnl Some platorms have setresgid that isn't implemented, test for this AC_MSG_CHECKING([if setresgid seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ errno=0; setresgid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0); ]])], [AC_MSG_RESULT([yes])], [AC_DEFINE([BROKEN_SETRESGID], [1], [Define if your setresgid() is broken]) AC_MSG_RESULT([not implemented])], [AC_MSG_WARN([cross compiling: not checking setresuid])] ) ]) AC_MSG_CHECKING([for working fflush(NULL)]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[fflush(NULL); exit(0);]])], AC_MSG_RESULT([yes]), [AC_MSG_RESULT([no]) AC_DEFINE([FFLUSH_NULL_BUG], [1], [define if fflush(NULL) does not work])], AC_MSG_WARN([cross compiling: assuming working]) ) dnl Checks for time functions AC_CHECK_FUNCS([gettimeofday time]) dnl Checks for utmp functions AC_CHECK_FUNCS([endutent getutent getutid getutline pututline setutent]) AC_CHECK_FUNCS([utmpname]) dnl Checks for utmpx functions AC_CHECK_FUNCS([endutxent getutxent getutxid getutxline getutxuser pututxline]) AC_CHECK_FUNCS([setutxdb setutxent utmpxname]) dnl Checks for lastlog functions AC_CHECK_FUNCS([getlastlogxbyname]) AC_CHECK_FUNC([daemon], [AC_DEFINE([HAVE_DAEMON], [1], [Define if your libraries define daemon()])], [AC_CHECK_LIB([bsd], [daemon], [LIBS="$LIBS -lbsd"; AC_DEFINE([HAVE_DAEMON])])] ) AC_CHECK_FUNC([getpagesize], [AC_DEFINE([HAVE_GETPAGESIZE], [1], [Define if your libraries define getpagesize()])], [AC_CHECK_LIB([ucb], [getpagesize], [LIBS="$LIBS -lucb"; AC_DEFINE([HAVE_GETPAGESIZE])])] ) # Check for broken snprintf if test "x$ac_cv_func_snprintf" = "xyes" ; then AC_MSG_CHECKING([whether snprintf correctly terminates long strings]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[ char b[5]; snprintf(b,5,"123456789"); exit(b[4]!='\0'); ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_SNPRINTF], [1], [Define if your snprintf is busted]) AC_MSG_WARN([****** Your snprintf() function is broken, complain to your vendor]) ], [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ] ) fi if test "x$ac_cv_func_snprintf" = "xyes" ; then AC_MSG_CHECKING([whether snprintf understands %zu]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ size_t a = 1, b = 2; char z[128]; snprintf(z, sizeof z, "%zu%zu", a, b); exit(strcmp(z, "12")); ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_SNPRINTF], [1], [snprintf does not understand %zu]) ], [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ] ) fi # We depend on vsnprintf returning the right thing on overflow: the # number of characters it tried to create (as per SUSv3) if test "x$ac_cv_func_vsnprintf" = "xyes" ; then AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include int x_snprintf(char *str, size_t count, const char *fmt, ...) { size_t ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); return ret; } ]], [[ char x[1]; if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) return 1; if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) return 1; return 0; ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_SNPRINTF], [1], [Define if your snprintf is busted]) AC_MSG_WARN([****** Your vsnprintf() function is broken, complain to your vendor]) ], [ AC_MSG_WARN([cross compiling: Assuming working vsnprintf()]) ] ) fi # On systems where [v]snprintf is broken, but is declared in stdio, # check that the fmt argument is const char * or just char *. # This is only useful for when BROKEN_SNPRINTF AC_MSG_CHECKING([whether snprintf can declare const char *fmt]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include int snprintf(char *a, size_t b, const char *c, ...) { return 0; } ]], [[ snprintf(0, 0, 0); ]])], [AC_MSG_RESULT([yes]) AC_DEFINE([SNPRINTF_CONST], [const], [Define as const if snprintf() can declare const char *fmt])], [AC_MSG_RESULT([no]) AC_DEFINE([SNPRINTF_CONST], [/* not const */])]) # Check for missing getpeereid (or equiv) support NO_PEERCHECK="" if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then AC_MSG_CHECKING([whether system supports SO_PEERCRED getsockopt]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[int i = SO_PEERCRED;]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_SO_PEERCRED], [1], [Have PEERCRED socket option]) ], [AC_MSG_RESULT([no]) NO_PEERCHECK=1 ]) fi dnl make sure that openpty does not reacquire controlling terminal if test ! -z "$check_for_openpty_ctty_bug"; then AC_MSG_CHECKING([if openpty correctly handles controlling tty]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #ifdef HAVE_PTY_H # include #endif #include #include #include ]], [[ pid_t pid; int fd, ptyfd, ttyfd, status; pid = fork(); if (pid < 0) { /* failed */ exit(1); } else if (pid > 0) { /* parent */ waitpid(pid, &status, 0); if (WIFEXITED(status)) exit(WEXITSTATUS(status)); else exit(2); } else { /* child */ close(0); close(1); close(2); setsid(); openpty(&ptyfd, &ttyfd, NULL, NULL, NULL); fd = open("/dev/tty", O_RDWR | O_NOCTTY); if (fd >= 0) exit(3); /* Acquired ctty: broken */ else exit(0); /* Did not acquire ctty: OK */ } ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) ], [ AC_MSG_RESULT([cross-compiling, assuming yes]) ] ) fi if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then AC_MSG_CHECKING([if getaddrinfo seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include #define TEST_PORT "2222" ]], [[ int err, sock; struct addrinfo *gai_ai, *ai, hints; char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); exit(1); } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { if (ai->ai_family != AF_INET6) continue; err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV); if (err != 0) { if (err == EAI_SYSTEM) perror("getnameinfo EAI_SYSTEM"); else fprintf(stderr, "getnameinfo failed: %s\n", gai_strerror(err)); exit(2); } sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock < 0) perror("socket"); if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { if (errno == EBADF) exit(3); } } exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_GETADDRINFO]) ], [ AC_MSG_RESULT([cross-compiling, assuming yes]) ] ) fi if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_aix_broken_getaddrinfo" = "x1"; then AC_MSG_CHECKING([if getaddrinfo seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include #define TEST_PORT "2222" ]], [[ int err, sock; struct addrinfo *gai_ai, *ai, hints; char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); exit(1); } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV); if (ai->ai_family == AF_INET && err != 0) { perror("getnameinfo"); exit(2); } } exit(0); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([AIX_GETNAMEINFO_HACK], [1], [Define if you have a getaddrinfo that fails for the all-zeros IPv6 address]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_GETADDRINFO]) ], [ AC_MSG_RESULT([cross-compiling, assuming no]) ] ) fi if test "x$ac_cv_func_getaddrinfo" = "xyes"; then AC_CHECK_DECLS(AI_NUMERICSERV, , , [#include #include #include ]) fi if test "x$check_for_conflicting_getspnam" = "x1"; then AC_MSG_CHECKING([for conflicting getspnam in shadow.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ exit(0); ]])], [ AC_MSG_RESULT([no]) ], [ AC_MSG_RESULT([yes]) AC_DEFINE([GETSPNAM_CONFLICTING_DEFS], [1], [Conflicting defs for getspnam]) ] ) fi dnl NetBSD added an strnvis and unfortunately made it incompatible with the dnl existing one in OpenBSD and Linux's libbsd (the former having existed dnl for over ten years). Despite this incompatibility being reported during dnl development (see http://gnats.netbsd.org/44977) they still shipped it. dnl Even more unfortunately FreeBSD and later MacOS picked up this incompatible dnl implementation. Try to detect this mess, and assume the only safe option dnl if we're cross compiling. dnl dnl OpenBSD, 2001: strnvis(char *dst, const char *src, size_t dlen, int flag); dnl NetBSD: 2012, strnvis(char *dst, size_t dlen, const char *src, int flag); if test "x$ac_cv_func_strnvis" = "xyes"; then AC_MSG_CHECKING([for working strnvis]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include static void sighandler(int sig) { _exit(1); } ]], [[ char dst[16]; signal(SIGSEGV, sighandler); if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0) exit(0); exit(1) ]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis detected broken])], [AC_MSG_WARN([cross compiling: assuming broken]) AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis assumed broken])] ) fi AC_MSG_CHECKING([if SA_RESTARTed signals interrupt select()]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #ifdef HAVE_SYS_SELECT # include #endif #include #include #include #include #include static void sighandler(int sig) { } ]], [[ int r; pid_t pid; struct sigaction sa; sa.sa_handler = sighandler; sa.sa_flags = SA_RESTART; (void)sigaction(SIGTERM, &sa, NULL); if ((pid = fork()) == 0) { /* child */ pid = getppid(); sleep(1); kill(pid, SIGTERM); sleep(1); if (getppid() == pid) /* if parent did not exit, shoot it */ kill(pid, SIGKILL); exit(0); } else { /* parent */ r = select(0, NULL, NULL, NULL, NULL); } exit(r == -1 ? 0 : 1); ]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_DEFINE([NO_SA_RESTART], [1], [SA_RESTARTed signals do no interrupt select])], [AC_MSG_WARN([cross compiling: assuming yes])] ) AC_CHECK_FUNCS([getpgrp],[ AC_MSG_CHECKING([if getpgrp accepts zero args]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[$ac_includes_default]], [[ getpgrp(); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([GETPGRP_VOID], [1], [getpgrp takes zero args])], [ AC_MSG_RESULT([no]) AC_DEFINE([GETPGRP_VOID], [0], [getpgrp takes one arg])] ) ]) # Search for OpenSSL saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" openssl_bin_PATH="$PATH" AC_ARG_WITH([ssl-dir], [ --with-ssl-dir=PATH Specify path to OpenSSL installation ], [ if test "x$openssl" = "xno" ; then AC_MSG_ERROR([cannot use --with-ssl-dir when OpenSSL disabled]) fi if test "x$withval" != "xno" ; then case "$withval" in # Relative paths ./*|../*) withval="`pwd`/$withval" esac if test -d "$withval/lib"; then libcrypto_path="${withval}/lib" elif test -d "$withval/lib64"; then libcrypto_path="$withval/lib64" else # Built but not installed libcrypto_path="${withval}" fi if test -n "${rpath_opt}"; then LDFLAGS="-L${libcrypto_path} ${rpath_opt}${libcrypto_path} ${LDFLAGS}" else LDFLAGS="-L${libcrypto_path} ${LDFLAGS}" fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi dnl Ensure specified openssl binary works, eg it can dnl find its runtime libraries, before trying to use. if test -x "${withval}/bin/openssl" && \ "${withval}/bin/openssl" version >/dev/null 2>&1; then openssl_bin_PATH="${withval}/bin${PATH_SEPARATOR}${PATH}" elif test -x "${withval}/apps/openssl" && \ "${withval}/apps/openssl" version >/dev/null 2>&1; then openssl_bin_PATH="${withval}/apps${PATH_SEPARATOR}${PATH}" fi fi ] ) AC_PATH_PROGS([openssl_bin], openssl, [], [$openssl_bin_PATH]) AC_SUBST(OPENSSL_BIN, [${openssl_bin}]) AC_ARG_WITH([openssl-header-check], [ --without-openssl-header-check Disable OpenSSL version consistency check], [ if test "x$withval" = "xno" ; then openssl_check_nonfatal=1 fi ] ) openssl_engine=no AC_ARG_WITH([ssl-engine], [ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ], [ if test "x$withval" != "xno" ; then if test "x$openssl" = "xno" ; then AC_MSG_ERROR([cannot use --with-ssl-engine when OpenSSL disabled]) fi openssl_engine=yes fi ] ) nocrypto_saved_LIBS="$LIBS" if test "x$openssl" = "xyes" ; then LIBS="-lcrypto $LIBS" CHANNELLIBS="-lcrypto $CHANNELLIBS" AC_TRY_LINK_FUNC([RAND_add], , [AC_MSG_ERROR([*** working libcrypto not found, check config.log])]) AC_CHECK_HEADER([openssl/opensslv.h], , [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])]) # Determine OpenSSL header version AC_MSG_CHECKING([OpenSSL header version]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #define DATA "conftest.sslincver" ]], [[ FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); if ((rc = fprintf(fd, "%08lx (%s)\n", (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) < 0) exit(1); exit(0); ]])], [ ssl_header_ver=`cat conftest.sslincver` AC_MSG_RESULT([$ssl_header_ver]) ], [ AC_MSG_RESULT([failed]) AC_MSG_ERROR([OpenSSL version test program failed.]) ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) # Determining OpenSSL library version is version dependent. AC_CHECK_FUNCS([OpenSSL_version OpenSSL_version_num]) # Determine OpenSSL library version AC_MSG_CHECKING([OpenSSL library version]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #define DATA "conftest.ssllibver" ]], [[ FILE *f; /* We need these legacy bits to warn for old libcrypto */ #ifndef OPENSSL_VERSION # define OPENSSL_VERSION SSLEAY_VERSION #endif #ifndef HAVE_OPENSSL_VERSION # define OpenSSL_version SSLeay_version #endif #ifndef HAVE_OPENSSL_VERSION_NUM # define OpenSSL_version_num SSLeay #endif if ((f = fopen(DATA, "w")) == NULL) exit(1); if (fprintf(f, "%08lx (%s)", (unsigned long)OpenSSL_version_num(), OpenSSL_version(OPENSSL_VERSION)) < 0) exit(1); #ifdef LIBRESSL_VERSION_NUMBER if (fprintf(f, " libressl-%08lx", LIBRESSL_VERSION_NUMBER) < 0) exit(1); #endif if (fputc('\n', f) == EOF || fclose(f) == EOF) exit(1); exit(0); ]])], [ sslver=`cat conftest.ssllibver` ssl_showver=`echo "$sslver" | sed 's/ libressl-.*//'` # Check version is supported. case "$sslver" in 100*|10100*) # 1.0.x, 1.1.0x AC_MSG_ERROR([OpenSSL >= 1.1.1 required (have "$ssl_showver")]) ;; 101*) ;; # 1.1.x 200*) # LibreSSL lver=`echo "$sslver" | sed 's/.*libressl-//'` case "$lver" in 2*|300*) # 2.x, 3.0.0 AC_MSG_ERROR([LibreSSL >= 3.1.0 required (have "$ssl_showver")]) ;; *) ;; # Assume all other versions are good. esac ;; 30*) # OpenSSL 3; we use the 1.1x API # https://openssl.org/policies/general/versioning-policy.html CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" ;; *) AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_showver")]) ;; esac AC_MSG_RESULT([$ssl_showver]) ], [ AC_MSG_RESULT([not found]) AC_MSG_ERROR([OpenSSL library not found.]) ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) case "$host" in x86_64-*) case "$sslver" in 3000004*) AC_MSG_ERROR([OpenSSL 3.0.4 has a potential RCE in its RSA implementation (CVE-2022-2274)]) ;; esac esac # Sanity check OpenSSL headers AC_MSG_CHECKING([whether OpenSSL's headers match the library]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) if test "x$openssl_check_nonfatal" = "x"; then AC_MSG_ERROR([Your OpenSSL headers do not match your library. Check config.log for details. If you are sure your installation is consistent, you can disable the check by running "./configure --without-openssl-header-check". Also see contrib/findssl.sh for help identifying header/library mismatches. ]) else AC_MSG_WARN([Your OpenSSL headers do not match your library. Check config.log for details. Also see contrib/findssl.sh for help identifying header/library mismatches.]) fi ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) AC_MSG_CHECKING([if programs using OpenSSL functions will link]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[ ERR_load_crypto_strings(); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) LIBS="$LIBS -ldl" AC_MSG_CHECKING([if programs using OpenSSL need -ldl]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[ ERR_load_crypto_strings(); ]])], [ AC_MSG_RESULT([yes]) CHANNELLIBS="$CHANNELLIBS -ldl" ], [ AC_MSG_RESULT([no]) ] ) ] ) AC_CHECK_FUNCS([ \ BN_is_prime_ex \ DES_crypt \ DSA_generate_parameters_ex \ EVP_DigestSign \ EVP_DigestVerify \ EVP_DigestFinal_ex \ EVP_DigestInit_ex \ EVP_MD_CTX_cleanup \ EVP_MD_CTX_copy_ex \ EVP_MD_CTX_init \ HMAC_CTX_init \ RSA_generate_key_ex \ RSA_get_default_method \ ]) # OpenSSL_add_all_algorithms may be a macro. AC_CHECK_FUNC(OpenSSL_add_all_algorithms, AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a function]), AC_CHECK_DECL(OpenSSL_add_all_algorithms, AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a macro]), , [[#include ]] ) ) # LibreSSL/OpenSSL API differences AC_CHECK_FUNCS([ \ EVP_CIPHER_CTX_iv \ EVP_CIPHER_CTX_iv_noconst \ EVP_CIPHER_CTX_get_iv \ EVP_CIPHER_CTX_get_updated_iv \ EVP_CIPHER_CTX_set_iv \ ]) if test "x$openssl_engine" = "xyes" ; then AC_MSG_CHECKING([for OpenSSL ENGINE support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([USE_OPENSSL_ENGINE], [1], [Enable OpenSSL engine support]) ], [ AC_MSG_ERROR([OpenSSL ENGINE support not found]) ]) fi # Check for OpenSSL without EVP_aes_{192,256}_cbc AC_MSG_CHECKING([whether OpenSSL lacks support for AES 192/256]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL); ]])], [ AC_MSG_RESULT([no]) ], [ AC_MSG_RESULT([yes]) AC_DEFINE([OPENSSL_LOBOTOMISED_AES], [1], [libcrypto is missing AES 192 and 256 bit functions]) ] ) AC_MSG_CHECKING([if EVP_DigestUpdate returns an int]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ if(EVP_DigestUpdate(NULL, NULL,0)) exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([OPENSSL_EVP_DIGESTUPDATE_VOID], [1], [Define if EVP_DigestUpdate returns void]) ] ) # Check for various EVP support in OpenSSL AC_CHECK_FUNCS([EVP_sha256 EVP_sha384 EVP_sha512 EVP_chacha20]) # Check complete ECC support in OpenSSL AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); const EVP_MD *m = EVP_sha256(); /* We need this too */ ]])], [ AC_MSG_RESULT([yes]) enable_nistp256=1 ], [ AC_MSG_RESULT([no]) ] ) AC_MSG_CHECKING([whether OpenSSL has NID_secp384r1]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); const EVP_MD *m = EVP_sha384(); /* We need this too */ ]])], [ AC_MSG_RESULT([yes]) enable_nistp384=1 ], [ AC_MSG_RESULT([no]) ] ) AC_MSG_CHECKING([whether OpenSSL has NID_secp521r1]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ ]])], [ AC_MSG_RESULT([yes]) AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include #include ]],[[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ exit(e == NULL || m == NULL); ]])], [ AC_MSG_RESULT([yes]) enable_nistp521=1 ], [ AC_MSG_RESULT([no]) ], [ AC_MSG_WARN([cross-compiling: assuming yes]) enable_nistp521=1 ] )], AC_MSG_RESULT([no]) ) if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \ test x$enable_nistp521 = x1; then AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC]) AC_CHECK_FUNCS([EC_KEY_METHOD_new]) openssl_ecc=yes else openssl_ecc=no fi if test x$enable_nistp256 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP256], [1], [libcrypto has NID_X9_62_prime256v1]) else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp256 \ ecdh-sha2-nistp256 \ ecdsa-sha2-nistp256-cert-v01@openssh.com" fi if test x$enable_nistp384 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1]) else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp384 \ ecdh-sha2-nistp384 \ ecdsa-sha2-nistp384-cert-v01@openssh.com" fi if test x$enable_nistp521 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1]) else unsupported_algorithms="$unsupported_algorithms \ ecdh-sha2-nistp521 \ ecdsa-sha2-nistp521 \ ecdsa-sha2-nistp521-cert-v01@openssh.com" fi # Check libcrypto ED25519 support AC_CHECK_FUNCS([EVP_PKEY_get_raw_public_key]) AC_CHECK_FUNCS([EVP_PKEY_get_raw_private_key]) AC_MSG_CHECKING([whether OpenSSL has ED25519 support]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[ unsigned char buf[64]; memset(buf, 0, sizeof(buf)); exit(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, buf, sizeof(buf)) == NULL); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([OPENSSL_HAS_ED25519], [1], [libcrypto has ed25519 support]) ], [ AC_MSG_RESULT([no]) ] ) fi # PKCS11/U2F depend on OpenSSL and dlopen(). enable_pkcs11=yes enable_sk=yes AC_CHECK_DECL([OPENSSL_IS_AWSLC], [enable_pkcs11="disabled; PKCS#11 not supported with AWS-LC"], [], [#include ] ) if test "x$openssl" != "xyes" ; then enable_pkcs11="disabled; missing libcrypto" fi if test "x$ac_cv_func_dlopen" != "xyes" ; then enable_pkcs11="disabled; missing dlopen(3)" enable_sk="disabled; missing dlopen(3)" fi if test "x$ac_cv_have_decl_RTLD_NOW" != "xyes" ; then enable_pkcs11="disabled; missing RTLD_NOW" enable_sk="disabled; missing RTLD_NOW" fi if test ! -z "$disable_pkcs11" ; then enable_pkcs11="disabled by user" fi if test ! -z "$disable_sk" ; then enable_sk="disabled by user" fi AC_MSG_CHECKING([whether to enable PKCS11]) if test "x$enable_pkcs11" = "xyes" ; then AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support]) fi AC_MSG_RESULT([$enable_pkcs11]) AC_MSG_CHECKING([whether to enable U2F]) if test "x$enable_sk" = "xyes" ; then AC_DEFINE([ENABLE_SK], [], [Enable for U2F/FIDO support]) AC_SUBST(SK_DUMMY_LIBRARY, [regress/misc/sk-dummy/sk-dummy.so]) else # Do not try to build sk-dummy library. AC_SUBST(SK_DUMMY_LIBRARY, [""]) fi AC_MSG_RESULT([$enable_sk]) # Now check for built-in security key support. if test "x$enable_sk" = "xyes" -a "x$enable_sk_internal" != "xno" ; then use_pkgconfig_for_libfido2= if test "x$PKGCONFIG" != "xno"; then AC_MSG_CHECKING([if $PKGCONFIG knows about libfido2]) if "$PKGCONFIG" libfido2; then AC_MSG_RESULT([yes]) use_pkgconfig_for_libfido2=yes else AC_MSG_RESULT([no]) fi fi if test "x$use_pkgconfig_for_libfido2" = "xyes"; then LIBFIDO2=`$PKGCONFIG --libs libfido2` CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libfido2`" else LIBFIDO2="-lfido2 -lcbor" fi OTHERLIBS=`echo $LIBFIDO2 | sed 's/-lfido2//'` fido2_error= AC_CHECK_LIB([fido2], [fido_init], [ ], [ fido2_error="missing/unusable libfido2" ], [ $OTHERLIBS ] ) AC_CHECK_HEADER([fido.h], [], [ fido2_error="missing fido.h from libfido2" ]) AC_CHECK_HEADER([fido/credman.h], [], [ fido2_error="missing fido/credman.h from libfido2" ], [ #include ] ) AC_MSG_CHECKING([for usable libfido2 installation]) if test ! -z "$fido2_error" ; then AC_MSG_RESULT([$fido2_error]) if test "x$enable_sk_internal" = "xyes" ; then AC_MSG_ERROR([No usable libfido2 library/headers found]) fi LIBFIDO2="" else AC_MSG_RESULT([yes]) AC_SUBST([LIBFIDO2]) AC_DEFINE([ENABLE_SK_INTERNAL], [], [Enable for built-in U2F/FIDO support]) enable_sk="built-in" saved_LIBS="$LIBS" LIBS="$LIBFIDO2 $LIBS" AC_CHECK_FUNCS([ \ fido_assert_set_clientdata \ fido_cred_prot \ fido_cred_set_prot \ fido_cred_set_clientdata \ fido_dev_get_touch_begin \ fido_dev_get_touch_status \ fido_dev_supports_cred_prot \ fido_dev_is_winhello \ ]) LIBS="$saved_LIBS" fi fi # Check for standalone SecurityKeyProvider AC_MSG_CHECKING([whether to build standalone sk-libfido2]) if test "x$enable_sk_standalone" = "xyes" ; then AC_MSG_RESULT([yes]) AC_SUBST([SK_STANDALONE], [sk-libfido2$SHLIBEXT]) else AC_MSG_RESULT([no]) AC_SUBST([SK_STANDALONE], [""]) fi AC_CHECK_FUNCS([ \ arc4random \ arc4random_buf \ arc4random_stir \ arc4random_uniform \ ]) ### Configure cryptographic random number support # Check whether OpenSSL seeds itself if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ exit(RAND_status() == 1 ? 0 : 1); ]])], [ OPENSSL_SEEDS_ITSELF=yes AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ], [ AC_MSG_WARN([cross compiling: assuming yes]) # This is safe, since we will fatal() at runtime if # OpenSSL is not seeded correctly. OPENSSL_SEEDS_ITSELF=yes ] ) fi # PRNGD TCP socket AC_ARG_WITH([prngd-port], [ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT], [ case "$withval" in no) withval="" ;; [[0-9]]*) ;; *) AC_MSG_ERROR([You must specify a numeric port number for --with-prngd-port]) ;; esac if test ! -z "$withval" ; then PRNGD_PORT="$withval" AC_DEFINE_UNQUOTED([PRNGD_PORT], [$PRNGD_PORT], [Port number of PRNGD/EGD random number socket]) fi ] ) # PRNGD Unix domain socket AC_ARG_WITH([prngd-socket], [ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)], [ case "$withval" in yes) withval="/var/run/egd-pool" ;; no) withval="" ;; /*) ;; *) AC_MSG_ERROR([You must specify an absolute path to the entropy socket]) ;; esac if test ! -z "$withval" ; then if test ! -z "$PRNGD_PORT" ; then AC_MSG_ERROR([You may not specify both a PRNGD/EGD port and socket]) fi if test ! -r "$withval" ; then AC_MSG_WARN([Entropy socket is not readable]) fi PRNGD_SOCKET="$withval" AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"], [Location of PRNGD/EGD random number socket]) fi ], [ # Check for existing socket only if we don't have a random device already if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then AC_MSG_CHECKING([for PRNGD/EGD socket]) # Insert other locations here for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then PRNGD_SOCKET="$sock" AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"]) break; fi done if test ! -z "$PRNGD_SOCKET" ; then AC_MSG_RESULT([$PRNGD_SOCKET]) else AC_MSG_RESULT([not found]) fi fi ] ) # Which randomness source do we use? if test ! -z "$PRNGD_PORT" ; then RAND_MSG="PRNGd port $PRNGD_PORT" elif test ! -z "$PRNGD_SOCKET" ; then RAND_MSG="PRNGd socket $PRNGD_SOCKET" elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then AC_DEFINE([OPENSSL_PRNG_ONLY], [1], [Define if you want the OpenSSL internally seeded PRNG only]) RAND_MSG="OpenSSL internal ONLY" elif test "x$openssl" = "xno" ; then AC_MSG_WARN([OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible]) else AC_MSG_ERROR([OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options]) fi LIBS="$nocrypto_saved_LIBS" saved_LIBS="$LIBS" AC_CHECK_LIB([iaf], [ia_openinfo], [ LIBS="$LIBS -liaf" AC_CHECK_FUNCS([set_id], [SSHDLIBS="$SSHDLIBS -liaf" AC_DEFINE([HAVE_LIBIAF], [1], [Define if system has libiaf that supports set_id]) ]) ]) LIBS="$saved_LIBS" # Check for crypt() in libcrypt. If we have it, we only need it for sshd. saved_LIBS="$LIBS" AC_CHECK_LIB([crypt], [crypt], [ LIBS="-lcrypt $LIBS" SSHDLIBS="-lcrypt $SSHDLIBS" ]) AC_CHECK_FUNCS([crypt]) LIBS="$saved_LIBS" # Check for PAM libs PAM_MSG="no" AC_ARG_WITH([pam], [ --with-pam Enable PAM support ], [ if test "x$withval" != "xno" ; then if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \ test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then AC_MSG_ERROR([PAM headers not found]) fi saved_LIBS="$LIBS" AC_CHECK_LIB([dl], [dlopen], , ) AC_CHECK_LIB([pam], [pam_set_item], , [AC_MSG_ERROR([*** libpam missing])]) AC_CHECK_FUNCS([pam_getenvlist]) AC_CHECK_FUNCS([pam_putenv]) LIBS="$saved_LIBS" PAM_MSG="yes" SSHDLIBS="$SSHDLIBS -lpam" AC_DEFINE([USE_PAM], [1], [Define if you want to enable PAM support]) if test $ac_cv_lib_dl_dlopen = yes; then case "$LIBS" in *-ldl*) # libdl already in LIBS ;; *) SSHDLIBS="$SSHDLIBS -ldl" ;; esac fi fi ] ) AC_ARG_WITH([pam-service], [ --with-pam-service=name Specify PAM service name ], [ if test "x$withval" != "xno" && \ test "x$withval" != "xyes" ; then AC_DEFINE_UNQUOTED([SSHD_PAM_SERVICE], ["$withval"], [sshd PAM service name]) fi ] ) # Check for older PAM if test "x$PAM_MSG" = "xyes" ; then # Check PAM strerror arguments (old PAM) AC_MSG_CHECKING([whether pam_strerror takes only one argument]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #if defined(HAVE_SECURITY_PAM_APPL_H) #include #elif defined (HAVE_PAM_PAM_APPL_H) #include #endif ]], [[ (void)pam_strerror((pam_handle_t *)NULL, -1); ]])], [AC_MSG_RESULT([no])], [ AC_DEFINE([HAVE_OLD_PAM], [1], [Define if you have an old version of PAM which takes only one argument to pam_strerror]) AC_MSG_RESULT([yes]) PAM_MSG="yes (old library)" ]) fi case "$host" in *-*-cygwin*) SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER ;; *) SSH_PRIVSEP_USER=sshd ;; esac AC_ARG_WITH([privsep-user], [ --with-privsep-user=user Specify non-privileged user for privilege separation], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then SSH_PRIVSEP_USER=$withval fi ] ) if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], [CYGWIN_SSH_PRIVSEP_USER], [Cygwin function to fetch non-privileged user for privilege separation]) else AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"], [non-privileged user for privilege separation]) fi AC_SUBST([SSH_PRIVSEP_USER]) if test "x$have_linux_no_new_privs" = "x1" ; then AC_CHECK_DECL([SECCOMP_MODE_FILTER], [have_seccomp_filter=1], , [ #include #include ]) fi if test "x$have_seccomp_filter" = "x1" ; then AC_MSG_CHECKING([kernel for seccomp_filter support]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ int i = $seccomp_audit_arch; errno = 0; prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0); exit(errno == EFAULT ? 0 : 1); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) # Disable seccomp filter as a target have_seccomp_filter=0 ] ) fi AC_CHECK_MEMBERS([struct pollfd.fd], [], [], [[ #include #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif ]]) AC_CHECK_TYPES([nfds_t], , , [ #include #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif ]) # Decide which sandbox style to use sandbox_arg="" AC_ARG_WITH([sandbox], [ --with-sandbox=style Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter)], [ if test "x$withval" = "xyes" ; then sandbox_arg="" else sandbox_arg="$withval" fi ] ) if test "x$sandbox_arg" != "xno"; then # POSIX specifies that poll() "shall fail with EINVAL if the nfds argument # is greater than OPEN_MAX". On some platforms that includes implementions # of select in userspace on top of poll() so check both work with rlimit # NOFILES so check that both work before enabling the rlimit sandbox. AC_MSG_CHECKING([if select and/or poll works with descriptor rlimit]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #ifdef HAVE_SYS_TIME_H # include #endif #include #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_POLL_H # include #elif HAVE_SYS_POLL_H # include #endif #include #include #include ]],[[ struct rlimit rl_zero; int fd, r; fd_set fds; struct timeval tv; #ifdef HAVE_POLL struct pollfd pfd; #endif fd = open("/dev/null", O_RDONLY); FD_ZERO(&fds); FD_SET(fd, &fds); rl_zero.rlim_cur = rl_zero.rlim_max = 0; setrlimit(RLIMIT_FSIZE, &rl_zero); setrlimit(RLIMIT_NOFILE, &rl_zero); tv.tv_sec = 1; tv.tv_usec = 0; r = select(fd+1, &fds, NULL, NULL, &tv); if (r == -1) exit(1); #ifdef HAVE_POLL pfd.fd = fd; pfd.events = POLLIN; r = poll(&pfd, 1, 1); if (r == -1) exit(2); #endif exit(0); ]])], [AC_MSG_RESULT([yes]) select_works_with_rlimit=yes], [AC_MSG_RESULT([no]) select_works_with_rlimit=no], [AC_MSG_WARN([cross compiling: assuming no]) select_works_with_rlimit=no] ) AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include ]],[[ struct rlimit rl_zero; int r; rl_zero.rlim_cur = rl_zero.rlim_max = 0; r = setrlimit(RLIMIT_NOFILE, &rl_zero); exit (r == -1 ? 1 : 0); ]])], [AC_MSG_RESULT([yes]) rlimit_nofile_zero_works=yes], [AC_MSG_RESULT([no]) rlimit_nofile_zero_works=no], [AC_MSG_WARN([cross compiling: assuming yes]) rlimit_nofile_zero_works=yes] ) AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]],[[ struct rlimit rl_zero; rl_zero.rlim_cur = rl_zero.rlim_max = 0; exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0); ]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_DEFINE(SANDBOX_SKIP_RLIMIT_FSIZE, 1, [setrlimit RLIMIT_FSIZE works])], [AC_MSG_WARN([cross compiling: assuming yes])] ) fi if test "x$sandbox_arg" = "xdarwin" || \ ( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \ test "x$ac_cv_header_sandbox_h" = "xyes") ; then test "x$ac_cv_func_sandbox_init" != "xyes" -o \ "x$ac_cv_header_sandbox_h" != "xyes" && \ AC_MSG_ERROR([Darwin seatbelt sandbox requires sandbox.h and sandbox_init function]) SANDBOX_STYLE="darwin" AC_DEFINE([SANDBOX_DARWIN], [1], [Sandbox using Darwin sandbox_init(3)]) elif test "x$sandbox_arg" = "xseccomp_filter" || \ ( test -z "$sandbox_arg" && \ test "x$have_seccomp_filter" = "x1" && \ test "x$ac_cv_header_elf_h" = "xyes" && \ test "x$ac_cv_header_linux_audit_h" = "xyes" && \ test "x$ac_cv_header_linux_filter_h" = "xyes" && \ test "x$seccomp_audit_arch" != "x" && \ test "x$have_linux_no_new_privs" = "x1" && \ test "x$ac_cv_func_prctl" = "xyes" ) ; then test "x$seccomp_audit_arch" = "x" && \ AC_MSG_ERROR([seccomp_filter sandbox not supported on $host]) test "x$have_linux_no_new_privs" != "x1" && \ AC_MSG_ERROR([seccomp_filter sandbox requires PR_SET_NO_NEW_PRIVS]) test "x$have_seccomp_filter" != "x1" && \ AC_MSG_ERROR([seccomp_filter sandbox requires seccomp headers]) test "x$ac_cv_func_prctl" != "xyes" && \ AC_MSG_ERROR([seccomp_filter sandbox requires prctl function]) SANDBOX_STYLE="seccomp_filter" AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter]) elif test "x$sandbox_arg" = "xcapsicum" || \ ( test -z "$sandbox_arg" && \ test "x$disable_capsicum" != "xyes" && \ test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \ test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \ AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header]) test "x$ac_cv_func_cap_rights_limit" != "xyes" && \ AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function]) SANDBOX_STYLE="capsicum" AC_DEFINE([SANDBOX_CAPSICUM], [1], [Sandbox using capsicum]) elif test "x$sandbox_arg" = "xrlimit" || \ ( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" && \ test "x$select_works_with_rlimit" = "xyes" && \ test "x$rlimit_nofile_zero_works" = "xyes" ) ; then test "x$ac_cv_func_setrlimit" != "xyes" && \ AC_MSG_ERROR([rlimit sandbox requires setrlimit function]) test "x$select_works_with_rlimit" != "xyes" && \ AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit]) SANDBOX_STYLE="rlimit" AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)]) elif test "x$sandbox_arg" = "xsolaris" || \ ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then SANDBOX_STYLE="solaris" AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges]) elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \ test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then SANDBOX_STYLE="none" AC_DEFINE([SANDBOX_NULL], [1], [no privsep sandboxing]) else AC_MSG_ERROR([unsupported --with-sandbox]) fi # Cheap hack to ensure NEWS-OS libraries are arranged right. if test ! -z "$SONY" ; then LIBS="$LIBS -liberty"; fi # Check for long long datatypes AC_CHECK_TYPES([long long, unsigned long long, long double]) # Check datatype sizes AC_CHECK_SIZEOF([short int]) AC_CHECK_SIZEOF([int]) AC_CHECK_SIZEOF([long int]) AC_CHECK_SIZEOF([long long int]) AC_CHECK_SIZEOF([time_t], [], [[ #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_TIME_H # include #endif ]] ) # Sanity check long long for some platforms (AIX) if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then ac_cv_sizeof_long_long_int=0 fi # compute LLONG_MIN and LLONG_MAX if we don't know them. if test -z "$have_llong_max" && test -z "$have_long_long_max"; then AC_MSG_CHECKING([for max value of long long]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include /* Why is this so damn hard? */ #ifdef __GNUC__ # undef __GNUC__ #endif #define __USE_ISOC99 #include #define DATA "conftest.llminmax" #define my_abs(a) ((a) < 0 ? ((a) * -1) : (a)) /* * printf in libc on some platforms (eg old Tru64) does not understand %lld so * we do this the hard way. */ static int fprint_ll(FILE *f, long long n) { unsigned int i; int l[sizeof(long long) * 8]; if (n < 0) if (fprintf(f, "-") < 0) return -1; for (i = 0; n != 0; i++) { l[i] = my_abs(n % 10); n /= 10; } do { if (fprintf(f, "%d", l[--i]) < 0) return -1; } while (i != 0); if (fprintf(f, " ") < 0) return -1; return 0; } ]], [[ FILE *f; long long i, llmin, llmax = 0; if((f = fopen(DATA,"w")) == NULL) exit(1); #if defined(LLONG_MIN) && defined(LLONG_MAX) fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n"); llmin = LLONG_MIN; llmax = LLONG_MAX; #else fprintf(stderr, "Calculating LLONG_MIN and LLONG_MAX\n"); /* This will work on one's complement and two's complement */ for (i = 1; i > llmax; i <<= 1, i++) llmax = i; llmin = llmax + 1LL; /* wrap */ #endif /* Sanity check */ if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax || llmax - 1 > llmax || llmin == llmax || llmin == 0 || llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) { fprintf(f, "unknown unknown\n"); exit(2); } if (fprint_ll(f, llmin) < 0) exit(3); if (fprint_ll(f, llmax) < 0) exit(4); if (fclose(f) < 0) exit(5); exit(0); ]])], [ llong_min=`$AWK '{print $1}' conftest.llminmax` llong_max=`$AWK '{print $2}' conftest.llminmax` AC_MSG_RESULT([$llong_max]) AC_DEFINE_UNQUOTED([LLONG_MAX], [${llong_max}LL], [max value of long long calculated by configure]) AC_MSG_CHECKING([for min value of long long]) AC_MSG_RESULT([$llong_min]) AC_DEFINE_UNQUOTED([LLONG_MIN], [${llong_min}LL], [min value of long long calculated by configure]) ], [ AC_MSG_RESULT([not found]) ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) fi AC_CHECK_DECLS([UINT32_MAX], , , [[ #ifdef HAVE_SYS_LIMITS_H # include #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef HAVE_STDINT_H # include #endif ]]) # More checks for data types AC_CACHE_CHECK([for u_int type], ac_cv_have_u_int, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int a; a = 1;]])], [ ac_cv_have_u_int="yes" ], [ ac_cv_have_u_int="no" ]) ]) if test "x$ac_cv_have_u_int" = "xyes" ; then AC_DEFINE([HAVE_U_INT], [1], [define if you have u_int data type]) have_u_int=1 fi AC_CACHE_CHECK([for intXX_t types], ac_cv_have_intxx_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])], [ ac_cv_have_intxx_t="yes" ], [ ac_cv_have_intxx_t="no" ]) ]) if test "x$ac_cv_have_intxx_t" = "xyes" ; then AC_DEFINE([HAVE_INTXX_T], [1], [define if you have intxx_t data type]) have_intxx_t=1 fi if (test -z "$have_intxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then AC_MSG_CHECKING([for intXX_t types in stdint.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_INTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi AC_CACHE_CHECK([for int64_t type], ac_cv_have_int64_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #ifdef HAVE_STDINT_H # include #endif #include #ifdef HAVE_SYS_BITYPES_H # include #endif ]], [[ int64_t a; a = 1; ]])], [ ac_cv_have_int64_t="yes" ], [ ac_cv_have_int64_t="no" ]) ]) if test "x$ac_cv_have_int64_t" = "xyes" ; then AC_DEFINE([HAVE_INT64_T], [1], [define if you have int64_t data type]) fi AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])], [ ac_cv_have_u_intxx_t="yes" ], [ ac_cv_have_u_intxx_t="no" ]) ]) if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then AC_DEFINE([HAVE_U_INTXX_T], [1], [define if you have u_intxx_t data type]) have_u_intxx_t=1 fi if test -z "$have_u_intxx_t" ; then AC_MSG_CHECKING([for u_intXX_t types in sys/socket.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_U_INTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi AC_CACHE_CHECK([for u_int64_t types], ac_cv_have_u_int64_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int64_t a; a = 1;]])], [ ac_cv_have_u_int64_t="yes" ], [ ac_cv_have_u_int64_t="no" ]) ]) if test "x$ac_cv_have_u_int64_t" = "xyes" ; then AC_DEFINE([HAVE_U_INT64_T], [1], [define if you have u_int64_t data type]) have_u_int64_t=1 fi if (test -z "$have_u_int64_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then AC_MSG_CHECKING([for u_int64_t type in sys/bitypes.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int64_t a; a = 1]])], [ AC_DEFINE([HAVE_U_INT64_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi if test -z "$have_u_intxx_t" ; then AC_CACHE_CHECK([for uintXX_t types], ac_cv_have_uintxx_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ]])], [ ac_cv_have_uintxx_t="yes" ], [ ac_cv_have_uintxx_t="no" ]) ]) if test "x$ac_cv_have_uintxx_t" = "xyes" ; then AC_DEFINE([HAVE_UINTXX_T], [1], [define if you have uintxx_t data type]) fi fi if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then AC_MSG_CHECKING([for uintXX_t types in stdint.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_UINTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_inttypes_h" = "xyes") then AC_MSG_CHECKING([for uintXX_t types in inttypes.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_UINTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then AC_MSG_CHECKING([for intXX_t and u_intXX_t types in sys/bitypes.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ int8_t a; int16_t b; int32_t c; u_int8_t e; u_int16_t f; u_int32_t g; a = b = c = e = f = g = 1; ]])], [ AC_DEFINE([HAVE_U_INTXX_T]) AC_DEFINE([HAVE_INTXX_T]) AC_MSG_RESULT([yes]) ], [AC_MSG_RESULT([no]) ]) fi AC_CACHE_CHECK([for u_char], ac_cv_have_u_char, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_char foo; foo = 125; ]])], [ ac_cv_have_u_char="yes" ], [ ac_cv_have_u_char="no" ]) ]) if test "x$ac_cv_have_u_char" = "xyes" ; then AC_DEFINE([HAVE_U_CHAR], [1], [define if you have u_char data type]) fi AC_CHECK_TYPES([intmax_t, uintmax_t], , , [ #include #ifdef HAVE_STDINT_H # include #endif ]) TYPE_SOCKLEN_T AC_CHECK_TYPES([sig_atomic_t, sighandler_t], , , [#include ]) AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [ #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif ]) AC_CHECK_MEMBERS([struct statfs.f_files, struct statfs.f_flags], [], [], [[ #include #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif ]]) AC_CHECK_TYPES([in_addr_t, in_port_t], , , [#include #include ]) AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ size_t foo; foo = 1235; ]])], [ ac_cv_have_size_t="yes" ], [ ac_cv_have_size_t="no" ]) ]) if test "x$ac_cv_have_size_t" = "xyes" ; then AC_DEFINE([HAVE_SIZE_T], [1], [define if you have size_t data type]) fi AC_CACHE_CHECK([for ssize_t], ac_cv_have_ssize_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ ssize_t foo; foo = 1235; ]])], [ ac_cv_have_ssize_t="yes" ], [ ac_cv_have_ssize_t="no" ]) ]) if test "x$ac_cv_have_ssize_t" = "xyes" ; then AC_DEFINE([HAVE_SSIZE_T], [1], [define if you have ssize_t data type]) fi AC_CACHE_CHECK([for clock_t], ac_cv_have_clock_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ clock_t foo; foo = 1235; ]])], [ ac_cv_have_clock_t="yes" ], [ ac_cv_have_clock_t="no" ]) ]) if test "x$ac_cv_have_clock_t" = "xyes" ; then AC_DEFINE([HAVE_CLOCK_T], [1], [define if you have clock_t data type]) fi AC_CACHE_CHECK([for sa_family_t], ac_cv_have_sa_family_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ sa_family_t foo; foo = 1235; ]])], [ ac_cv_have_sa_family_t="yes" ], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]], [[ sa_family_t foo; foo = 1235; ]])], [ ac_cv_have_sa_family_t="yes" ], [ ac_cv_have_sa_family_t="no" ] ) ]) ]) if test "x$ac_cv_have_sa_family_t" = "xyes" ; then AC_DEFINE([HAVE_SA_FAMILY_T], [1], [define if you have sa_family_t data type]) fi AC_CACHE_CHECK([for pid_t], ac_cv_have_pid_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ pid_t foo; foo = 1235; ]])], [ ac_cv_have_pid_t="yes" ], [ ac_cv_have_pid_t="no" ]) ]) if test "x$ac_cv_have_pid_t" = "xyes" ; then AC_DEFINE([HAVE_PID_T], [1], [define if you have pid_t data type]) fi AC_CACHE_CHECK([for mode_t], ac_cv_have_mode_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ mode_t foo; foo = 1235; ]])], [ ac_cv_have_mode_t="yes" ], [ ac_cv_have_mode_t="no" ]) ]) if test "x$ac_cv_have_mode_t" = "xyes" ; then AC_DEFINE([HAVE_MODE_T], [1], [define if you have mode_t data type]) fi AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_storage s; ]])], [ ac_cv_have_struct_sockaddr_storage="yes" ], [ ac_cv_have_struct_sockaddr_storage="no" ]) ]) if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_SOCKADDR_STORAGE], [1], [define if you have struct sockaddr_storage data type]) fi AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_in6 s; s.sin6_family = 0; ]])], [ ac_cv_have_struct_sockaddr_in6="yes" ], [ ac_cv_have_struct_sockaddr_in6="no" ]) ]) if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_SOCKADDR_IN6], [1], [define if you have struct sockaddr_in6 data type]) fi AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct in6_addr s; s.s6_addr[0] = 0; ]])], [ ac_cv_have_struct_in6_addr="yes" ], [ ac_cv_have_struct_in6_addr="no" ]) ]) if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_IN6_ADDR], [1], [define if you have struct in6_addr data type]) dnl Now check for sin6_scope_id AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id], , , [ #ifdef HAVE_SYS_TYPES_H #include #endif #include ]) fi AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]], [[ struct addrinfo s; s.ai_flags = AI_PASSIVE; ]])], [ ac_cv_have_struct_addrinfo="yes" ], [ ac_cv_have_struct_addrinfo="no" ]) ]) if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_ADDRINFO], [1], [define if you have struct addrinfo data type]) fi AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ struct timeval tv; tv.tv_sec = 1;]])], [ ac_cv_have_struct_timeval="yes" ], [ ac_cv_have_struct_timeval="no" ]) ]) if test "x$ac_cv_have_struct_timeval" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_TIMEVAL], [1], [define if you have struct timeval]) have_struct_timeval=1 fi AC_CACHE_CHECK([for struct timespec], ac_cv_have_struct_timespec, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_TIME_H # include #endif ]], [[ struct timespec ts; ts.tv_sec = 1;]])], [ ac_cv_have_struct_timespec="yes" ], [ ac_cv_have_struct_timespec="no" ]) ]) if test "x$ac_cv_have_struct_timespec" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_TIMESPEC], [1], [define if you have struct timespec]) have_struct_timespec=1 fi # We need int64_t or else certain parts of the compile will fail. if test "x$ac_cv_have_int64_t" = "xno" && \ test "x$ac_cv_sizeof_long_int" != "x8" && \ test "x$ac_cv_sizeof_long_long_int" = "x0" ; then echo "OpenSSH requires int64_t support. Contact your vendor or install" echo "an alternative compiler (I.E., GCC) before continuing." echo "" exit 1; else dnl test snprintf (broken on SCO w/gcc) AC_RUN_IFELSE( [AC_LANG_SOURCE([[ #include #include #include #ifdef HAVE_SNPRINTF int main(void) { char buf[50]; char expected_out[50]; int mazsize = 50 ; #if (SIZEOF_LONG_INT == 8) long int num = 0x7fffffffffffffff; #else long long num = 0x7fffffffffffffffll; #endif strcpy(expected_out, "9223372036854775807"); #if (SIZEOF_LONG_INT == 8) snprintf(buf, mazsize, "%ld", num); #else snprintf(buf, mazsize, "%lld", num); #endif if(strcmp(buf, expected_out) != 0) exit(1); exit(0); } #else int main(void) { exit(0); } #endif ]])], [ true ], [ AC_DEFINE([BROKEN_SNPRINTF]) ], AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ) fi dnl Checks for structure members OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmp.h], [HAVE_HOST_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmpx.h], [HAVE_HOST_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([syslen], [utmpx.h], [HAVE_SYSLEN_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_pid], [utmp.h], [HAVE_PID_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmp.h], [HAVE_TYPE_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmpx.h], [HAVE_TYPE_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmp.h], [HAVE_TV_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmp.h], [HAVE_ID_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmpx.h], [HAVE_ID_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmp.h], [HAVE_ADDR_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmpx.h], [HAVE_ADDR_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmp.h], [HAVE_ADDR_V6_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmpx.h], [HAVE_ADDR_V6_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_exit], [utmp.h], [HAVE_EXIT_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmp.h], [HAVE_TIME_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_ss], [utmpx.h], [HAVE_SS_IN_UTMPX]) AC_CHECK_MEMBERS([struct stat.st_blksize]) AC_CHECK_MEMBERS([struct stat.st_mtim]) AC_CHECK_MEMBERS([struct stat.st_mtime]) AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class, struct passwd.pw_change, struct passwd.pw_expire], [], [], [[ #include #include ]]) AC_CHECK_MEMBER([struct __res_state.retrans], [], [AC_DEFINE([__res_state], [state], [Define if we don't have struct __res_state in resolv.h])], [[ #include #if HAVE_SYS_TYPES_H # include #endif #include #include #include ]]) AC_CHECK_MEMBER([struct sockaddr_in.sin_len], [AC_DEFINE([SOCK_HAS_LEN], [1], [sockaddr_in has sin_len])], [], [AC_LANG_SOURCE([[ #include #include #include ]])] ) AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], ac_cv_have_ss_family_in_struct_ss, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_storage s; s.ss_family = 1; ]])], [ ac_cv_have_ss_family_in_struct_ss="yes" ], [ ac_cv_have_ss_family_in_struct_ss="no" ]) ]) if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then AC_DEFINE([HAVE_SS_FAMILY_IN_SS], [1], [Fields in struct sockaddr_storage]) fi AC_CACHE_CHECK([for __ss_family field in struct sockaddr_storage], ac_cv_have___ss_family_in_struct_ss, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_storage s; s.__ss_family = 1; ]])], [ ac_cv_have___ss_family_in_struct_ss="yes" ], [ ac_cv_have___ss_family_in_struct_ss="no" ]) ]) if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then AC_DEFINE([HAVE___SS_FAMILY_IN_SS], [1], [Fields in struct sockaddr_storage]) fi dnl make sure we're using the real structure members and not defines AC_CACHE_CHECK([for msg_accrights field in struct msghdr], ac_cv_have_accrights_in_msghdr, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ #ifdef msg_accrights #error "msg_accrights is a macro" exit(1); #endif struct msghdr m; m.msg_accrights = 0; exit(0); ]])], [ ac_cv_have_accrights_in_msghdr="yes" ], [ ac_cv_have_accrights_in_msghdr="no" ] ) ]) if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then AC_DEFINE([HAVE_ACCRIGHTS_IN_MSGHDR], [1], [Define if your system uses access rights style file descriptor passing]) fi AC_MSG_CHECKING([if struct statvfs.f_fsid is integral type]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif ]], [[ struct statvfs s; s.f_fsid = 0; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([if fsid_t has member val]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ fsid_t t; t.val[0] = 0; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([FSID_HAS_VAL], [1], [fsid_t has member val]) ], [ AC_MSG_RESULT([no]) ]) AC_MSG_CHECKING([if f_fsid has member __val]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ fsid_t t; t.__val[0] = 0; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([FSID_HAS___VAL], [1], [fsid_t has member __val]) ], [ AC_MSG_RESULT([no]) ]) ]) AC_CACHE_CHECK([for msg_control field in struct msghdr], ac_cv_have_control_in_msghdr, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ #ifdef msg_control #error "msg_control is a macro" exit(1); #endif struct msghdr m; m.msg_control = 0; exit(0); ]])], [ ac_cv_have_control_in_msghdr="yes" ], [ ac_cv_have_control_in_msghdr="no" ] ) ]) if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then AC_DEFINE([HAVE_CONTROL_IN_MSGHDR], [1], [Define if your system uses ancillary data style file descriptor passing]) fi AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern char *__progname; printf("%s", __progname); ]])], [ ac_cv_libc_defines___progname="yes" ], [ ac_cv_libc_defines___progname="no" ]) ]) if test "x$ac_cv_libc_defines___progname" = "xyes" ; then AC_DEFINE([HAVE___PROGNAME], [1], [Define if libc defines __progname]) fi AC_CACHE_CHECK([whether $CC implements __FUNCTION__], ac_cv_cc_implements___FUNCTION__, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ printf("%s", __FUNCTION__); ]])], [ ac_cv_cc_implements___FUNCTION__="yes" ], [ ac_cv_cc_implements___FUNCTION__="no" ]) ]) if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then AC_DEFINE([HAVE___FUNCTION__], [1], [Define if compiler implements __FUNCTION__]) fi AC_CACHE_CHECK([whether $CC implements __func__], ac_cv_cc_implements___func__, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ printf("%s", __func__); ]])], [ ac_cv_cc_implements___func__="yes" ], [ ac_cv_cc_implements___func__="no" ]) ]) if test "x$ac_cv_cc_implements___func__" = "xyes" ; then AC_DEFINE([HAVE___func__], [1], [Define if compiler implements __func__]) fi AC_CACHE_CHECK([whether va_copy exists], ac_cv_have_va_copy, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include va_list x,y; ]], [[ va_copy(x,y); ]])], [ ac_cv_have_va_copy="yes" ], [ ac_cv_have_va_copy="no" ]) ]) if test "x$ac_cv_have_va_copy" = "xyes" ; then AC_DEFINE([HAVE_VA_COPY], [1], [Define if va_copy exists]) fi AC_CACHE_CHECK([whether __va_copy exists], ac_cv_have___va_copy, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include va_list x,y; ]], [[ __va_copy(x,y); ]])], [ ac_cv_have___va_copy="yes" ], [ ac_cv_have___va_copy="no" ]) ]) if test "x$ac_cv_have___va_copy" = "xyes" ; then AC_DEFINE([HAVE___VA_COPY], [1], [Define if __va_copy exists]) fi AC_CACHE_CHECK([whether getopt has optreset support], ac_cv_have_getopt_optreset, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern int optreset; optreset = 0; ]])], [ ac_cv_have_getopt_optreset="yes" ], [ ac_cv_have_getopt_optreset="no" ]) ]) if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then AC_DEFINE([HAVE_GETOPT_OPTRESET], [1], [Define if your getopt(3) defines and uses optreset]) fi AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);]])], [ ac_cv_libc_defines_sys_errlist="yes" ], [ ac_cv_libc_defines_sys_errlist="no" ]) ]) if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then AC_DEFINE([HAVE_SYS_ERRLIST], [1], [Define if your system defines sys_errlist[]]) fi AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern int sys_nerr; printf("%i", sys_nerr);]])], [ ac_cv_libc_defines_sys_nerr="yes" ], [ ac_cv_libc_defines_sys_nerr="no" ]) ]) if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then AC_DEFINE([HAVE_SYS_NERR], [1], [Define if your system defines sys_nerr]) fi # Check libraries needed by DNS fingerprint support AC_SEARCH_LIBS([getrrsetbyname], [resolv], [AC_DEFINE([HAVE_GETRRSETBYNAME], [1], [Define if getrrsetbyname() exists])], [ # Needed by our getrrsetbyname() AC_SEARCH_LIBS([res_query], [resolv]) AC_SEARCH_LIBS([dn_expand], [resolv]) AC_MSG_CHECKING([if res_query will link]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include #include ]], [[ res_query (0, 0, 0, 0, 0); ]])], AC_MSG_RESULT([yes]), [AC_MSG_RESULT([no]) saved_LIBS="$LIBS" LIBS="$LIBS -lresolv" AC_MSG_CHECKING([for res_query in -lresolv]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include #include ]], [[ res_query (0, 0, 0, 0, 0); ]])], [AC_MSG_RESULT([yes])], [LIBS="$saved_LIBS" AC_MSG_RESULT([no])]) ]) AC_CHECK_FUNCS([_getshort _getlong]) AC_CHECK_DECLS([_getshort, _getlong], , , [#include #include ]) AC_CHECK_MEMBER([HEADER.ad], [AC_DEFINE([HAVE_HEADER_AD], [1], [Define if HEADER.ad exists in arpa/nameser.h])], , [#include ]) ]) AC_MSG_CHECKING([if struct __res_state _res is an extern]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #if HAVE_SYS_TYPES_H # include #endif #include #include #include extern struct __res_state _res; ]], [[ struct __res_state *volatile p = &_res; /* force resolution of _res */ return 0; ]],)], [AC_MSG_RESULT([yes]) AC_DEFINE([HAVE__RES_EXTERN], [1], [Define if you have struct __res_state _res as an extern]) ], [ AC_MSG_RESULT([no]) ] ) # Check whether user wants SELinux support SELINUX_MSG="no" LIBSELINUX="" AC_ARG_WITH([selinux], [ --with-selinux Enable SELinux support], [ if test "x$withval" != "xno" ; then save_LIBS="$LIBS" AC_DEFINE([WITH_SELINUX], [1], [Define if you want SELinux support.]) SELINUX_MSG="yes" AC_CHECK_HEADER([selinux/selinux.h], , AC_MSG_ERROR([SELinux support requires selinux.h header])) AC_CHECK_LIB([selinux], [setexeccon], [ LIBSELINUX="-lselinux" LIBS="$LIBS -lselinux" ], AC_MSG_ERROR([SELinux support requires libselinux library])) AC_CHECK_FUNCS([getseuserbyname get_default_context_with_level]) LIBS="$save_LIBS $LIBSELINUX" fi ] ) AC_SUBST([SSHDLIBS]) # Check whether user wants Kerberos 5 support KRB5_MSG="no" AC_ARG_WITH([kerberos5], [ --with-kerberos5=PATH Enable Kerberos 5 support], [ if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then KRB5ROOT="/usr/local" else KRB5ROOT=${withval} fi AC_DEFINE([KRB5], [1], [Define if you want Kerberos 5 support]) KRB5_MSG="yes" use_pkgconfig_for_krb5= if test "x$PKGCONFIG" != "xno"; then AC_MSG_CHECKING([if $PKGCONFIG knows about kerberos5]) if "$PKGCONFIG" krb5; then AC_MSG_RESULT([yes]) use_pkgconfig_for_krb5=yes else AC_MSG_RESULT([no]) fi fi if test "x$use_pkgconfig_for_krb5" = "xyes"; then K5CFLAGS=`$PKGCONFIG --cflags krb5` K5LIBS=`$PKGCONFIG --libs krb5` CPPFLAGS="$CPPFLAGS $K5CFLAGS" AC_MSG_CHECKING([for gssapi support]) if "$PKGCONFIG" krb5-gssapi; then AC_MSG_RESULT([yes]) AC_DEFINE([GSSAPI], [1], [Define this if you want GSSAPI support in the version 2 protocol]) GSSCFLAGS="`$PKGCONFIG --cflags krb5-gssapi`" GSSLIBS="`$PKGCONFIG --libs krb5-gssapi`" CPPFLAGS="$CPPFLAGS $GSSCFLAGS" else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING([whether we are using Heimdal]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *tmp = heimdal_version; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HEIMDAL], [1], [Define this if you are using the Heimdal version of Kerberos V5]) ], [AC_MSG_RESULT([no]) ]) else AC_PATH_TOOL([KRB5CONF], [krb5-config], [$KRB5ROOT/bin/krb5-config], [$KRB5ROOT/bin:$PATH]) if test -x $KRB5CONF ; then K5CFLAGS="`$KRB5CONF --cflags`" K5LIBS="`$KRB5CONF --libs`" CPPFLAGS="$CPPFLAGS $K5CFLAGS" AC_MSG_CHECKING([for gssapi support]) if $KRB5CONF | grep gssapi >/dev/null ; then AC_MSG_RESULT([yes]) AC_DEFINE([GSSAPI], [1], [Define this if you want GSSAPI support in the version 2 protocol]) GSSCFLAGS="`$KRB5CONF --cflags gssapi`" GSSLIBS="`$KRB5CONF --libs gssapi`" CPPFLAGS="$CPPFLAGS $GSSCFLAGS" else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING([whether we are using Heimdal]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *tmp = heimdal_version; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HEIMDAL], [1], [Define this if you are using the Heimdal version of Kerberos V5]) ], [AC_MSG_RESULT([no]) ]) else CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" AC_MSG_CHECKING([whether we are using Heimdal]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *tmp = heimdal_version; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HEIMDAL]) K5LIBS="-lkrb5" K5LIBS="$K5LIBS -lcom_err -lasn1" AC_CHECK_LIB([roken], [net_write], [K5LIBS="$K5LIBS -lroken"]) AC_CHECK_LIB([des], [des_cbc_encrypt], [K5LIBS="$K5LIBS -ldes"]) ], [ AC_MSG_RESULT([no]) K5LIBS="-lkrb5 -lk5crypto -lcom_err" ]) AC_SEARCH_LIBS([dn_expand], [resolv]) AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context], [ AC_DEFINE([GSSAPI]) GSSLIBS="-lgssapi_krb5" ], [ AC_CHECK_LIB([gssapi], [gss_init_sec_context], [ AC_DEFINE([GSSAPI]) GSSLIBS="-lgssapi" ], [ AC_CHECK_LIB([gss], [gss_init_sec_context], [ AC_DEFINE([GSSAPI]) GSSLIBS="-lgss" ], AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail])) ]) ]) AC_CHECK_HEADER([gssapi.h], , [ unset ac_cv_header_gssapi_h CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" AC_CHECK_HEADERS([gssapi.h], , AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail]) ) ] ) oldCPP="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" AC_CHECK_HEADER([gssapi_krb5.h], , [ CPPFLAGS="$oldCPP" ]) fi fi if test -n "${rpath_opt}" ; then LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib" fi if test ! -z "$blibpath" ; then blibpath="$blibpath:${KRB5ROOT}/lib" fi AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h]) AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h]) AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h]) AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1], [Define this if you want to use libkafs' AFS support])]) AC_CHECK_DECLS([GSS_C_NT_HOSTBASED_SERVICE], [], [], [[ #ifdef HAVE_GSSAPI_H # include #elif defined(HAVE_GSSAPI_GSSAPI_H) # include #endif #ifdef HAVE_GSSAPI_GENERIC_H # include #elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) # include #endif ]]) saved_LIBS="$LIBS" LIBS="$LIBS $K5LIBS" AC_CHECK_FUNCS([krb5_cc_new_unique krb5_get_error_message krb5_free_error_message]) LIBS="$saved_LIBS" fi ] ) AC_SUBST([GSSLIBS]) AC_SUBST([K5LIBS]) AC_SUBST([CHANNELLIBS]) # Looking for programs, paths and files PRIVSEP_PATH=/var/empty AC_ARG_WITH([privsep-path], [ --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then PRIVSEP_PATH=$withval fi ] ) AC_SUBST([PRIVSEP_PATH]) AC_ARG_WITH([xauth], [ --with-xauth=PATH Specify path to xauth program ], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then xauth_path=$withval fi ], [ TestPath="$PATH" TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin" TestPath="${TestPath}${PATH_SEPARATOR}/usr/bin/X11" TestPath="${TestPath}${PATH_SEPARATOR}/usr/X11R6/bin" TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin" AC_PATH_PROG([xauth_path], [xauth], , [$TestPath]) if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then xauth_path="/usr/openwin/bin/xauth" fi ] ) STRIP_OPT=-s AC_ARG_ENABLE([strip], [ --disable-strip Disable calling strip(1) on install], [ if test "x$enableval" = "xno" ; then STRIP_OPT= fi ] ) AC_SUBST([STRIP_OPT]) if test -z "$xauth_path" ; then XAUTH_PATH="undefined" AC_SUBST([XAUTH_PATH]) else AC_DEFINE_UNQUOTED([XAUTH_PATH], ["$xauth_path"], [Define if xauth is found in your path]) XAUTH_PATH=$xauth_path AC_SUBST([XAUTH_PATH]) fi dnl # --with-maildir=/path/to/mail gets top priority. dnl # if maildir is set in the platform case statement above we use that. dnl # Otherwise we run a program to get the dir from system headers. dnl # We first look for _PATH_MAILDIR then MAILDIR then _PATH_MAIL dnl # If we find _PATH_MAILDIR we do nothing because that is what dnl # session.c expects anyway. Otherwise we set to the value found dnl # stripping any trailing slash. If for some strage reason our program dnl # does not find what it needs, we default to /var/spool/mail. # Check for mail directory AC_ARG_WITH([maildir], [ --with-maildir=/path/to/mail Specify your system mail directory], [ if test "X$withval" != X && test "x$withval" != xno && \ test "x${withval}" != xyes; then AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$withval"], [Set this to your mail directory if you do not have _PATH_MAILDIR]) fi ],[ if test "X$maildir" != "X"; then AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"]) else AC_MSG_CHECKING([Discovering system mail directory]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_MAILLOCK_H #include #endif #define DATA "conftest.maildir" ]], [[ FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); #if defined (_PATH_MAILDIR) if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0) exit(1); #elif defined (MAILDIR) if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0) exit(1); #elif defined (_PATH_MAIL) if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0) exit(1); #else exit (2); #endif exit(0); ]])], [ maildir_what=`awk -F: '{print $1}' conftest.maildir` maildir=`awk -F: '{print $2}' conftest.maildir \ | sed 's|/$||'` AC_MSG_RESULT([Using: $maildir from $maildir_what]) if test "x$maildir_what" != "x_PATH_MAILDIR"; then AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"]) fi ], [ if test "X$ac_status" = "X2";then # our test program didn't find it. Default to /var/spool/mail AC_MSG_RESULT([Using: default value of /var/spool/mail]) AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["/var/spool/mail"]) else AC_MSG_RESULT([*** not found ***]) fi ], [ AC_MSG_WARN([cross compiling: use --with-maildir=/path/to/mail]) ] ) fi ] ) # maildir if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then AC_MSG_WARN([cross compiling: Disabling /dev/ptmx test]) disable_ptmx_check=yes fi if test -z "$no_dev_ptmx" ; then if test "x$disable_ptmx_check" != "xyes" ; then AC_CHECK_FILE(["/dev/ptmx"], [ AC_DEFINE_UNQUOTED([HAVE_DEV_PTMX], [1], [Define if you have /dev/ptmx]) have_dev_ptmx=1 ] ) fi fi if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then AC_CHECK_FILE(["/dev/ptc"], [ AC_DEFINE_UNQUOTED([HAVE_DEV_PTS_AND_PTC], [1], [Define if you have /dev/ptc]) have_dev_ptc=1 ] ) else AC_MSG_WARN([cross compiling: Disabling /dev/ptc test]) fi # Options from here on. Some of these are preset by platform above AC_ARG_WITH([mantype], [ --with-mantype=man|cat|doc Set man page type], [ case "$withval" in man|cat|doc) MANTYPE=$withval ;; *) AC_MSG_ERROR([invalid man type: $withval]) ;; esac ] ) if test -z "$MANTYPE"; then if ${MANDOC} ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=doc elif ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=doc elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=man else MANTYPE=cat fi fi AC_SUBST([MANTYPE]) if test "$MANTYPE" = "doc"; then mansubdir=man; else mansubdir=$MANTYPE; fi AC_SUBST([mansubdir]) # Whether to disable shadow password support AC_ARG_WITH([shadow], [ --without-shadow Disable shadow password support], [ if test "x$withval" = "xno" ; then AC_DEFINE([DISABLE_SHADOW]) disable_shadow=yes fi ] ) if test -z "$disable_shadow" ; then AC_MSG_CHECKING([if the systems has expire shadow information]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include struct spwd sp; ]], [[ sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ]])], [ sp_expire_available=yes ], [ ]) if test "x$sp_expire_available" = "xyes" ; then AC_MSG_RESULT([yes]) AC_DEFINE([HAS_SHADOW_EXPIRE], [1], [Define if you want to use shadow password expire field]) else AC_MSG_RESULT([no]) fi fi # Use ip address instead of hostname in $DISPLAY if test ! -z "$IPADDR_IN_DISPLAY" ; then DISPLAY_HACK_MSG="yes" AC_DEFINE([IPADDR_IN_DISPLAY], [1], [Define if you need to use IP address instead of hostname in $DISPLAY]) else DISPLAY_HACK_MSG="no" AC_ARG_WITH([ipaddr-display], [ --with-ipaddr-display Use ip address instead of hostname in $DISPLAY], [ if test "x$withval" != "xno" ; then AC_DEFINE([IPADDR_IN_DISPLAY]) DISPLAY_HACK_MSG="yes" fi ] ) fi # check for /etc/default/login and use it if present. AC_ARG_ENABLE([etc-default-login], [ --disable-etc-default-login Disable using PATH from /etc/default/login [no]], [ if test "x$enableval" = "xno"; then AC_MSG_NOTICE([/etc/default/login handling disabled]) etc_default_login=no else etc_default_login=yes fi ], [ if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then AC_MSG_WARN([cross compiling: not checking /etc/default/login]) etc_default_login=no else etc_default_login=yes fi ] ) if test "x$etc_default_login" != "xno"; then AC_CHECK_FILE(["/etc/default/login"], [ external_path_file=/etc/default/login ]) if test "x$external_path_file" = "x/etc/default/login"; then AC_DEFINE([HAVE_ETC_DEFAULT_LOGIN], [1], [Define if your system has /etc/default/login]) fi fi dnl BSD systems use /etc/login.conf so --with-default-path= has no effect if test $ac_cv_func_login_getcapbool = "yes" && \ test $ac_cv_header_login_cap_h = "yes" ; then external_path_file=/etc/login.conf fi # Whether to mess with the default path SERVER_PATH_MSG="(default)" AC_ARG_WITH([default-path], [ --with-default-path= Specify default $PATH environment for server], [ if test "x$external_path_file" = "x/etc/login.conf" ; then AC_MSG_WARN([ --with-default-path=PATH has no effect on this system. Edit /etc/login.conf instead.]) elif test "x$withval" != "xno" ; then if test ! -z "$external_path_file" ; then AC_MSG_WARN([ --with-default-path=PATH will only be used if PATH is not defined in $external_path_file .]) fi user_path="$withval" SERVER_PATH_MSG="$withval" fi ], [ if test "x$external_path_file" = "x/etc/login.conf" ; then AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf]) else if test ! -z "$external_path_file" ; then AC_MSG_WARN([ If PATH is defined in $external_path_file, ensure the path to scp is included, otherwise scp will not work.]) fi AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ /* find out what STDPATH is */ #include #include #ifdef HAVE_PATHS_H # include #endif #ifndef _PATH_STDPATH # ifdef _PATH_USERPATH /* Irix */ # define _PATH_STDPATH _PATH_USERPATH # else # define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" # endif #endif #include #include #include #define DATA "conftest.stdpath" ]], [[ FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0) exit(1); exit(0); ]])], [ user_path=`cat conftest.stdpath` ], [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ], [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ] ) # make sure $bindir is in USER_PATH so scp will work t_bindir="${bindir}" while echo "${t_bindir}" | egrep '\$\{|NONE/' >/dev/null 2>&1; do t_bindir=`eval echo ${t_bindir}` case $t_bindir in NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;; esac case $t_bindir in NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;; esac done echo $user_path | grep ":$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then echo $user_path | grep "^$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then user_path=$user_path:$t_bindir AC_MSG_RESULT([Adding $t_bindir to USER_PATH so scp will work]) fi fi fi ] ) if test "x$external_path_file" != "x/etc/login.conf" ; then AC_DEFINE_UNQUOTED([USER_PATH], ["$user_path"], [Specify default $PATH]) AC_SUBST([user_path]) fi # Set superuser path separately to user path AC_ARG_WITH([superuser-path], [ --with-superuser-path= Specify different path for super-user], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then AC_DEFINE_UNQUOTED([SUPERUSER_PATH], ["$withval"], [Define if you want a different $PATH for the superuser]) superuser_path=$withval fi ] ) AC_MSG_CHECKING([if we need to convert IPv4 in IPv6-mapped addresses]) IPV4_IN6_HACK_MSG="no" AC_ARG_WITH(4in6, [ --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses], [ if test "x$withval" != "xno" ; then AC_MSG_RESULT([yes]) AC_DEFINE([IPV4_IN_IPV6], [1], [Detect IPv4 in IPv6 mapped addresses and treat as IPv4]) IPV4_IN6_HACK_MSG="yes" else AC_MSG_RESULT([no]) fi ], [ if test "x$inet6_default_4in6" = "xyes"; then AC_MSG_RESULT([yes (default)]) AC_DEFINE([IPV4_IN_IPV6]) IPV4_IN6_HACK_MSG="yes" else AC_MSG_RESULT([no (default)]) fi ] ) # Whether to enable BSD auth support BSD_AUTH_MSG=no AC_ARG_WITH([bsd-auth], [ --with-bsd-auth Enable BSD auth support], [ if test "x$withval" != "xno" ; then AC_DEFINE([BSD_AUTH], [1], [Define if you have BSD auth support]) BSD_AUTH_MSG=yes fi ] ) # Where to place sshd.pid piddir=/var/run # make sure the directory exists if test ! -d $piddir ; then piddir=`eval echo ${sysconfdir}` case $piddir in NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;; esac fi AC_ARG_WITH([pid-dir], [ --with-pid-dir=PATH Specify location of sshd.pid file], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then piddir=$withval if test ! -d $piddir ; then AC_MSG_WARN([** no $piddir directory on this system **]) fi fi ] ) AC_DEFINE_UNQUOTED([_PATH_SSH_PIDDIR], ["$piddir"], [Specify location of ssh.pid]) AC_SUBST([piddir]) AC_ARG_ENABLE([fd-passing], [ --disable-fd-passing disable file descriptor passsing [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_FD_PASSING]) fi ] ) dnl allow user to disable some login recording features AC_ARG_ENABLE([lastlog], [ --disable-lastlog disable use of lastlog even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_LASTLOG]) fi ] ) AC_ARG_ENABLE([utmp], [ --disable-utmp disable use of utmp even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_UTMP]) fi ] ) AC_ARG_ENABLE([utmpx], [ --disable-utmpx disable use of utmpx even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_UTMPX], [1], [Define if you don't want to use utmpx]) fi ] ) AC_ARG_ENABLE([wtmp], [ --disable-wtmp disable use of wtmp even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_WTMP]) fi ] ) AC_ARG_ENABLE([wtmpx], [ --disable-wtmpx disable use of wtmpx even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_WTMPX], [1], [Define if you don't want to use wtmpx]) fi ] ) AC_ARG_ENABLE([libutil], [ --disable-libutil disable use of libutil (login() etc.) [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_LOGIN]) fi ] ) AC_ARG_ENABLE([pututline], [ --disable-pututline disable use of pututline() etc. ([uw]tmp) [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_PUTUTLINE], [1], [Define if you don't want to use pututline() etc. to write [uw]tmp]) fi ] ) AC_ARG_ENABLE([pututxline], [ --disable-pututxline disable use of pututxline() etc. ([uw]tmpx) [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_PUTUTXLINE], [1], [Define if you don't want to use pututxline() etc. to write [uw]tmpx]) fi ] ) AC_ARG_WITH([lastlog], [ --with-lastlog=FILE|DIR specify lastlog location [common locations]], [ if test "x$withval" = "xno" ; then AC_DEFINE([DISABLE_LASTLOG]) elif test -n "$withval" && test "x${withval}" != "xyes"; then conf_lastlog_location=$withval fi ] ) dnl lastlog, [uw]tmpx? detection dnl NOTE: set the paths in the platform section to avoid the dnl need for command-line parameters dnl lastlog and [uw]tmp are subject to a file search if all else fails dnl lastlog detection dnl NOTE: the code itself will detect if lastlog is a directory AC_MSG_CHECKING([if your system defines LASTLOG_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_LOGIN_H # include #endif ]], [[ char *lastlog = LASTLOG_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([if your system defines _PATH_LASTLOG]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif ]], [[ char *lastlog = _PATH_LASTLOG; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_lastlog_path=no ]) ]) if test -z "$conf_lastlog_location"; then if test x"$system_lastlog_path" = x"no" ; then for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do if (test -d "$f" || test -f "$f") ; then conf_lastlog_location=$f fi done if test -z "$conf_lastlog_location"; then AC_MSG_WARN([** Cannot find lastlog **]) dnl Don't define DISABLE_LASTLOG - that means we don't try wtmp/wtmpx fi fi fi if test -n "$conf_lastlog_location"; then AC_DEFINE_UNQUOTED([CONF_LASTLOG_FILE], ["$conf_lastlog_location"], [Define if you want to specify the path to your lastlog file]) fi dnl utmp detection AC_MSG_CHECKING([if your system defines UTMP_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_PATHS_H # include #endif ]], [[ char *utmp = UTMP_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_utmp_path=no ]) if test -z "$conf_utmp_location"; then if test x"$system_utmp_path" = x"no" ; then for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do if test -f $f ; then conf_utmp_location=$f fi done if test -z "$conf_utmp_location"; then AC_DEFINE([DISABLE_UTMP]) fi fi fi if test -n "$conf_utmp_location"; then AC_DEFINE_UNQUOTED([CONF_UTMP_FILE], ["$conf_utmp_location"], [Define if you want to specify the path to your utmp file]) fi dnl wtmp detection AC_MSG_CHECKING([if your system defines WTMP_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_PATHS_H # include #endif ]], [[ char *wtmp = WTMP_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_wtmp_path=no ]) if test -z "$conf_wtmp_location"; then if test x"$system_wtmp_path" = x"no" ; then for f in /usr/adm/wtmp /var/log/wtmp; do if test -f $f ; then conf_wtmp_location=$f fi done if test -z "$conf_wtmp_location"; then AC_DEFINE([DISABLE_WTMP]) fi fi fi if test -n "$conf_wtmp_location"; then AC_DEFINE_UNQUOTED([CONF_WTMP_FILE], ["$conf_wtmp_location"], [Define if you want to specify the path to your wtmp file]) fi dnl wtmpx detection AC_MSG_CHECKING([if your system defines WTMPX_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_PATHS_H # include #endif ]], [[ char *wtmpx = WTMPX_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_wtmpx_path=no ]) if test -z "$conf_wtmpx_location"; then if test x"$system_wtmpx_path" = x"no" ; then AC_DEFINE([DISABLE_WTMPX]) fi else AC_DEFINE_UNQUOTED([CONF_WTMPX_FILE], ["$conf_wtmpx_location"], [Define if you want to specify the path to your wtmpx file]) fi if test ! -z "$blibpath" ; then LDFLAGS="$LDFLAGS $blibflags$blibpath" AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile]) fi AC_CHECK_MEMBER([struct lastlog.ll_line], [], [ if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then AC_DEFINE([DISABLE_LASTLOG]) fi ], [ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_LASTLOG_H #include #endif ]) AC_CHECK_MEMBER([struct utmp.ut_line], [], [ AC_DEFINE([DISABLE_UTMP]) AC_DEFINE([DISABLE_WTMP]) ], [ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_LASTLOG_H #include #endif ]) dnl Adding -Werror to CFLAGS early prevents configure tests from running. dnl Add now. CFLAGS="$CFLAGS $werror_flags" if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then TEST_SSH_IPV6=no else TEST_SSH_IPV6=yes fi AC_CHECK_DECL([BROKEN_GETADDRINFO], [TEST_SSH_IPV6=no]) AC_SUBST([TEST_SSH_IPV6], [$TEST_SSH_IPV6]) AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8]) AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS]) AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms]) AC_SUBST([DEPEND], [$(cat $srcdir/.depend)]) # Binaries for interop tests. AC_PATH_PROG([PLINK], [plink]) AC_PATH_PROG([PUTTYGEN], [puttygen]) AC_PATH_PROG([CONCH], [conch]) AC_PATH_PROG([DROPBEAR], [dropbear]) AC_PATH_PROG([DBCLIENT], [dbclient]) AC_PATH_PROG([DROPBEARKEY], [dropbearkey]) AC_PATH_PROG([DROPBEARCONVERT], [dropbearconvert]) CFLAGS="${CFLAGS} ${CFLAGS_AFTER}" LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}" # Make a copy of CFLAGS/LDFLAGS without PIE options. LDFLAGS_NOPIE=`echo "$LDFLAGS" | sed 's/^-pie //;s/ -pie//g'` CFLAGS_NOPIE=`echo "$CFLAGS" | sed 's/^-fPIE //;s/ -fPIE//g'` AC_SUBST([LDFLAGS_NOPIE]) AC_SUBST([CFLAGS_NOPIE]) AC_EXEEXT AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \ openbsd-compat/Makefile openbsd-compat/regress/Makefile \ survey.sh]) AC_OUTPUT # Print summary of options # Someone please show me a better way :) A=`eval echo ${prefix}` ; A=`eval echo ${A}` B=`eval echo ${bindir}` ; B=`eval echo ${B}` C=`eval echo ${sbindir}` ; C=`eval echo ${C}` D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}` E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}` F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}` G=`eval echo ${piddir}` ; G=`eval echo ${G}` H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}` I=`eval echo ${user_path}` ; I=`eval echo ${I}` J=`eval echo ${superuser_path}` ; J=`eval echo ${J}` echo "" echo "OpenSSH has been configured with the following options:" echo " User binaries: $B" echo " System binaries: $C" echo " Configuration files: $D" echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" echo " Privilege separation chroot path: $H" if test "x$external_path_file" = "x/etc/login.conf" ; then echo " At runtime, sshd will use the path defined in $external_path_file" echo " Make sure the path to scp is present, otherwise scp will not work" else echo " sshd default user PATH: $I" if test ! -z "$external_path_file"; then echo " (If PATH is set in $external_path_file it will be used instead. If" echo " used, ensure the path to scp is present, otherwise scp will not work.)" fi fi if test ! -z "$superuser_path" ; then echo " sshd superuser user PATH: $J" fi echo " Manpage format: $MANTYPE" echo " PAM support: $PAM_MSG" echo " OSF SIA support: $SIA_MSG" echo " KerberosV support: $KRB5_MSG" echo " SELinux support: $SELINUX_MSG" echo " libedit support: $LIBEDIT_MSG" echo " libldns support: $LDNS_MSG" echo " Solaris process contract support: $SPC_MSG" echo " Solaris project support: $SP_MSG" echo " Solaris privilege support: $SPP_MSG" echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" echo " U2F/FIDO support: $enable_sk" echo "" echo " Host: ${host}" echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" echo " Libraries: ${LIBS}" if test ! -z "${CHANNELLIBS}"; then echo " +for channels: ${CHANNELLIBS}" fi if test ! -z "${LIBFIDO2}"; then echo " +for FIDO2: ${LIBFIDO2}" fi if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" fi echo "" if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then echo "SVR4 style packages are supported with \"make package\"" echo "" fi if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " echo "Example PAM control files can be found in the contrib/ " echo "subdirectory" echo "" fi if test ! -z "$NO_PEERCHECK" ; then echo "WARNING: the operating system that you are using does not" echo "appear to support getpeereid(), getpeerucred() or the" echo "SO_PEERCRED getsockopt() option. These facilities are used to" echo "enforce security checks to prevent unauthorised connections to" echo "ssh-agent. Their absence increases the risk that a malicious" echo "user can connect to your agent." echo "" fi if test "$AUDIT_MODULE" = "bsm" ; then echo "WARNING: BSM audit support is currently considered EXPERIMENTAL." echo "See the Solaris section in README.platform for details." fi openssh-10.0p1/PaxHeaders.10889/contrib040755 001750 001750 0000000003614775415623 0014545xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib004075500017500001750000000000001477541562300131235ustar00djmdjmopenssh-10.0p1/contrib/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0016254xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib/Makefile010064400017500001750000000013131477541562300146350ustar00djmdjmPKG_CONFIG = pkg-config all: @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2 gnome-ssk-askpass3" gnome-ssh-askpass1: gnome-ssh-askpass1.c $(CC) $(CFLAGS) `gnome-config --cflags gnome gnomeui` \ gnome-ssh-askpass1.c -o gnome-ssh-askpass1 \ `gnome-config --libs gnome gnomeui` gnome-ssh-askpass2: gnome-ssh-askpass2.c $(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gtk+-2.0` \ gnome-ssh-askpass2.c -o gnome-ssh-askpass2 \ `$(PKG_CONFIG) --libs gtk+-2.0 x11` gnome-ssh-askpass3: gnome-ssh-askpass3.c $(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gtk+-3.0` \ gnome-ssh-askpass3.c -o gnome-ssh-askpass3 \ `$(PKG_CONFIG) --libs gtk+-3.0 x11` clean: rm -f *.o gnome-ssh-askpass gnome-ssh-askpass[123] openssh-10.0p1/contrib/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0015474xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib/README010064400017500001750000000033601477541562300140610ustar00djmdjmOther patches and addons for OpenSSH. Please send submissions to djm@mindrot.org Externally maintained --------------------- SSH Proxy Command -- connect.c Shun-ichi GOTO has written a very useful ProxyCommand 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. https://bitbucket.org/gotoh/connect/wiki/Home X11 SSH Askpass: Jim Knoble has written an excellent X11 passphrase requester. This is highly recommended: http://www.jmknoble.net/software/x11-ssh-askpass/ In this directory ----------------- ssh-copy-id: Phil Hands' shell script to automate the process of adding your public key to a remote machine's ~/.ssh/authorized_keys file. gnome-ssh-askpass[12]: A GNOME and Gtk2 passphrase requesters. Use "make gnome-ssh-askpass1" or "make gnome-ssh-askpass2" to build. sshd.pam.generic: A generic PAM config file which may be useful on your system. YMMV sshd.pam.freebsd: A PAM config file which works with FreeBSD's PAM port. Contributed by Dominik Brettnacher findssl.sh: Search for all instances of OpenSSL headers and libraries and print their versions. This is intended to help diagnose OpenSSH's "OpenSSL headers do not match your library" errors. aix: Files to build an AIX native (installp or SMIT installable) package. caldera: RPM spec file and scripts for building Caldera OpenLinuix packages cygwin: Support files for Cygwin hpux: Support files for HP-UX redhat: RPM spec file and scripts for building Redhat packages suse: RPM spec file and scripts for building SuSE packages openssh-10.0p1/contrib/PaxHeaders.10889/aix040755 001750 001750 0000000003614775415623 0015326xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib/aix004075500017500001750000000000001477541562300137045ustar00djmdjmopenssh-10.0p1/contrib/aix/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0016255xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib/aix/README010064400017500001750000000024141477541562300146410ustar00djmdjmOverview: This directory contains files to build an AIX native (installp or SMIT installable) openssh package. Directions: (optional) create config.local in your build dir ./configure [options] contrib/aix/buildbff.sh The file config.local or the environment is read to set the following options (default first): PERMIT_ROOT_LOGIN=[no|yes] X11_FORWARDING=[no|yes] AIX_SRC=[no|yes] Acknowledgements: The contents of this directory are based on Ben Lindstrom's Solaris buildpkg.sh. Ben also supplied inventory.sh. Jim Abbey's (GPL'ed) lppbuild-2.1 was used to learn how to build .bff's and for comparison with the output from this script, however no code from lppbuild is included and it is not required for operation. SRC support based on examples provided by Sandor Sklar and Maarten Kreuger. PrivSep account handling fixes contributed by W. Earl Allen. Other notes: 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.dtucker.net/openssh/. Disclaimer: It is hoped that it is useful but there is no warranty. If it breaks you get to keep both pieces. - Darren Tucker (dtucker at zip dot com dot au) 2002/03/01 openssh-10.0p1/contrib/aix/PaxHeaders.10889/buildbff.sh100755 001750 001750 0000000003614775415623 0017511xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib/aix/buildbff.sh010075500017500001750000000213631477541562300161010ustar00djmdjm#!/bin/sh # # buildbff.sh: Create AIX SMIT-installable OpenSSH packages # # Author: Darren Tucker (dtucker at zip dot com dot au) # This file is placed in the public domain and comes with absolutely # no warranty. # # Based originally on Ben Lindstrom's buildpkg.sh for Solaris # # # Tunable configuration settings # create a "config.local" in your build directory or set # environment variables to override these. # [ -z "$PERMIT_ROOT_LOGIN" ] && PERMIT_ROOT_LOGIN=no [ -z "$X11_FORWARDING" ] && X11_FORWARDING=no [ -z "$AIX_SRC" ] && AIX_SRC=no umask 022 startdir=`pwd` perl -v >/dev/null || (echo perl required; exit 1) # Path to inventory.sh: same place as buildbff.sh if echo $0 | egrep '^/' then inventory=`dirname $0`/inventory.sh # absolute path else inventory=`pwd`/`dirname $0`/inventory.sh # relative path fi # # We still support running from contrib/aix, but this is deprecated # if pwd | egrep 'contrib/aix$' then echo "Changing directory to `pwd`/../.." echo "Please run buildbff.sh from your build directory in future." cd ../.. contribaix=1 fi if [ ! -f Makefile ] then echo "Makefile not found (did you run configure?)" exit 1 fi # # Directories used during build: # current dir = $objdir directory you ran ./configure in. # $objdir/$PKGDIR/ directory package files are constructed in # $objdir/$PKGDIR/root/ package root ($FAKE_ROOT) # objdir=`pwd` PKGNAME=openssh PKGDIR=package # # Collect local configuration settings to override defaults # if [ -s ./config.local ] then echo Reading local settings from config.local . ./config.local fi # # Fill in some details from Makefile, like prefix and sysconfdir # the eval also expands variables like sysconfdir=${prefix}/etc # provided they are eval'ed in the correct order # for confvar in prefix exec_prefix bindir sbindir libexecdir datadir mandir mansubdir sysconfdir piddir srcdir do eval $confvar=`grep "^$confvar=" $objdir/Makefile | cut -d = -f 2` done # # Collect values of privsep user and privsep path # currently only found in config.h # for confvar in SSH_PRIVSEP_USER PRIVSEP_PATH do eval $confvar=`awk '/#define[ \t]'$confvar'/{print $3}' $objdir/config.h` done # Set privsep defaults if not defined if [ -z "$SSH_PRIVSEP_USER" ] then SSH_PRIVSEP_USER=sshd fi if [ -z "$PRIVSEP_PATH" ] then PRIVSEP_PATH=/var/empty fi # Clean package build directory rm -rf $objdir/$PKGDIR FAKE_ROOT=$objdir/$PKGDIR/root mkdir -p $FAKE_ROOT # Start by faking root install echo "Faking root install..." cd $objdir make install-nokeys DESTDIR=$FAKE_ROOT if [ $? -gt 0 ] then echo "Fake root install failed, stopping." exit 1 fi # # Copy informational files to include in package # cp $srcdir/LICENCE $objdir/$PKGDIR/ cp $srcdir/README* $objdir/$PKGDIR/ # # Extract common info requires for the 'info' part of the package. # AIX requires 4-part version numbers # VERSION=`./ssh -V 2>&1 | cut -f 1 -d , | cut -f 2 -d _` MAJOR=`echo $VERSION | cut -f 1 -d p | cut -f 1 -d .` MINOR=`echo $VERSION | cut -f 1 -d p | cut -f 2 -d .` PATCH=`echo $VERSION | cut -f 1 -d p | cut -f 3 -d .` PORTABLE=`echo $VERSION | awk 'BEGIN{FS="p"}{print $2}'` [ "$PATCH" = "" ] && PATCH=0 [ "$PORTABLE" = "" ] && PORTABLE=0 BFFVERSION=`printf "%d.%d.%d.%d" $MAJOR $MINOR $PATCH $PORTABLE` echo "Building BFF for $PKGNAME $VERSION (package version $BFFVERSION)" # # Set ssh and sshd parameters as per config.local # if [ "${PERMIT_ROOT_LOGIN}" = no ] then perl -p -i -e "s/#PermitRootLogin yes/PermitRootLogin no/" \ $FAKE_ROOT/${sysconfdir}/sshd_config fi if [ "${X11_FORWARDING}" = yes ] then perl -p -i -e "s/#X11Forwarding no/X11Forwarding yes/" \ $FAKE_ROOT/${sysconfdir}/sshd_config fi # Rename config files; postinstall script will copy them if necessary for cfgfile in ssh_config sshd_config do mv $FAKE_ROOT/$sysconfdir/$cfgfile $FAKE_ROOT/$sysconfdir/$cfgfile.default done # # Generate lpp control files. # working dir is $FAKE_ROOT but files are generated in dir above # and moved into place just before creation of .bff # cd $FAKE_ROOT echo Generating LPP control files find . ! -name . -print >../openssh.al $inventory >../openssh.inventory cat <../openssh.copyright This software is distributed under a BSD-style license. For the full text of the license, see /usr/lpp/openssh/LICENCE EOD # # openssh.size file allows filesystem expansion as required # generate list of directories containing files # then calculate disk usage for each directory and store in openssh.size # files=`find . -type f -print` dirs=`for file in $files; do dirname $file; done | sort -u` for dir in $dirs do du $dir done > ../openssh.size # # Create postinstall script # cat <>../openssh.post_i #!/bin/sh echo Creating configs from defaults if necessary. for cfgfile in ssh_config sshd_config do if [ ! -f $sysconfdir/\$cfgfile ] then echo "Creating \$cfgfile from default" cp $sysconfdir/\$cfgfile.default $sysconfdir/\$cfgfile else echo "\$cfgfile already exists." fi done echo # Create PrivilegeSeparation user and group if not present echo Checking for PrivilegeSeparation user and group. if cut -f1 -d: /etc/group | egrep '^'$SSH_PRIVSEP_USER'\$' >/dev/null then echo "PrivSep group $SSH_PRIVSEP_USER already exists." else echo "Creating PrivSep group $SSH_PRIVSEP_USER." mkgroup -A $SSH_PRIVSEP_USER fi # Create user if required if lsuser "$SSH_PRIVSEP_USER" >/dev/null then echo "PrivSep user $SSH_PRIVSEP_USER already exists." else echo "Creating PrivSep user $SSH_PRIVSEP_USER." mkuser gecos='SSHD PrivSep User' login=false rlogin=false account_locked=true pgrp=$SSH_PRIVSEP_USER $SSH_PRIVSEP_USER fi if egrep '^[ \t]*UsePrivilegeSeparation[ \t]+no' $sysconfdir/sshd_config >/dev/null then echo UsePrivilegeSeparation not enabled, privsep directory not required. else # create chroot directory if required if [ -d $PRIVSEP_PATH ] then echo "PrivSep chroot directory $PRIVSEP_PATH already exists." else echo "Creating PrivSep chroot directory $PRIVSEP_PATH." mkdir $PRIVSEP_PATH chown 0 $PRIVSEP_PATH chgrp 0 $PRIVSEP_PATH chmod 755 $PRIVSEP_PATH fi fi echo # Generate keys unless they already exist echo Creating host keys if required. $bindir/ssh-keygen -A echo # Set startup command depending on SRC support if [ "$AIX_SRC" = "yes" ] then echo Creating SRC sshd subsystem. rmssys -s sshd 2>&1 >/dev/null mkssys -s sshd -p "$sbindir/sshd" -a '-D' -u 0 -S -n 15 -f 9 -R -G tcpip startupcmd="start $sbindir/sshd \\\"\\\$src_running\\\"" oldstartcmd="$sbindir/sshd" else startupcmd="$sbindir/sshd" oldstartcmd="start $sbindir/sshd \\\"$src_running\\\"" fi # If migrating to or from SRC, change previous startup command # otherwise add to rc.tcpip if egrep "^\$oldstartcmd" /etc/rc.tcpip >/dev/null then if sed "s|^\$oldstartcmd|\$startupcmd|g" /etc/rc.tcpip >/etc/rc.tcpip.new then chmod 0755 /etc/rc.tcpip.new mv /etc/rc.tcpip /etc/rc.tcpip.old && \ mv /etc/rc.tcpip.new /etc/rc.tcpip else echo "Updating /etc/rc.tcpip failed, please check." fi else # Add to system startup if required if grep "^\$startupcmd" /etc/rc.tcpip >/dev/null then echo "sshd found in rc.tcpip, not adding." else echo "Adding sshd to rc.tcpip" echo >>/etc/rc.tcpip echo "# Start sshd" >>/etc/rc.tcpip echo "\$startupcmd" >>/etc/rc.tcpip fi fi EOF # # Create liblpp.a and move control files into it # echo Creating liblpp.a ( cd .. for i in openssh.al openssh.copyright openssh.inventory openssh.post_i openssh.size LICENCE README* do ar -r liblpp.a $i rm $i done ) # # Create lpp_name # # This will end up looking something like: # 4 R I OpenSSH { # OpenSSH 3.0.2.1 1 N U en_US OpenSSH 3.0.2p1 Portable for AIX # [ # % # /usr/local/bin 8073 # /usr/local/etc 189 # /usr/local/libexec 185 # /usr/local/man/man1 145 # /usr/local/man/man8 83 # /usr/local/sbin 2105 # /usr/local/share 3 # % # ] # } echo Creating lpp_name cat <../lpp_name 4 R I $PKGNAME { $PKGNAME $BFFVERSION 1 N U en_US OpenSSH $VERSION Portable for AIX [ % EOF for i in $bindir $sysconfdir $libexecdir $mandir/${mansubdir}1 $mandir/${mansubdir}8 $sbindir $datadir /usr/lpp/openssh do # get size in 512 byte blocks if [ -d $FAKE_ROOT/$i ] then size=`du $FAKE_ROOT/$i | awk '{print $1}'` echo "$i $size" >>../lpp_name fi done echo '%' >>../lpp_name echo ']' >>../lpp_name echo '}' >>../lpp_name # # Move pieces into place # mkdir -p usr/lpp/openssh mv ../liblpp.a usr/lpp/openssh mv ../lpp_name . # # Now invoke backup to create .bff file # note: lpp_name needs to be the first file so we generate the # file list on the fly and feed it to backup using -i # echo Creating $PKGNAME-$VERSION.bff with backup... rm -f $PKGNAME-$VERSION.bff ( echo "./lpp_name" find . ! -name lpp_name -a ! -name . -print ) | backup -i -q -f ../$PKGNAME-$VERSION.bff $filelist # # Move package into final location and clean up # mv ../$PKGNAME-$VERSION.bff $startdir cd $startdir rm -rf $objdir/$PKGDIR echo $0: done. openssh-10.0p1/contrib/aix/PaxHeaders.10889/inventory.sh100755 001750 001750 0000000003614775415623 0017771xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib/aix/inventory.sh010075500017500001750000000030351477541562300163550ustar00djmdjm#!/bin/sh # # inventory.sh # # Originally written by Ben Lindstrom, modified by Darren Tucker to use perl # This file is placed into the public domain. # # This will produce an AIX package inventory file, which looks like: # # /usr/local/bin: # class=apply,inventory,openssh # owner=root # group=system # mode=755 # type=DIRECTORY # /usr/local/bin/slogin: # class=apply,inventory,openssh # owner=root # group=system # mode=777 # type=SYMLINK # target=ssh # /usr/local/share/Ssh.bin: # class=apply,inventory,openssh # owner=root # group=system # mode=644 # type=FILE # size=VOLATILE # checksum=VOLATILE find . ! -name . -print | perl -ne '{ chomp; if ( -l $_ ) { ($dev,$ino,$mod,$nl,$uid,$gid,$rdev,$sz,$at,$mt,$ct,$bsz,$blk)=lstat; } else { ($dev,$ino,$mod,$nl,$uid,$gid,$rdev,$sz,$at,$mt,$ct,$bsz,$blk)=stat; } # Start to display inventory information $name = $_; $name =~ s|^.||; # Strip leading dot from path print "$name:\n"; print "\tclass=apply,inventory,openssh\n"; print "\towner=root\n"; print "\tgroup=system\n"; printf "\tmode=%lo\n", $mod & 07777; # Mask perm bits if ( -l $_ ) { # Entry is SymLink print "\ttype=SYMLINK\n"; printf "\ttarget=%s\n", readlink($_); } elsif ( -f $_ ) { # Entry is File print "\ttype=FILE\n"; print "\tsize=$sz\n"; print "\tchecksum=VOLATILE\n"; } elsif ( -d $_ ) { # Entry is Directory print "\ttype=DIRECTORY\n"; } }' openssh-10.0p1/contrib/aix/PaxHeaders.10889/pam.conf100644 001750 001750 0000000003614775415623 0017021xustar0030 atime=1744182234.558422418 openssh-10.0p1/contrib/aix/pam.conf010064400017500001750000000012741477541562300154100ustar00djmdjm# # PAM configuration file /etc/pam.conf # Example for OpenSSH on AIX 5.2 # # Authentication Management sshd auth required /usr/lib/security/pam_aix OTHER auth required /usr/lib/security/pam_aix # Account Management sshd account required /usr/lib/security/pam_aix OTHER account required /usr/lib/security/pam_aix # Password Management sshd password required /usr/lib/security/pam_aix OTHER password required /usr/lib/security/pam_aix # Session Management sshd session required /usr/lib/security/pam_aix OTHER session required /usr/lib/security/pam_aix openssh-10.0p1/contrib/PaxHeaders.10889/cygwin040755 001750 001750 0000000003614775415623 0016045xustar0030 atime=1744182234.559398935 openssh-10.0p1/contrib/cygwin004075500017500001750000000000001477541562300144235ustar00djmdjmopenssh-10.0p1/contrib/cygwin/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0017554xustar0030 atime=1744182234.559398935 openssh-10.0p1/contrib/cygwin/Makefile010064400017500001750000000060441477541562300161430ustar00djmdjmsrcdir=../.. copyidsrcdir=.. prefix=/usr exec_prefix=$(prefix) bindir=$(prefix)/bin datadir=$(prefix)/share mandir=$(datadir)/man docdir=$(datadir)/doc sshdocdir=$(docdir)/openssh cygdocdir=$(docdir)/Cygwin sysconfdir=/etc defaultsdir=$(sysconfdir)/defaults/etc inetdefdir=$(defaultsdir)/inetd.d PRIVSEP_PATH=/var/empty INSTALL=/usr/bin/install -c MKDIR_P=$(srcdir)/mkinstalldirs DESTDIR= all: @echo @echo "Use \`make cygwin-postinstall DESTDIR=[package directory]'" @echo "Be sure having DESTDIR set correctly!" @echo move-config-files: $(DESTDIR)$(sysconfdir)/ssh_config $(DESTDIR)$(sysconfdir)/sshd_config $(MKDIR_P) $(DESTDIR)$(defaultsdir) mv $(DESTDIR)$(sysconfdir)/ssh_config $(DESTDIR)$(defaultsdir) mv $(DESTDIR)$(sysconfdir)/sshd_config $(DESTDIR)$(defaultsdir) remove-empty-dir: rm -rf $(DESTDIR)$(PRIVSEP_PATH) install-inetd-config: $(MKDIR_P) $(DESTDIR)$(inetdefdir) $(INSTALL) -m 644 sshd-inetd $(DESTDIR)$(inetdefdir)/sshd-inetd install-sshdoc: $(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 -$(INSTALL) -m 644 $(srcdir)/OVERVIEW $(DESTDIR)$(sshdocdir)/OVERVIEW -$(INSTALL) -m 644 $(srcdir)/PROTOCOL $(DESTDIR)$(sshdocdir)/PROTOCOL -$(INSTALL) -m 644 $(srcdir)/PROTOCOL.agent $(DESTDIR)$(sshdocdir)/PROTOCOL.agent -$(INSTALL) -m 644 $(srcdir)/PROTOCOL.certkeys $(DESTDIR)$(sshdocdir)/PROTOCOL.certkeys -$(INSTALL) -m 644 $(srcdir)/PROTOCOL.mux $(DESTDIR)$(sshdocdir)/PROTOCOL.mux -$(INSTALL) -m 644 $(srcdir)/README $(DESTDIR)$(sshdocdir)/README -$(INSTALL) -m 644 $(srcdir)/README.dns $(DESTDIR)$(sshdocdir)/README.dns -$(INSTALL) -m 644 $(srcdir)/README.platform $(DESTDIR)$(sshdocdir)/README.platform -$(INSTALL) -m 644 $(srcdir)/README.privsep $(DESTDIR)$(sshdocdir)/README.privsep -$(INSTALL) -m 644 $(srcdir)/README.tun $(DESTDIR)$(sshdocdir)/README.tun -$(INSTALL) -m 644 $(srcdir)/TODO $(DESTDIR)$(sshdocdir)/TODO install-cygwindoc: README $(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 $(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 install-copy-id: $(copyidsrcdir)/ssh-copy-id $(copyidsrcdir)/ssh-copy-id.1 $(INSTALL) -m 755 $(copyidsrcdir)/ssh-copy-id $(DESTDIR)$(bindir)/ssh-copy-id $(INSTALL) -m 644 $(copyidsrcdir)/ssh-copy-id.1 $(DESTDIR)$(mandir)/man1/ssh-copy-id.1 gzip-man-pages: rm $(DESTDIR)$(mandir)/man1/slogin.1 gzip $(DESTDIR)$(mandir)/man1/*.1 gzip $(DESTDIR)$(mandir)/man5/*.5 gzip $(DESTDIR)$(mandir)/man8/*.8 cd $(DESTDIR)$(mandir)/man1 && ln -s ssh.1.gz slogin.1.gz cygwin-postinstall: move-config-files remove-empty-dir install-inetd-config install-doc install-scripts install-copy-id gzip-man-pages @echo "Cygwin specific configuration finished." openssh-10.0p1/contrib/cygwin/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0016774xustar0030 atime=1744182234.559398935 openssh-10.0p1/contrib/cygwin/README010064400017500001750000000060101477541562300153540ustar00djmdjmThis package describes important Cygwin specific stuff concerning OpenSSH. The binary package is usually built for recent Cygwin versions and might not run on older versions. Please check http://cygwin.com/ for information about current Cygwin releases. ================== Host configuration ================== If you are installing OpenSSH the first time, you can generate global config files and server keys, as well as installing sshd as a service, by running /usr/bin/ssh-host-config Note that this binary archive doesn't contain default config files in /etc. That files are only created if ssh-host-config is started. To support testing and unattended installation ssh-host-config got some options: usage: ssh-host-config [OPTION]... Options: --debug -d Enable shell's debug output. --yes -y Answer all questions with "yes" automatically. --no -n Answer all questions with "no" automatically. --cygwin -c Use "options" as value for CYGWIN environment var. --name -N sshd windows service name. --port -p sshd listens on port n. --user -u privileged user for service, default 'cyg_server'. --pwd -w Use "pwd" as password for privileged user. --privileged On Windows XP, require privileged user instead of LocalSystem for sshd service. Installing sshd as daemon via ssh-host-config is recommended. Alternatively you can start sshd via inetd, if you have the inetutils package installed. Just run ssh-host-config, but answer "no" when asked to install sshd as service. The ssh-host-config script also adds the required lines to /etc/inetd.conf and /etc/services. ================== User configuration ================== Any user can simplify creating the own private and public keys by running /usr/bin/ssh-user-config To support testing and unattended installation ssh-user-config got some options as well: usage: ssh-user-config [OPTION]... Options: --debug -d Enable shell's debug output. --yes -y Answer all questions with "yes" automatically. --no -n Answer all questions with "no" automatically. --passphrase -p word Use "word" as passphrase automatically. 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 directory is set in /etc/passwd, the root directory is used instead! ================ Building OpenSSH ================ Building from source is easy. Just unpack the source archive, cd to that directory, and call cygport: cygport openssh.cygport all You must have installed the following packages to be able to build OpenSSH with the aforementioned cygport script: zlib crypt libssl-devel libedit-devel libkrb5-devel Please send requests, error reports etc. to cygwin@cygwin.com. Have fun, Corinna Vinschen Cygwin Developer Red Hat Inc. openssh-10.0p1/contrib/cygwin/PaxHeaders.10889/ssh-host-config100644 001750 001750 0000000003614775415623 0021052xustar0030 atime=1744182234.559398935 openssh-10.0p1/contrib/cygwin/ssh-host-config010064400017500001750000000554201477541562300174430ustar00djmdjm#!/bin/bash # # ssh-host-config, Copyright 2000-2014 Red Hat Inc. # # This file is part of the Cygwin port of OpenSSH. # # 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", 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 ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR # THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ====================================================================== # Initialization # ====================================================================== CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh # 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=( /usr/bin/basename coreutils /usr/bin/cat coreutils /usr/bin/chmod coreutils /usr/bin/dirname coreutils /usr/bin/id coreutils /usr/bin/mv coreutils /usr/bin/rm coreutils /usr/bin/cygpath cygwin /usr/bin/mkpasswd cygwin /usr/bin/mount cygwin /usr/bin/ps cygwin /usr/bin/umount cygwin /usr/bin/cmp diffutils /usr/bin/grep grep /usr/bin/awk gawk /usr/bin/ssh-keygen openssh /usr/sbin/sshd openssh /usr/bin/sed sed ) csih_sanity_check_server=yes source ${CSIH_SCRIPT} PROGNAME=$(/usr/bin/basename $0) _tdir=$(/usr/bin/dirname $0) PROGDIR=$(cd $_tdir && pwd) # Subdirectory where the new package is being installed PREFIX=/usr # Directory where the config files are stored SYSCONFDIR=/etc LOCALSTATEDIR=/var sshd_config_configured=no port_number=22 service_name=cygsshd strictmodes=yes cygwin_value="" user_account= password_value= opt_force=no # ====================================================================== # Routine: update_services_file # ====================================================================== update_services_file() { local _my_etcdir="/ssh-host-config.$$" local _win_etcdir local _services local _spaces local _serv_tmp local _wservices local ret=0 _win_etcdir="${SYSTEMROOT}\\system32\\drivers\\etc" _services="${_my_etcdir}/services" _spaces=" #" _serv_tmp="${_my_etcdir}/srv.out.$$" /usr/bin/mount -o text,posix=0,noacl -f "${_win_etcdir}" "${_my_etcdir}" # Depends on the above mount _wservices=`cygpath -w "${_services}"` # Add ssh 22/tcp and ssh 22/udp to services if [ `/usr/bin/grep -q 'ssh[[:space:]][[:space:]]*22' "${_services}"; echo $?` -ne 0 ] then if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh 22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh 22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}" then if /usr/bin/mv "${_serv_tmp}" "${_services}" then csih_inform "Added ssh to ${_wservices}" else csih_warning "Adding ssh to ${_wservices} failed!" let ++ret fi /usr/bin/rm -f "${_serv_tmp}" else csih_warning "Adding ssh to ${_wservices} failed!" let ++ret fi fi /usr/bin/umount "${_my_etcdir}" return $ret } # --- End of update_services_file --- # # ====================================================================== # Routine: sshd_strictmodes # MODIFIES: strictmodes # ====================================================================== sshd_strictmodes() { if [ "${sshd_config_configured}" != "yes" ] then echo csih_inform "StrictModes is set to 'yes' by default." csih_inform "This is the recommended setting, but it requires that the POSIX" csih_inform "permissions of the user's home directory, the user's .ssh" csih_inform "directory, and the user's ssh key files are tight so that" csih_inform "only the user has write permissions." csih_inform "On the other hand, StrictModes don't work well with default" csih_inform "Windows permissions of a home directory mounted with the" csih_inform "'noacl' option, and they don't work at all if the home" csih_inform "directory is on a FAT or FAT32 partition." if ! csih_request "Should StrictModes be used?" then strictmodes=no fi fi return 0 } # ====================================================================== # Routine: sshd_privsep # Try to create ssshd user account # ====================================================================== sshd_privsep() { local ret=0 if [ "${sshd_config_configured}" != "yes" ] then if ! csih_create_unprivileged_user sshd then 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 } # --- End of sshd_privsep --- # # ====================================================================== # Routine: sshd_config_tweak # ====================================================================== sshd_config_tweak() { local ret=0 # Modify sshd_config csih_inform "Updating ${SYSCONFDIR}/sshd_config file" if [ "${port_number}" -ne 22 ] then /usr/bin/sed -i -e "s/^#\?[[:space:]]*Port[[:space:]].*/Port ${port_number}/" \ ${SYSCONFDIR}/sshd_config if [ $? -ne 0 ] then csih_warning "Setting listening port to ${port_number} failed!" csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" let ++ret fi fi if [ "${strictmodes}" = "no" ] then /usr/bin/sed -i -e "s/^#\?[[:space:]]*StrictModes[[:space:]].*/StrictModes no/" \ ${SYSCONFDIR}/sshd_config if [ $? -ne 0 ] then csih_warning "Setting StrictModes to 'no' failed!" csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" let ++ret fi fi return $ret } # --- End of sshd_config_tweak --- # # ====================================================================== # Routine: update_inetd_conf # ====================================================================== update_inetd_conf() { local _inetcnf="${SYSCONFDIR}/inetd.conf" local _inetcnf_tmp="${SYSCONFDIR}/inetd.conf.$$" local _inetcnf_dir="${SYSCONFDIR}/inetd.d" local _sshd_inetd_conf="${_inetcnf_dir}/sshd-inetd" local _sshd_inetd_conf_tmp="${_inetcnf_dir}/sshd-inetd.$$" local _with_comment=1 local ret=0 if [ -d "${_inetcnf_dir}" ] then # we have inetutils-1.5 inetd.d support if [ -f "${_inetcnf}" ] then /usr/bin/grep -q '^[[:space:]]*ssh' "${_inetcnf}" && _with_comment=0 # check for sshd OR ssh in top-level inetd.conf file, and remove # will be replaced by a file in inetd.d/ if [ $(/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?) -eq 0 ] then /usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}" if [ -f "${_inetcnf_tmp}" ] then if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}" then csih_inform "Removed ssh[d] from ${_inetcnf}" else csih_warning "Removing ssh[d] from ${_inetcnf} failed!" let ++ret fi /usr/bin/rm -f "${_inetcnf_tmp}" else csih_warning "Removing ssh[d] from ${_inetcnf} failed!" let ++ret fi fi fi csih_install_config "${_sshd_inetd_conf}" "${SYSCONFDIR}/defaults" if /usr/bin/cmp "${SYSCONFDIR}/defaults${_sshd_inetd_conf}" "${_sshd_inetd_conf}" >/dev/null 2>&1 then if [ "${_with_comment}" -eq 0 ] then /usr/bin/sed -e 's/@COMMENT@[[:space:]]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" else /usr/bin/sed -e 's/@COMMENT@[[:space:]]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" fi if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}" then csih_inform "Updated ${_sshd_inetd_conf}" else csih_warning "Updating ${_sshd_inetd_conf} failed!" let ++ret fi fi elif [ -f "${_inetcnf}" ] then /usr/bin/grep -q '^[[:space:]]*sshd' "${_inetcnf}" && _with_comment=0 # check for sshd in top-level inetd.conf file, and remove # will be replaced by a file in inetd.d/ if [ `/usr/bin/grep -q '^#\?[[:space:]]*sshd' "${_inetcnf}"; echo $?` -eq 0 ] then /usr/bin/grep -v '^#\?[[:space:]]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}" if [ -f "${_inetcnf_tmp}" ] then if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}" then csih_inform "Removed sshd from ${_inetcnf}" else csih_warning "Removing sshd from ${_inetcnf} failed!" let ++ret fi /usr/bin/rm -f "${_inetcnf_tmp}" else csih_warning "Removing sshd from ${_inetcnf} failed!" let ++ret fi fi # Add ssh line to inetd.conf if [ `/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -ne 0 ] then if [ "${_with_comment}" -eq 0 ] then echo 'ssh stream tcp nowait root /usr/sbin/sshd sshd -i' >> "${_inetcnf}" else echo '# ssh stream tcp nowait root /usr/sbin/sshd sshd -i' >> "${_inetcnf}" fi if [ $? -eq 0 ] then csih_inform "Added ssh to ${_inetcnf}" else csih_warning "Adding ssh to ${_inetcnf} failed!" let ++ret fi fi fi return $ret } # --- End of update_inetd_conf --- # # ====================================================================== # Routine: check_service_files_ownership # Checks that the files in /etc and /var belong to the right owner # ====================================================================== check_service_files_ownership() { local run_service_as=$1 local ret=0 if [ -z "${run_service_as}" ] then accnt_name=$(/usr/bin/cygrunsrv -VQ "${service_name}" | /usr/bin/sed -ne 's/^Account *: *//gp') if [ "${accnt_name}" = "LocalSystem" ] then # Convert "LocalSystem" to "SYSTEM" as is the correct account name run_service_as="SYSTEM" else dom="${accnt_name%%\\*}" accnt_name="${accnt_name#*\\}" if [ "${dom}" = '.' ] then # Check local account run_service_as=$(/usr/bin/mkpasswd -l -u "${accnt_name}" | /usr/bin/awk -F: '{print $1;}') else # Check domain run_service_as=$(/usr/bin/mkpasswd -d "${dom}" -u "${accnt_name}" | /usr/bin/awk -F: '{print $1;}') fi fi if [ -z "${run_service_as}" ] then 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 ${service_name} service belong to the user running the service." return 1 fi fi for i in "${SYSCONFDIR}"/ssh_config "${SYSCONFDIR}"/sshd_config "${SYSCONFDIR}"/ssh_host_*key "${SYSCONFDIR}"/ssh_host_*key.pub do if [ -f "$i" ] then if ! chown "${run_service_as}".544 "$i" >/dev/null 2>&1 then csih_warning "Couldn't change owner of $i!" let ++ret fi fi done if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/empty >/dev/null 2>&1 then csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/empty!" let ++ret fi if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/log/lastlog >/dev/null 2>&1 then csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/log/lastlog!" let ++ret fi if [ -f ${LOCALSTATEDIR}/log/sshd.log ] then if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/log/sshd.log >/dev/null 2>&1 then csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/log/sshd.log!" let ++ret fi fi if [ $ret -ne 0 ] then csih_warning "Couldn't change owner of important files to ${run_service_as}!" 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 } # --- End of check_service_files_ownership --- # # ====================================================================== # Routine: install_service # Install sshd as a service # ====================================================================== install_service() { local run_service_as local password local ret=0 echo if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1 then csih_inform "Sshd service is already installed." check_service_files_ownership "" || let ret+=$? else echo -e "${_csih_QUERY_STR} Do you want to install sshd as a service?" if csih_request "(Say \"no\" if it is already installed as a service)" then csih_get_cygenv "${cygwin_value}" if ( [ "$csih_FORCE_PRIVILEGED_USER" != "yes" ] ) then # 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 if ! csih_create_privileged_user "${password_value}" then csih_error_recoverable "There was a serious problem creating a privileged user." 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 if [ "${run_service_as}" = "${csih_PRIVILEGED_USERNAME}" ] then password="${csih_PRIVILEGED_PASSWORD}" if [ -z "${password}" ] then csih_get_value "Please enter the password for user '${run_service_as}':" "-s" password="${csih_value}" fi fi # At this point, we either have $run_service_as = "system" and # $password is empty, or $run_service_as is some privileged user and # (hopefully) $password contains the correct password. So, from here # out, we use '-z "${password}"' to discriminate the two cases. csih_check_user "${run_service_as}" if [ -n "${csih_cygenv}" ] then cygwin_env=( -e "CYGWIN=${csih_cygenv}" ) fi if [ -z "${password}" ] then if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \ -a "-D" -y tcpip "${cygwin_env[@]}" then 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 ${service_name}' or \`cygrunsrv -S ${service_name}'. Otherwise, it" csih_inform "will start automatically after the next reboot." fi else if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \ -a "-D" -y tcpip "${cygwin_env[@]}" \ -u "${run_service_as}" -w "${password}" then /usr/bin/editrights -u "${run_service_as}" -a SeServiceLogonRight echo csih_inform "The sshd service has been installed under the '${run_service_as}'" csih_inform "account. To start the service now, call \`net start ${service_name}' or" csih_inform "\`cygrunsrv -S ${service_name}'. Otherwise, it will start automatically" csih_inform "after the next reboot." fi fi if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1 then check_service_files_ownership "${run_service_as}" || let ret+=$? else csih_error_recoverable "Installing sshd as a service failed!" let ++ret fi fi # user allowed us to install as service fi # service not yet installed return $ret } # --- End of install_service --- # # ====================================================================== # Main Entry Point # ====================================================================== # Check how the script has been started. If # (1) it has been started by giving the full path and # that path is /etc/postinstall, OR # (2) Otherwise, if the environment variable # SSH_HOST_CONFIG_AUTO_ANSWER_NO is set # then set auto_answer to "no". This allows automatic # creation of the config files in /etc w/o overwriting # them if they already exist. In both cases, color # escape sequences are suppressed, so as to prevent # cluttering setup's logfiles. if [ "$PROGDIR" = "/etc/postinstall" ] then csih_auto_answer="no" csih_disable_color opt_force=yes fi if [ -n "${SSH_HOST_CONFIG_AUTO_ANSWER_NO}" ] then csih_auto_answer="no" csih_disable_color opt_force=yes fi # ====================================================================== # Parse options # ====================================================================== while : do case $# in 0) break ;; esac option=$1 shift case "${option}" in -d | --debug ) set -x csih_trace_on ;; -y | --yes ) csih_auto_answer=yes opt_force=yes ;; -n | --no ) csih_auto_answer=no opt_force=yes ;; -c | --cygwin ) cygwin_value="$1" shift ;; -N | --name ) service_name=$1 shift ;; -p | --port ) port_number=$1 shift ;; -u | --user ) user_account="$1" shift ;; -w | --pwd ) password_value="$1" shift ;; --privileged ) csih_FORCE_PRIVILEGED_USER=yes ;; *) echo "usage: ${progname} [OPTION]..." echo echo "This script creates an OpenSSH host configuration." echo echo "Options:" echo " --debug -d Enable shell's debug output." echo " --yes -y Answer all questions with \"yes\" automatically." echo " --no -n Answer all questions with \"no\" automatically." echo " --cygwin -c Use \"options\" as value for CYGWIN environment var." echo " --name -N sshd windows service name." echo " --port -p sshd listens on port n." echo " --user -u privileged user for service, default 'cyg_server'." echo " --pwd -w Use \"pwd\" as password for privileged user." echo " --privileged On Windows XP, require privileged user" echo " instead of LocalSystem for sshd service." echo exit 1 ;; esac done # ====================================================================== # Action! # ====================================================================== # Check for running ssh/sshd processes first. Refuse to do anything while # some ssh processes are still running if /usr/bin/ps -ef | /usr/bin/grep -q '/sshd\?$' then echo csih_error "There are still ssh processes running. Please shut them down first." fi # Make sure the user is running in an administrative context admin=$(/usr/bin/id -G | /usr/bin/grep -Eq '\<544\>' && echo yes || echo no) if [ "${admin}" != "yes" ] then echo csih_warning "Running this script typically requires administrator privileges!" csih_warning "However, it seems your account does not have these privileges." csih_warning "Here's the list of groups in your user token:" echo /usr/bin/id -Gnz | xargs -0n1 echo " " echo csih_warning "This usually means you're running this script from a non-admin" csih_warning "desktop session, or in a non-elevated shell under UAC control." echo csih_warning "Make sure you have the appropriate privileges right now," csih_warning "otherwise parts of this script will probably fail!" echo echo -e "${_csih_QUERY_STR} Are you sure you want to continue? (Say \"no\" if you're not sure" if ! csih_request "you have the required privileges)" then echo csih_inform "Ok. Exiting. Make sure to switch to an administrative account" csih_inform "or to start this script from an elevated shell." exit 1 fi fi echo warning_cnt=0 # Create /var/log/lastlog if not already exists if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ] then echo csih_error_multi "${LOCALSTATEDIR}/log/lastlog exists, but is not a file." \ "Cannot create ssh host configuration." fi if [ ! -e ${LOCALSTATEDIR}/log/lastlog ] then /usr/bin/cat /dev/null > ${LOCALSTATEDIR}/log/lastlog if ! /usr/bin/chmod 644 ${LOCALSTATEDIR}/log/lastlog >/dev/null 2>&1 then csih_warning "Can't set permissions on ${LOCALSTATEDIR}/log/lastlog!" let ++warning_cnt fi fi # Create /var/empty file used as chroot jail for privilege separation csih_make_dir "${LOCALSTATEDIR}/empty" "Cannot create ${LOCALSTATEDIR}/empty directory." if ! /usr/bin/chmod 755 "${LOCALSTATEDIR}/empty" >/dev/null 2>&1 then csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!" let ++warning_cnt fi # generate missing host keys csih_inform "Generating missing SSH host keys" /usr/bin/ssh-keygen -A || let warning_cnt+=$? # handle ssh_config csih_install_config "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt if /usr/bin/cmp "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/ssh_config" >/dev/null 2>&1 then if [ "${port_number}" != "22" ] then csih_inform "Updating ${SYSCONFDIR}/ssh_config file with requested port" echo "Host localhost" >> ${SYSCONFDIR}/ssh_config echo " Port ${port_number}" >> ${SYSCONFDIR}/ssh_config fi fi # 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 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+=$? echo if [ $warning_cnt -eq 0 ] then csih_inform "Host configuration finished. Have fun!" else csih_warning "Host configuration exited with ${warning_cnt} errors or warnings!" csih_warning "Make sure that all problems reported are fixed," csih_warning "then re-run ssh-host-config." fi exit $warning_cnt openssh-10.0p1/contrib/cygwin/PaxHeaders.10889/ssh-user-config100644 001750 001750 0000000003614775415623 0021053xustar0030 atime=1744182234.559398935 openssh-10.0p1/contrib/cygwin/ssh-user-config010064400017500001750000000177421477541562300174510ustar00djmdjm#!/bin/bash # # ssh-user-config, Copyright 2000-2014 Red Hat Inc. # # This file is part of the Cygwin port of OpenSSH. # # 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", 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 ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR # THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ====================================================================== # Initialization # ====================================================================== PROGNAME=$(basename -- $0) _tdir=$(dirname -- $0) PROGDIR=$(cd $_tdir && pwd) CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh # Subdirectory where the new package is being installed PREFIX=/usr # Directory where the config files are stored SYSCONFDIR=/etc source ${CSIH_SCRIPT} auto_passphrase="no" passphrase="" pwdhome= with_passphrase= # ====================================================================== # Routine: create_identity # optionally create identity of type argument in ~/.ssh # optionally add result to ~/.ssh/authorized_keys # ====================================================================== create_identity() { local file="$1" local type="$2" local name="$3" if [ ! -f "${pwdhome}/.ssh/${file}" ] then if csih_request "Shall I create a ${name} identity file for you?" then csih_inform "Generating ${pwdhome}/.ssh/${file}" if [ "${with_passphrase}" = "yes" ] then ssh-keygen -t "${type}" -N "${passphrase}" -f "${pwdhome}/.ssh/${file}" > /dev/null else ssh-keygen -t "${type}" -f "${pwdhome}/.ssh/${file}" > /dev/null fi if csih_request "Do you want to use this identity to log in to this machine?" then csih_inform "Adding to ${pwdhome}/.ssh/authorized_keys" cat "${pwdhome}/.ssh/${file}.pub" >> "${pwdhome}/.ssh/authorized_keys" fi fi fi } # === End of create_ssh1_identity() === # readonly -f create_identity # ====================================================================== # Routine: check_user_homedir # Perform various checks on the user's home directory # SETS GLOBAL VARIABLE: # pwdhome # ====================================================================== check_user_homedir() { pwdhome=$(getent passwd $UID | awk -F: '{ print $6; }') if [ "X${pwdhome}" = "X" ] then csih_error_multi \ "There is no home directory set for you in the account database." \ 'Setting $HOME is not sufficient!' fi if [ ! -d "${pwdhome}" ] then csih_error_multi \ "${pwdhome} is set in the account database as your home directory" \ 'but it is not a valid directory. Cannot create user identity files.' fi # If home is the root dir, set home to empty string to avoid error messages # in subsequent parts of that script. if [ "X${pwdhome}" = "X/" ] then # But first raise a warning! csih_warning "Your home directory in the account database is set to root (/). This is not recommended!" if csih_request "Would you like to proceed anyway?" then pwdhome='' else csih_warning "Exiting. Configuration is not complete" exit 1 fi fi if [ -d "${pwdhome}" -a -n "`chmod -c g-w,o-w "${pwdhome}"`" ] then echo csih_warning 'group and other have been revoked write permission to your home' csih_warning "directory ${pwdhome}." csih_warning 'This is required by OpenSSH to allow public key authentication using' csih_warning 'the key files stored in your .ssh subdirectory.' csih_warning 'Revert this change ONLY if you know what you are doing!' echo fi } # === End of check_user_homedir() === # readonly -f check_user_homedir # ====================================================================== # Routine: check_user_dot_ssh_dir # Perform various checks on the ~/.ssh directory # PREREQUISITE: # pwdhome -- check_user_homedir() # ====================================================================== check_user_dot_ssh_dir() { if [ -e "${pwdhome}/.ssh" -a ! -d "${pwdhome}/.ssh" ] then csih_error "${pwdhome}/.ssh is existent but not a directory. Cannot create user identity files." fi if [ ! -e "${pwdhome}/.ssh" ] then mkdir "${pwdhome}/.ssh" if [ ! -e "${pwdhome}/.ssh" ] then csih_error "Creating users ${pwdhome}/.ssh directory failed" fi fi } # === End of check_user_dot_ssh_dir() === # readonly -f check_user_dot_ssh_dir # ====================================================================== # Routine: fix_authorized_keys_perms # Corrects the permissions of ~/.ssh/authorized_keys # PREREQUISITE: # pwdhome -- check_user_homedir() # ====================================================================== fix_authorized_keys_perms() { if [ -e "${pwdhome}/.ssh/authorized_keys" ] then setfacl -b "${pwdhome}/.ssh/authorized_keys" 2>/dev/null || echo -n if ! chmod u-x,g-wx,o-wx "${pwdhome}/.ssh/authorized_keys" then csih_warning "Setting correct permissions to ${pwdhome}/.ssh/authorized_keys" csih_warning "failed. Please care for the correct permissions. The minimum requirement" csih_warning "is, the owner needs read permissions." echo fi fi } # === End of fix_authorized_keys_perms() === # readonly -f fix_authorized_keys_perms # ====================================================================== # Main Entry Point # ====================================================================== # Check how the script has been started. If # (1) it has been started by giving the full path and # that path is /etc/postinstall, OR # (2) Otherwise, if the environment variable # SSH_USER_CONFIG_AUTO_ANSWER_NO is set # then set auto_answer to "no". This allows automatic # creation of the config files in /etc w/o overwriting # them if they already exist. In both cases, color # escape sequences are suppressed, so as to prevent # cluttering setup's logfiles. if [ "$PROGDIR" = "/etc/postinstall" ] then csih_auto_answer="no" csih_disable_color fi if [ -n "${SSH_USER_CONFIG_AUTO_ANSWER_NO}" ] then csih_auto_answer="no" csih_disable_color fi # ====================================================================== # Parse options # ====================================================================== while : do case $# in 0) break ;; esac option=$1 shift case "$option" in -d | --debug ) set -x csih_trace_on ;; -y | --yes ) csih_auto_answer=yes ;; -n | --no ) csih_auto_answer=no ;; -p | --passphrase ) with_passphrase="yes" passphrase=$1 shift ;; *) echo "usage: ${PROGNAME} [OPTION]..." echo echo "This script creates an OpenSSH user configuration." echo echo "Options:" echo " --debug -d Enable shell's debug output." echo " --yes -y Answer all questions with \"yes\" automatically." echo " --no -n Answer all questions with \"no\" automatically." echo " --passphrase -p word Use \"word\" as passphrase automatically." echo exit 1 ;; esac done # ====================================================================== # Action! # ====================================================================== check_user_homedir check_user_dot_ssh_dir create_identity id_rsa rsa "SSH2 RSA" create_identity id_dsa dsa "SSH2 DSA" create_identity id_ecdsa ecdsa "SSH2 ECDSA" create_identity identity rsa1 "(deprecated) SSH1 RSA" fix_authorized_keys_perms echo csih_inform "Configuration finished. Have fun!" openssh-10.0p1/contrib/cygwin/PaxHeaders.10889/sshd-inetd100644 001750 001750 0000000003614775415623 0020101xustar0030 atime=1744182234.559398935 openssh-10.0p1/contrib/cygwin/sshd-inetd010064400017500001750000000003001477541562300164550ustar00djmdjm# This file can be used to enable sshd as a slave of the inetd service # To do so, the line below should be uncommented. @COMMENT@ ssh stream tcp nowait root /usr/sbin/sshd sshd -i openssh-10.0p1/contrib/PaxHeaders.10889/findssl.sh100644 001750 001750 0000000003614775415623 0016612xustar0030 atime=1744182234.560375753 openssh-10.0p1/contrib/findssl.sh010064400017500001750000000112751477541562300152030ustar00djmdjm#!/bin/sh # # findssl.sh # Search for all instances of OpenSSL headers and libraries # and print their versions. # Intended to help diagnose OpenSSH's "OpenSSL headers do not # match your library" errors. # # Written by Darren Tucker (dtucker at zip dot com dot au) # This file is placed in the public domain. # # Release history: # 2002-07-27: Initial release. # 2002-08-04: Added public domain notice. # 2003-06-24: Incorporated readme, set library paths. First cvs version. # 2004-12-13: Add traps to cleanup temp files, from Amarendra Godbole. # # "OpenSSL headers do not match your library" are usually caused by # OpenSSH's configure picking up an older version of OpenSSL headers # or libraries. You can use the following # procedure to help identify # the cause. # # The output of configure will tell you the versions of the OpenSSL # headers and libraries that were picked up, for example: # # checking OpenSSL header version... 90604f (OpenSSL 0.9.6d 9 May 2002) # checking OpenSSL library version... 90602f (OpenSSL 0.9.6b [engine] 9 Jul 2001) # checking whether OpenSSL's headers match the library... no # configure: error: Your OpenSSL headers do not match your library # # Now run findssl.sh. This should identify the headers and libraries # present and their versions. You should be able to identify the # libraries and headers used and adjust your CFLAGS or remove incorrect # versions. The output will show OpenSSL's internal version identifier # and should look something like: # $ ./findssl.sh # Searching for OpenSSL header files. # 0x0090604fL /usr/include/openssl/opensslv.h # 0x0090604fL /usr/local/ssl/include/openssl/opensslv.h # # Searching for OpenSSL shared library files. # 0x0090602fL /lib/libcrypto.so.0.9.6b # 0x0090602fL /lib/libcrypto.so.2 # 0x0090581fL /usr/lib/libcrypto.so.0 # 0x0090602fL /usr/lib/libcrypto.so # 0x0090581fL /usr/lib/libcrypto.so.0.9.5a # 0x0090600fL /usr/lib/libcrypto.so.0.9.6 # 0x0090600fL /usr/lib/libcrypto.so.1 # # Searching for OpenSSL static library files. # 0x0090602fL /usr/lib/libcrypto.a # 0x0090604fL /usr/local/ssl/lib/libcrypto.a # # In this example, I gave configure no extra flags, so it's picking up # the OpenSSL header from /usr/include/openssl (90604f) and the library # from /usr/lib/ (90602f). # # Adjust these to suit your compiler. # You may also need to set the *LIB*PATH environment variables if # DEFAULT_LIBPATH is not correct for your system. # CC=gcc STATIC=-static # # Cleanup on interrupt # trap 'rm -f conftest.c' INT HUP TERM # # Set up conftest C source # rm -f findssl.log cat >conftest.c < int main(){printf("0x%08xL\n", SSLeay());} EOD # # Set default library paths if not already set # DEFAULT_LIBPATH=/usr/lib:/usr/local/lib LIBPATH=${LIBPATH:=$DEFAULT_LIBPATH} LD_LIBRARY_PATH=${LD_LIBRARY_PATH:=$DEFAULT_LIBPATH} LIBRARY_PATH=${LIBRARY_PATH:=$DEFAULT_LIBPATH} export LIBPATH LD_LIBRARY_PATH LIBRARY_PATH # not all platforms have a 'which' command if which ls >/dev/null 2>/dev/null; then : which is defined else which () { saveIFS="$IFS" IFS=: for p in $PATH; do if test -x "$p/$1" -a -f "$p/$1"; then IFS="$saveIFS" echo "$p/$1" return 0 fi done IFS="$saveIFS" return 1 } fi # # Search for OpenSSL headers and print versions # echo Searching for OpenSSL header files. if [ -x "`which locate`" ] then headers=`locate opensslv.h` else headers=`find / -name opensslv.h -print 2>/dev/null` fi for header in $headers do ver=`awk '/OPENSSL_VERSION_NUMBER/{printf \$3}' $header` echo "$ver $header" done echo # # Search for shared libraries. # Relies on shared libraries looking like "libcrypto.s*" # echo Searching for OpenSSL shared library files. if [ -x "`which locate`" ] then libraries=`locate libcrypto.s` else libraries=`find / -name 'libcrypto.s*' -print 2>/dev/null` fi for lib in $libraries do (echo "Trying libcrypto $lib" >>findssl.log dir=`dirname $lib` LIBPATH="$dir:$LIBPATH" LD_LIBRARY_PATH="$dir:$LIBPATH" LIBRARY_PATH="$dir:$LIBPATH" export LIBPATH LD_LIBRARY_PATH LIBRARY_PATH ${CC} -o conftest conftest.c $lib 2>>findssl.log if [ -x ./conftest ] then ver=`./conftest 2>/dev/null` rm -f ./conftest echo "$ver $lib" fi) done echo # # Search for static OpenSSL libraries and print versions # echo Searching for OpenSSL static library files. if [ -x "`which locate`" ] then libraries=`locate libcrypto.a` else libraries=`find / -name libcrypto.a -print 2>/dev/null` fi for lib in $libraries do libdir=`dirname $lib` echo "Trying libcrypto $lib" >>findssl.log ${CC} ${STATIC} -o conftest conftest.c -L${libdir} -lcrypto 2>>findssl.log if [ -x ./conftest ] then ver=`./conftest 2>/dev/null` rm -f ./conftest echo "$ver $lib" fi done # # Clean up # rm -f conftest.c openssh-10.0p1/contrib/PaxHeaders.10889/gnome-ssh-askpass1.c100644 001750 001750 0000000003614775415623 0020404xustar0030 atime=1744182234.560375753 openssh-10.0p1/contrib/gnome-ssh-askpass1.c010064400017500001750000000125401477541562300167710ustar00djmdjm/* * Copyright (c) 2000-2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This is a simple GNOME SSH passphrase grabber. To use it, set the * environment variable SSH_ASKPASS to point to the location of * gnome-ssh-askpass before calling "ssh-add < /dev/null". * * There is only two run-time options: if you set the environment variable * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the * pointer will be grabbed too. These may have some benefit to security if * you don't trust your X server. We grab the keyboard always. */ /* * Compile with: * * cc `gnome-config --cflags gnome gnomeui` \ * gnome-ssh-askpass1.c -o gnome-ssh-askpass \ * `gnome-config --libs gnome gnomeui` * */ #include #include #include #include #include #include void report_failed_grab (void) { GtkWidget *err; err = gnome_message_box_new("Could not grab keyboard or mouse.\n" "A malicious client may be eavesdropping on your session.", GNOME_MESSAGE_BOX_ERROR, "EXIT", NULL); gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); gtk_object_set(GTK_OBJECT(err), "type", GTK_WINDOW_POPUP, NULL); gnome_dialog_run_and_close(GNOME_DIALOG(err)); } int passphrase_dialog(char *message) { char *passphrase; char **messages; int result, i, grab_server, grab_pointer; GtkWidget *dialog, *entry, *label; grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); messages = g_strsplit(message, "\\n", 0); if (messages) for(i = 0; messages[i]; i++) { label = gtk_label_new(messages[i]); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0); } entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), entry, FALSE, FALSE, 0); gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); gtk_widget_grab_focus(entry); /* Center window and prepare for grab */ gtk_object_set(GTK_OBJECT(dialog), "type", GTK_WINDOW_POPUP, NULL); gnome_dialog_set_default(GNOME_DIALOG(dialog), 0); gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, TRUE); gnome_dialog_close_hides(GNOME_DIALOG(dialog), TRUE); gtk_container_set_border_width(GTK_CONTAINER(GNOME_DIALOG(dialog)->vbox), GNOME_PAD); gtk_widget_show_all(dialog); /* Grab focus */ if (grab_server) XGrabServer(GDK_DISPLAY()); if (grab_pointer && gdk_pointer_grab(dialog->window, TRUE, 0, NULL, NULL, GDK_CURRENT_TIME)) goto nograb; if (gdk_keyboard_grab(dialog->window, FALSE, GDK_CURRENT_TIME)) goto nograbkb; /* Make close dialog */ gnome_dialog_editable_enters(GNOME_DIALOG(dialog), GTK_EDITABLE(entry)); /* Run dialog */ result = gnome_dialog_run(GNOME_DIALOG(dialog)); /* Ungrab */ if (grab_server) XUngrabServer(GDK_DISPLAY()); if (grab_pointer) gdk_pointer_ungrab(GDK_CURRENT_TIME); gdk_keyboard_ungrab(GDK_CURRENT_TIME); gdk_flush(); /* Report passphrase if user selected OK */ passphrase = gtk_entry_get_text(GTK_ENTRY(entry)); if (result == 0) puts(passphrase); /* Zero passphrase in memory */ memset(passphrase, '\0', strlen(passphrase)); gtk_entry_set_text(GTK_ENTRY(entry), passphrase); gnome_dialog_close(GNOME_DIALOG(dialog)); return (result == 0 ? 0 : -1); /* * At least one grab failed - ungrab what we got, and report the * failure to the user. Note that XGrabServer() cannot fail. */ nograbkb: gdk_pointer_ungrab(GDK_CURRENT_TIME); nograb: if (grab_server) XUngrabServer(GDK_DISPLAY()); gnome_dialog_close(GNOME_DIALOG(dialog)); report_failed_grab(); return (-1); } int main(int argc, char **argv) { char *message; int result; gnome_init("GNOME ssh-askpass", "0.1", argc, argv); if (argc == 2) message = argv[1]; else message = "Enter your OpenSSH passphrase:"; setvbuf(stdout, 0, _IONBF, 0); result = passphrase_dialog(message); return (result); } openssh-10.0p1/contrib/PaxHeaders.10889/gnome-ssh-askpass2.c100644 001750 001750 0000000003614775415623 0020405xustar0030 atime=1744182234.560375753 openssh-10.0p1/contrib/gnome-ssh-askpass2.c010064400017500001750000000225671477541562300170040ustar00djmdjm/* * Copyright (c) 2000-2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* GTK2 support by Nalin Dahyabhai */ /* * This is a simple GNOME SSH passphrase grabber. To use it, set the * environment variable SSH_ASKPASS to point to the location of * gnome-ssh-askpass before calling "ssh-add < /dev/null". * * There is only two run-time options: if you set the environment variable * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the * pointer will be grabbed too. These may have some benefit to security if * you don't trust your X server. We grab the keyboard always. */ #define GRAB_TRIES 16 #define GRAB_WAIT 250 /* milliseconds */ #define PROMPT_ENTRY 0 #define PROMPT_CONFIRM 1 #define PROMPT_NONE 2 /* * Compile with: * * cc -Wall `pkg-config --cflags gtk+-2.0` \ * gnome-ssh-askpass2.c -o gnome-ssh-askpass \ * `pkg-config --libs gtk+-2.0` * */ #include #include #include #include #include #include #include #include static void report_failed_grab (GtkWidget *parent_window, const char *what) { GtkWidget *err; err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Could not grab %s. A malicious client may be eavesdropping " "on your session.", what); gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); gtk_dialog_run(GTK_DIALOG(err)); gtk_widget_destroy(err); } static void ok_dialog(GtkWidget *entry, gpointer dialog) { g_return_if_fail(GTK_IS_DIALOG(dialog)); gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); } static gboolean check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog) { switch (event->keyval) { case GDK_KEY_Escape: /* esc -> close dialog */ gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); return TRUE; case GDK_KEY_Tab: /* tab -> focus close button */ gtk_widget_grab_focus(gtk_dialog_get_widget_for_response( dialog, GTK_RESPONSE_CLOSE)); return TRUE; default: /* eat all other key events */ return TRUE; } } static int parse_env_hex_color(const char *env, GdkColor *c) { const char *s; unsigned long ul; char *ep; size_t n; if ((s = getenv(env)) == NULL) return 0; memset(c, 0, sizeof(*c)); /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */ if (*s == '#') s++; else if (strncmp(s, "0x", 2) == 0) s += 2; n = strlen(s); if (n != 3 && n != 6) goto bad; ul = strtoul(s, &ep, 16); if (*ep != '\0' || ul > 0xffffff) { bad: fprintf(stderr, "Invalid $%s - invalid hex color code\n", env); return 0; } /* Valid hex sequence; expand into a GdkColor */ if (n == 3) { /* 4-bit RGB */ c->red = ((ul >> 8) & 0xf) << 12; c->green = ((ul >> 4) & 0xf) << 12; c->blue = (ul & 0xf) << 12; } else { /* 8-bit RGB */ c->red = ((ul >> 16) & 0xff) << 8; c->green = ((ul >> 8) & 0xff) << 8; c->blue = (ul & 0xff) << 8; } return 1; } static int passphrase_dialog(char *message, int prompt_type) { const char *failed; char *passphrase, *local; int result, grab_tries, grab_server, grab_pointer; int buttons, default_response; GtkWidget *parent_window, *dialog, *entry; GdkGrabStatus status; GdkColor fg, bg; int fg_set = 0, bg_set = 0; grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); grab_tries = 0; fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg); bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg); /* Create an invisible parent window so that GtkDialog doesn't * complain. */ parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); switch (prompt_type) { case PROMPT_CONFIRM: buttons = GTK_BUTTONS_YES_NO; default_response = GTK_RESPONSE_YES; break; case PROMPT_NONE: buttons = GTK_BUTTONS_CLOSE; default_response = GTK_RESPONSE_CLOSE; break; default: buttons = GTK_BUTTONS_OK_CANCEL; default_response = GTK_RESPONSE_OK; break; } dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, GTK_MESSAGE_QUESTION, buttons, "%s", message); gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH"); gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); if (fg_set) gtk_widget_modify_fg(dialog, GTK_STATE_NORMAL, &fg); if (bg_set) gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg); if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { entry = gtk_entry_new(); if (fg_set) gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg); if (bg_set) gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg); gtk_box_pack_start( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry, FALSE, FALSE, 0); gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); gtk_widget_grab_focus(entry); if (prompt_type == PROMPT_ENTRY) { gtk_widget_show(entry); /* Make close dialog */ g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(ok_dialog), dialog); } else { /* * Ensure the 'close' button is not focused by default * but is still reachable via tab. This is a bit of a * hack - it uses a hidden entry that responds to a * couple of keypress events (escape and tab only). */ gtk_widget_realize(entry); g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(check_none), dialog); } } /* Grab focus */ gtk_widget_show_now(dialog); if (grab_pointer) { for(;;) { status = gdk_pointer_grab( (gtk_widget_get_window(GTK_WIDGET(dialog))), TRUE, 0, NULL, NULL, GDK_CURRENT_TIME); if (status == GDK_GRAB_SUCCESS) break; usleep(GRAB_WAIT * 1000); if (++grab_tries > GRAB_TRIES) { failed = "mouse"; goto nograb; } } } for(;;) { 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); if (++grab_tries > GRAB_TRIES) { failed = "keyboard"; goto nograbkb; } } if (grab_server) { gdk_x11_grab_server(); } result = gtk_dialog_run(GTK_DIALOG(dialog)); /* Ungrab */ if (grab_server) 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 */ if (prompt_type == PROMPT_ENTRY) { passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); if (result == GTK_RESPONSE_OK) { local = g_locale_from_utf8(passphrase, strlen(passphrase), NULL, NULL, NULL); if (local != NULL) { puts(local); memset(local, '\0', strlen(local)); g_free(local); } else { puts(passphrase); } } /* Zero passphrase in memory */ memset(passphrase, '\b', strlen(passphrase)); gtk_entry_set_text(GTK_ENTRY(entry), passphrase); memset(passphrase, '\0', strlen(passphrase)); g_free(passphrase); } gtk_widget_destroy(dialog); if (result != GTK_RESPONSE_OK && result != GTK_RESPONSE_YES) return -1; return 0; 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_x11_get_default_xdisplay()); gtk_widget_destroy(dialog); report_failed_grab(parent_window, failed); return (-1); } int main(int argc, char **argv) { char *message, *prompt_mode; int result, prompt_type = PROMPT_ENTRY; gtk_init(&argc, &argv); if (argc > 1) { message = g_strjoinv(" ", argv + 1); } else { message = g_strdup("Enter your OpenSSH passphrase:"); } if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) { if (strcasecmp(prompt_mode, "confirm") == 0) prompt_type = PROMPT_CONFIRM; else if (strcasecmp(prompt_mode, "none") == 0) prompt_type = PROMPT_NONE; } setvbuf(stdout, 0, _IONBF, 0); result = passphrase_dialog(message, prompt_type); g_free(message); return (result); } openssh-10.0p1/contrib/PaxHeaders.10889/gnome-ssh-askpass3.c100644 001750 001750 0000000003614775415623 0020406xustar0030 atime=1744182234.560375753 openssh-10.0p1/contrib/gnome-ssh-askpass3.c010064400017500001750000000214101477541562300167670ustar00djmdjm/* * Copyright (c) 2000-2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* GTK2 support by Nalin Dahyabhai */ /* * This is a simple GNOME SSH passphrase grabber. To use it, set the * environment variable SSH_ASKPASS to point to the location of * gnome-ssh-askpass before calling "ssh-add < /dev/null". * * There is only two run-time options: if you set the environment variable * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the * pointer will be grabbed too. These may have some benefit to security if * you don't trust your X server. We grab the keyboard always. */ #define GRAB_TRIES 16 #define GRAB_WAIT 250 /* milliseconds */ #define PROMPT_ENTRY 0 #define PROMPT_CONFIRM 1 #define PROMPT_NONE 2 /* * Compile with: * * cc -Wall `pkg-config --cflags gtk+-2.0` \ * gnome-ssh-askpass2.c -o gnome-ssh-askpass \ * `pkg-config --libs gtk+-2.0` * */ #include #include #include #include #include #include #include #include static void ok_dialog(GtkWidget *entry, gpointer dialog) { g_return_if_fail(GTK_IS_DIALOG(dialog)); gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); } static gboolean check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog) { switch (event->keyval) { case GDK_KEY_Escape: /* esc -> close dialog */ gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); return TRUE; case GDK_KEY_Tab: /* tab -> focus close button */ gtk_widget_grab_focus(gtk_dialog_get_widget_for_response( dialog, GTK_RESPONSE_CLOSE)); return TRUE; default: /* eat all other key events */ return TRUE; } } static int parse_env_hex_color(const char *env, GdkColor *c) { const char *s; unsigned long ul; char *ep; size_t n; if ((s = getenv(env)) == NULL) return 0; memset(c, 0, sizeof(*c)); /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */ if (*s == '#') s++; else if (strncmp(s, "0x", 2) == 0) s += 2; n = strlen(s); if (n != 3 && n != 6) goto bad; ul = strtoul(s, &ep, 16); if (*ep != '\0' || ul > 0xffffff) { bad: fprintf(stderr, "Invalid $%s - invalid hex color code\n", env); return 0; } /* Valid hex sequence; expand into a GdkColor */ if (n == 3) { /* 4-bit RGB */ c->red = ((ul >> 8) & 0xf) << 12; c->green = ((ul >> 4) & 0xf) << 12; c->blue = (ul & 0xf) << 12; } else { /* 8-bit RGB */ c->red = ((ul >> 16) & 0xff) << 8; c->green = ((ul >> 8) & 0xff) << 8; c->blue = (ul & 0xff) << 8; } return 1; } static int passphrase_dialog(char *message, int prompt_type) { const char *failed; char *passphrase, *local; int result, grab_tries, grab_server, grab_pointer; int buttons, default_response; GtkWidget *parent_window, *dialog, *entry, *err; GdkGrabStatus status; GdkColor fg, bg; GdkSeat *seat; GdkDisplay *display; GdkSeatCapabilities caps; int fg_set = 0, bg_set = 0; grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); grab_tries = 0; fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg); bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg); /* Create an invisible parent window so that GtkDialog doesn't * complain. */ parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); switch (prompt_type) { case PROMPT_CONFIRM: buttons = GTK_BUTTONS_YES_NO; default_response = GTK_RESPONSE_YES; break; case PROMPT_NONE: buttons = GTK_BUTTONS_CLOSE; default_response = GTK_RESPONSE_CLOSE; break; default: buttons = GTK_BUTTONS_OK_CANCEL; default_response = GTK_RESPONSE_OK; break; } dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, GTK_MESSAGE_QUESTION, buttons, "%s", message); gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH"); gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); if (fg_set) gtk_widget_modify_fg(dialog, GTK_STATE_NORMAL, &fg); if (bg_set) gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg); if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { entry = gtk_entry_new(); if (fg_set) gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg); if (bg_set) gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg); gtk_box_pack_start( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry, FALSE, FALSE, 0); gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); gtk_widget_grab_focus(entry); if (prompt_type == PROMPT_ENTRY) { gtk_widget_show(entry); /* Make close dialog */ g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(ok_dialog), dialog); } else { /* * Ensure the 'close' button is not focused by default * but is still reachable via tab. This is a bit of a * hack - it uses a hidden entry that responds to a * couple of keypress events (escape and tab only). */ gtk_widget_realize(entry); g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(check_none), dialog); } } /* Grab focus */ gtk_widget_show_now(dialog); display = gtk_widget_get_display(GTK_WIDGET(dialog)); seat = gdk_display_get_default_seat(display); caps = GDK_SEAT_CAPABILITY_KEYBOARD; if (grab_pointer) caps |= GDK_SEAT_CAPABILITY_ALL_POINTING; if (grab_server) caps = GDK_SEAT_CAPABILITY_ALL; for (;;) { status = gdk_seat_grab(seat, gtk_widget_get_window(dialog), caps, TRUE, NULL, NULL, NULL, NULL); if (status == GDK_GRAB_SUCCESS) break; usleep(GRAB_WAIT * 1000); if (++grab_tries > GRAB_TRIES) goto nograb; } result = gtk_dialog_run(GTK_DIALOG(dialog)); /* Ungrab */ gdk_seat_ungrab(seat); gdk_display_flush(display); /* Report passphrase if user selected OK */ if (prompt_type == PROMPT_ENTRY) { passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); if (result == GTK_RESPONSE_OK) { local = g_locale_from_utf8(passphrase, strlen(passphrase), NULL, NULL, NULL); if (local != NULL) { puts(local); memset(local, '\0', strlen(local)); g_free(local); } else { puts(passphrase); } } /* Zero passphrase in memory */ memset(passphrase, '\b', strlen(passphrase)); gtk_entry_set_text(GTK_ENTRY(entry), passphrase); memset(passphrase, '\0', strlen(passphrase)); g_free(passphrase); } gtk_widget_destroy(dialog); if (result != GTK_RESPONSE_OK && result != GTK_RESPONSE_YES) return -1; return 0; nograb: gtk_widget_destroy(dialog); err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Could not grab input. A malicious client may be eavesdropping " "on your session."); gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); gtk_dialog_run(GTK_DIALOG(err)); gtk_widget_destroy(err); return -1; } int main(int argc, char **argv) { char *message, *prompt_mode; int result, prompt_type = PROMPT_ENTRY; gtk_init(&argc, &argv); if (argc > 1) { message = g_strjoinv(" ", argv + 1); } else { message = g_strdup("Enter your OpenSSH passphrase:"); } if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) { if (strcasecmp(prompt_mode, "confirm") == 0) prompt_type = PROMPT_CONFIRM; else if (strcasecmp(prompt_mode, "none") == 0) prompt_type = PROMPT_NONE; } setvbuf(stdout, 0, _IONBF, 0); result = passphrase_dialog(message, prompt_type); g_free(message); return (result); } openssh-10.0p1/contrib/PaxHeaders.10889/hpux040755 001750 001750 0000000003614775415623 0015531xustar0030 atime=1744182234.560375753 openssh-10.0p1/contrib/hpux004075500017500001750000000000001477541562300141075ustar00djmdjmopenssh-10.0p1/contrib/hpux/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0016460xustar0030 atime=1744182234.560375753 openssh-10.0p1/contrib/hpux/README010064400017500001750000000021641477541562300150460ustar00djmdjmREADME for OpenSSH HP-UX contrib files Kevin Steves sshd: configuration file for sshd.rc sshd.rc: SSH startup script egd: configuration file for egd.rc egd.rc: EGD (entropy gathering daemon) startup script To install: sshd.rc: o Verify paths in sshd.rc match your local installation (WHAT_PATH and WHAT_PID) o Customize sshd if needed (SSHD_ARGS) o Install: # cp sshd /etc/rc.config.d # chmod 444 /etc/rc.config.d/sshd # cp sshd.rc /sbin/init.d # chmod 555 /sbin/init.d/sshd.rc # ln -s /sbin/init.d/sshd.rc /sbin/rc1.d/K100sshd # ln -s /sbin/init.d/sshd.rc /sbin/rc2.d/S900sshd egd.rc: o Verify egd.pl path in egd.rc matches your local installation (WHAT_PATH) o Customize egd if needed (EGD_ARGS and EGD_LOG) o Add pseudo account: # groupadd egd # useradd -g egd egd # mkdir -p /etc/opt/egd # chown egd:egd /etc/opt/egd # chmod 711 /etc/opt/egd o Install: # cp egd /etc/rc.config.d # chmod 444 /etc/rc.config.d/egd # cp egd.rc /sbin/init.d # chmod 555 /sbin/init.d/egd.rc # ln -s /sbin/init.d/egd.rc /sbin/rc1.d/K600egd # ln -s /sbin/init.d/egd.rc /sbin/rc2.d/S400egd openssh-10.0p1/contrib/hpux/PaxHeaders.10889/egd100644 001750 001750 0000000003614775415623 0016262xustar0030 atime=1744182234.560375753 openssh-10.0p1/contrib/hpux/egd010064400017500001750000000006051477541562300146460ustar00djmdjm# EGD_START: Set to 1 to start entropy gathering daemon # EGD_ARGS: Command line arguments to pass to egd # EGD_LOG: EGD stdout and stderr log file (default /etc/opt/egd/egd.log) # # To configure the egd environment: # groupadd egd # useradd -g egd egd # mkdir -p /etc/opt/egd # chown egd:egd /etc/opt/egd # chmod 711 /etc/opt/egd EGD_START=1 EGD_ARGS='/etc/opt/egd/entropy' EGD_LOG= openssh-10.0p1/contrib/hpux/PaxHeaders.10889/egd.rc100755 001750 001750 0000000003614775415623 0016670xustar0030 atime=1744182234.561352931 openssh-10.0p1/contrib/hpux/egd.rc010075500017500001750000000042471477541562300152620ustar00djmdjm#!/sbin/sh # # egd.rc: EGD start-up and shutdown script # # Allowed exit values: # 0 = success; causes "OK" to show up in checklist. # 1 = failure; causes "FAIL" to show up in checklist. # 2 = skip; causes "N/A" to show up in the checklist. # Use this value if execution of this script is overridden # by the use of a control variable, or if this script is not # appropriate to execute for some other reason. # 3 = reboot; causes the system to be rebooted after execution. # Input and output: # stdin is redirected from /dev/null # # stdout and stderr are redirected to the /etc/rc.log file # during checklist mode, or to the console in raw mode. umask 022 PATH=/usr/sbin:/usr/bin:/sbin export PATH WHAT='EGD (entropy gathering daemon)' WHAT_PATH=/opt/perl/bin/egd.pl WHAT_CONFIG=/etc/rc.config.d/egd WHAT_LOG=/etc/opt/egd/egd.log # NOTE: If your script executes in run state 0 or state 1, then /usr might # not be available. Do not attempt to access commands or files in # /usr unless your script executes in run state 2 or greater. Other # file systems typically not mounted until run state 2 include /var # and /opt. rval=0 # Check the exit value of a command run by this script. If non-zero, the # exit code is echoed to the log file and the return value of this script # is set to indicate failure. set_return() { x=$? if [ $x -ne 0 ]; then echo "EXIT CODE: $x" rval=1 # script FAILed fi } case $1 in 'start_msg') echo "Starting $WHAT" ;; 'stop_msg') echo "Stopping $WHAT" ;; 'start') if [ -f $WHAT_CONFIG ] ; then . $WHAT_CONFIG else echo "ERROR: $WHAT_CONFIG defaults file MISSING" fi if [ "$EGD_START" -eq 1 -a -x $WHAT_PATH ]; then EGD_LOG=${EGD_LOG:-$WHAT_LOG} su egd -c "nohup $WHAT_PATH $EGD_ARGS >$EGD_LOG 2>&1" && echo $WHAT started set_return else rval=2 fi ;; 'stop') pid=`ps -fuegd | awk '$1 == "egd" { print $2 }'` if [ "X$pid" != "X" ]; then if kill "$pid"; then echo "$WHAT stopped" else rval=1 echo "Unable to stop $WHAT" fi fi set_return ;; *) echo "usage: $0 {start|stop|start_msg|stop_msg}" rval=1 ;; esac exit $rval openssh-10.0p1/contrib/hpux/PaxHeaders.10889/sshd100644 001750 001750 0000000003614775415623 0016464xustar0030 atime=1744182234.561352931 openssh-10.0p1/contrib/hpux/sshd010064400017500001750000000001731477541562300150500ustar00djmdjm# SSHD_START: Set to 1 to start SSH daemon # SSHD_ARGS: Command line arguments to pass to sshd # SSHD_START=1 SSHD_ARGS= openssh-10.0p1/contrib/hpux/PaxHeaders.10889/sshd.rc100755 001750 001750 0000000003614775415623 0017072xustar0030 atime=1744182234.561352931 openssh-10.0p1/contrib/hpux/sshd.rc010075500017500001750000000036661477541562300154700ustar00djmdjm#!/sbin/sh # # sshd.rc: SSH daemon start-up and shutdown script # # Allowed exit values: # 0 = success; causes "OK" to show up in checklist. # 1 = failure; causes "FAIL" to show up in checklist. # 2 = skip; causes "N/A" to show up in the checklist. # Use this value if execution of this script is overridden # by the use of a control variable, or if this script is not # appropriate to execute for some other reason. # 3 = reboot; causes the system to be rebooted after execution. # Input and output: # stdin is redirected from /dev/null # # stdout and stderr are redirected to the /etc/rc.log file # during checklist mode, or to the console in raw mode. PATH=/usr/sbin:/usr/bin:/sbin export PATH WHAT='OpenSSH' WHAT_PATH=/opt/openssh/sbin/sshd WHAT_PID=/var/run/sshd.pid WHAT_CONFIG=/etc/rc.config.d/sshd # NOTE: If your script executes in run state 0 or state 1, then /usr might # not be available. Do not attempt to access commands or files in # /usr unless your script executes in run state 2 or greater. Other # file systems typically not mounted until run state 2 include /var # and /opt. rval=0 # Check the exit value of a command run by this script. If non-zero, the # exit code is echoed to the log file and the return value of this script # is set to indicate failure. set_return() { x=$? if [ $x -ne 0 ]; then echo "EXIT CODE: $x" rval=1 # script FAILed fi } case $1 in 'start_msg') echo "Starting $WHAT" ;; 'stop_msg') echo "Stopping $WHAT" ;; 'start') if [ -f $WHAT_CONFIG ] ; then . $WHAT_CONFIG else echo "ERROR: $WHAT_CONFIG defaults file MISSING" fi if [ "$SSHD_START" -eq 1 -a -x "$WHAT_PATH" ]; then $WHAT_PATH $SSHD_ARGS && echo "$WHAT started" set_return else rval=2 fi ;; 'stop') if kill `cat $WHAT_PID`; then echo "$WHAT stopped" else rval=1 echo "Unable to stop $WHAT" fi set_return ;; *) echo "usage: $0 {start|stop|start_msg|stop_msg}" rval=1 ;; esac exit $rval openssh-10.0p1/contrib/PaxHeaders.10889/redhat040755 001750 001750 0000000003614775415623 0016014xustar0030 atime=1744182234.561352931 openssh-10.0p1/contrib/redhat004075500017500001750000000000001477541562300143725ustar00djmdjmopenssh-10.0p1/contrib/redhat/PaxHeaders.10889/gnome-ssh-askpass.csh100644 001750 001750 0000000003614775415623 0022125xustar0030 atime=1744182234.561352931 openssh-10.0p1/contrib/redhat/gnome-ssh-askpass.csh010064400017500001750000000000721477541562300205070ustar00djmdjmsetenv SSH_ASKPASS /usr/libexec/openssh/gnome-ssh-askpass openssh-10.0p1/contrib/redhat/PaxHeaders.10889/gnome-ssh-askpass.sh100644 001750 001750 0000000003614775415623 0021762xustar0030 atime=1744182234.561352931 openssh-10.0p1/contrib/redhat/gnome-ssh-askpass.sh010064400017500001750000000001061477541562300203420ustar00djmdjmSSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass export SSH_ASKPASS openssh-10.0p1/contrib/redhat/PaxHeaders.10889/openssh.spec100644 001750 001750 0000000003614775415623 0020416xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/redhat/openssh.spec010064400017500001750000000724061477541562300170120ustar00djmdjm%global ver 10.0p1 %global rel 1%{?dist} # OpenSSH privilege separation requires a user & group ID %global sshd_uid 74 %global sshd_gid 74 # Version of ssh-askpass %global aversion 1.2.4.1 # Do we want to disable building of x11-askpass? (1=yes 0=no) %global no_x11_askpass 0 # Do we want to disable building of gnome-askpass? (1=yes 0=no) %global no_gnome_askpass 0 # Do we want to link against a static libcrypto? (1=yes 0=no) %global static_libcrypto 0 # Do we want smartcard support (1=yes 0=no) %global scard 0 # Use GTK2 instead of GNOME in gnome-ssh-askpass %global gtk2 1 %global without_openssl 0 # build without openssl where 1.1.1 is not available %if %{defined fedora} && 0%{?fedora} <= 28 %global without_openssl 1 %endif %if %{defined rhel} && 0%{?rhel} <= 7 %global without_openssl 1 %endif # Do we want kerberos5 support (1=yes 0=no) %global kerberos5 1 # Reserve options to override askpass settings with: # rpm -ba|--rebuild --define 'skip_xxx 1' %{?skip_x11_askpass:%global no_x11_askpass 1} %{?skip_gnome_askpass:%global no_gnome_askpass 1} # Add option to build without GTK2 for older platforms with only GTK+. # RedHat <= 7.2 and Red Hat Advanced Server 2.1 are examples. # rpm -ba|--rebuild --define 'no_gtk2 1' %{?no_gtk2:%global gtk2 0} # Options for static OpenSSL link: # rpm -ba|--rebuild --define "static_openssl 1" %{?static_openssl:%global static_libcrypto 1} # Options for Smartcard support: (needs libsectok and openssl-engine) # rpm -ba|--rebuild --define "smartcard 1" %{?smartcard:%global scard 1} # Is this a build for the rescue CD (without PAM)? (1=yes 0=no) %global rescue 0 %{?build_rescue:%global rescue 1} # Turn off some stuff for resuce builds %if %{rescue} %global kerberos5 0 %endif Summary: The OpenSSH implementation of SSH protocol version 2. Name: openssh Version: %{ver} %if %{rescue} Release: %{rel}rescue %else Release: %{rel} %endif URL: https://www.openssh.com/portable.html Source0: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: http://www.jmknoble.net/software/x11-ssh-askpass/x11-ssh-askpass-%{aversion}.tar.gz License: BSD Group: Applications/Internet BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot Obsoletes: ssh Requires: initscripts >= 5.20 BuildRequires: perl %if ! %{without_openssl} BuildRequires: openssl-devel >= 1.1.1 %endif BuildRequires: /bin/login BuildRequires: glibc-devel, pam %if ! %{no_x11_askpass} BuildRequires: /usr/include/X11/Xlib.h # Xt development tools BuildRequires: libXt-devel # Provides xmkmf BuildRequires: imake # Rely on relatively recent gtk BuildRequires: gtk2-devel %endif %if ! %{no_gnome_askpass} BuildRequires: pkgconfig %endif %if %{kerberos5} BuildRequires: krb5-devel BuildRequires: krb5-libs %endif %package clients Summary: OpenSSH clients. Requires: openssh = %{version}-%{release} Group: Applications/Internet Obsoletes: ssh-clients %package server Summary: The OpenSSH server daemon. Group: System Environment/Daemons Obsoletes: ssh-server Requires: openssh = %{version}-%{release}, chkconfig >= 0.9 Requires: /etc/pam.d/system-auth %package askpass Summary: A passphrase dialog for OpenSSH and X. Group: Applications/Internet Requires: openssh = %{version}-%{release} Obsoletes: ssh-extras %package askpass-gnome Summary: A passphrase dialog for OpenSSH, X, and GNOME. Group: Applications/Internet Requires: openssh = %{version}-%{release} Obsoletes: ssh-extras %description SSH (Secure SHell) is a program for logging into and executing commands on a remote machine. SSH is intended to replace rlogin and rsh, and to provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections and arbitrary TCP/IP ports can also be forwarded over the secure channel. OpenSSH is OpenBSD's version of the last free version of SSH, bringing it up to date in terms of security and features, as well as removing all patented algorithms to separate libraries. This package includes the core files necessary for both the OpenSSH client and server. To make this package useful, you should also install openssh-clients, openssh-server, or both. %description clients OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package includes the clients necessary to make encrypted connections to SSH servers. You'll also need to install the openssh package on OpenSSH clients. %description server OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains the secure shell daemon (sshd). The sshd daemon allows SSH clients to securely connect to your SSH server. You also need to have the openssh package installed. %description askpass OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains an X11 passphrase dialog for OpenSSH. %description askpass-gnome OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains an X11 passphrase dialog for OpenSSH and the GNOME GUI desktop environment. %prep %if ! %{no_x11_askpass} %setup -q -a 1 %else %setup -q %endif %build %if %{rescue} CFLAGS="$RPM_OPT_FLAGS -Os"; export CFLAGS %endif %configure \ --sysconfdir=%{_sysconfdir}/ssh \ --libexecdir=%{_libexecdir}/openssh \ --datadir=%{_datadir}/openssh \ --with-default-path=/usr/local/bin:/bin:/usr/bin \ --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ --with-privsep-path=%{_var}/empty/sshd \ --mandir=%{_mandir} \ --with-mantype=man \ --disable-strip \ %if %{without_openssl} --without-openssl \ %endif %if %{scard} --with-smartcard \ %endif %if %{rescue} --without-pam \ %else --with-pam \ %endif %if %{kerberos5} --with-kerberos5=$K5DIR \ %endif %if %{static_libcrypto} perl -pi -e "s|-lcrypto|%{_libdir}/libcrypto.a|g" Makefile %endif make %if ! %{no_x11_askpass} pushd x11-ssh-askpass-%{aversion} %configure --libexecdir=%{_libexecdir}/openssh xmkmf -a make popd %endif # Define a variable to toggle gnome1/gtk2 building. This is necessary # because RPM doesn't handle nested %if statements. %if %{gtk2} gtk2=yes %else gtk2=no %endif %if ! %{no_gnome_askpass} pushd contrib if [ $gtk2 = yes ] ; then make gnome-ssh-askpass2 mv gnome-ssh-askpass2 gnome-ssh-askpass else make gnome-ssh-askpass1 mv gnome-ssh-askpass1 gnome-ssh-askpass fi popd %endif %install rm -rf $RPM_BUILD_ROOT mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd make install DESTDIR=$RPM_BUILD_ROOT install -d $RPM_BUILD_ROOT/etc/pam.d/ install -d $RPM_BUILD_ROOT/etc/rc.d/init.d install -d $RPM_BUILD_ROOT%{_libexecdir}/openssh install -m644 contrib/redhat/sshd.pam $RPM_BUILD_ROOT/etc/pam.d/sshd install -m755 contrib/redhat/sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd %if ! %{no_x11_askpass} install x11-ssh-askpass-%{aversion}/x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/x11-ssh-askpass ln -s x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/ssh-askpass %endif %if ! %{no_gnome_askpass} install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass %endif %if ! %{scard} rm -f $RPM_BUILD_ROOT/usr/share/openssh/Ssh.bin %endif %if ! %{no_gnome_askpass} install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ install -m 755 contrib/redhat/gnome-ssh-askpass.csh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ install -m 755 contrib/redhat/gnome-ssh-askpass.sh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ %endif perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %clean rm -rf $RPM_BUILD_ROOT %triggerun server -- ssh-server if [ "$1" != 0 -a -r /var/run/sshd.pid ] ; then touch /var/run/sshd.restart fi %triggerun server -- openssh-server < 2.5.0p1 # Count the number of HostKey and HostDsaKey statements we have. gawk 'BEGIN {IGNORECASE=1} /^hostkey/ || /^hostdsakey/ {sawhostkey = sawhostkey + 1} END {exit sawhostkey}' /etc/ssh/sshd_config # And if we only found one, we know the client was relying on the old default # behavior, which loaded the the SSH2 DSA host key when HostDsaKey wasn't # specified. Now that HostKey is used for both SSH1 and SSH2 keys, specifying # one nullifies the default, which would have loaded both. if [ $? -eq 1 ] ; then echo HostKey /etc/ssh/ssh_host_rsa_key >> /etc/ssh/sshd_config echo HostKey /etc/ssh/ssh_host_dsa_key >> /etc/ssh/sshd_config fi %triggerpostun server -- ssh-server if [ "$1" != 0 ] ; then /sbin/chkconfig --add sshd if test -f /var/run/sshd.restart ; then rm -f /var/run/sshd.restart /sbin/service sshd start > /dev/null 2>&1 || : fi fi %pre server %{_sbindir}/groupadd -r -g %{sshd_gid} sshd 2>/dev/null || : %{_sbindir}/useradd -d /var/empty/sshd -s /bin/false -u %{sshd_uid} \ -g sshd -M -r sshd 2>/dev/null || : %post server /sbin/chkconfig --add sshd %postun server /sbin/service sshd condrestart > /dev/null 2>&1 || : %preun server if [ "$1" = 0 ] then /sbin/service sshd stop > /dev/null 2>&1 || : /sbin/chkconfig --del sshd fi %files %defattr(-,root,root) %doc CREDITS ChangeLog INSTALL LICENCE OVERVIEW README* PROTOCOL* TODO %attr(0755,root,root) %{_bindir}/scp %attr(0644,root,root) %{_mandir}/man1/scp.1* %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli %if ! %{rescue} %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0644,root,root) %{_mandir}/man1/ssh-keygen.1* %attr(0755,root,root) %dir %{_libexecdir}/openssh %attr(4711,root,root) %{_libexecdir}/openssh/ssh-keysign %attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper %attr(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper %attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8* %attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8* %attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8* %endif %if %{scard} %attr(0755,root,root) %dir %{_datadir}/openssh %attr(0644,root,root) %{_datadir}/openssh/Ssh.bin %endif %files clients %defattr(-,root,root) %attr(0755,root,root) %{_bindir}/ssh %attr(0644,root,root) %{_mandir}/man1/ssh.1* %attr(0644,root,root) %{_mandir}/man5/ssh_config.5* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config %if ! %{rescue} %attr(2755,root,nobody) %{_bindir}/ssh-agent %attr(0755,root,root) %{_bindir}/ssh-add %attr(0755,root,root) %{_bindir}/ssh-keyscan %attr(0755,root,root) %{_bindir}/sftp %attr(0644,root,root) %{_mandir}/man1/ssh-agent.1* %attr(0644,root,root) %{_mandir}/man1/ssh-add.1* %attr(0644,root,root) %{_mandir}/man1/ssh-keyscan.1* %attr(0644,root,root) %{_mandir}/man1/sftp.1* %endif %if ! %{rescue} %files server %defattr(-,root,root) %dir %attr(0111,root,root) %{_var}/empty/sshd %attr(0755,root,root) %{_sbindir}/sshd %attr(0755,root,root) %{_libexecdir}/openssh/sshd-session %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server %attr(0644,root,root) %{_mandir}/man8/sshd.8* %attr(0644,root,root) %{_mandir}/man5/moduli.5* %attr(0644,root,root) %{_mandir}/man5/sshd_config.5* %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config %attr(0600,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0755,root,root) %config /etc/rc.d/init.d/sshd %endif %if ! %{no_x11_askpass} %files askpass %defattr(-,root,root) %doc x11-ssh-askpass-%{aversion}/README %doc x11-ssh-askpass-%{aversion}/ChangeLog %doc x11-ssh-askpass-%{aversion}/SshAskpass*.ad %{_libexecdir}/openssh/ssh-askpass %attr(0755,root,root) %{_libexecdir}/openssh/x11-ssh-askpass %endif %if ! %{no_gnome_askpass} %files askpass-gnome %defattr(-,root,root) %attr(0755,root,root) %config %{_sysconfdir}/profile.d/gnome-ssh-askpass.* %attr(0755,root,root) %{_libexecdir}/openssh/gnome-ssh-askpass %endif %changelog * Mon Oct 16 2023 Fabio Pedretti - Remove reference of dropped sshd.pam.old file - Update openssl-devel dependency to require >= 1.1.1 - Build with --without-openssl elsewhere - Remove ancient build6x config, intended for RHL 6.x (the distro predating Fedora, not RHEL) * Thu Oct 28 2021 Damien Miller - Remove remaining traces of --with-md5-passwords * Mon Jul 20 2020 Damien Miller - Add ssh-sk-helper and corresponding manual page. * Sat Feb 10 2018 Darren Tucker - Update openssl-devel dependency to match current requirements. - Handle Fedora >=6 openssl 1.0 compat libs. - Remove SSH1 from description. - Don't strip binaries at build time so that debuginfo package can be created. * Sun Nov 16 2014 Nico Kadel-Garcia - Add '--mandir' and '--with-mantype' for RHEL 5 compatibility - Add 'dist' option to 'ver' so package names reflect OS at build time - Always include x11-ssh-askpass tarball in SRPM - Add openssh-x11-aspass BuildRequires for libXT-devel, imake, gtk2-devel - Discard 'K5DIR' reporting, not usable inside 'mock' for RHEL 5 compatibility - Discard obsolete '--with-rsh' configure option - Update openssl-devel dependency to 0.9.8f, as found in autoconf * Wed Jul 14 2010 Tim Rice - test for skip_x11_askpass (line 77) should have been for no_x11_askpass * Mon Jun 2 2003 Damien Miller - Remove noip6 option. This may be controlled at run-time in client config file using new AddressFamily directive * Mon May 12 2003 Damien Miller - Don't install profile.d scripts when not building with GNOME/GTK askpass (patch from bet@rahul.net) * Tue Oct 01 2002 Damien Miller - Install ssh-agent setgid nobody to prevent ptrace() key theft attacks * Mon Sep 30 2002 Damien Miller - Use contrib/ Makefile for building askpass programs * Fri Jun 21 2002 Damien Miller - Merge in spec changes from seba@iq.pl (Sebastian Pachuta) - Add new {ssh,sshd}_config.5 manpages - Add new ssh-keysign program and remove setuid from ssh client * Fri May 10 2002 Damien Miller - Merge in spec changes from RedHat, reorgansie a little - Add Privsep user, group and directory * Thu Mar 7 2002 Nalin Dahyabhai 3.1p1-2 - bump and grind (through the build system) * Thu Mar 7 2002 Nalin Dahyabhai 3.1p1-1 - require sharutils for building (mindrot #137) - require db1-devel only when building for 6.x (#55105), which probably won't work anyway (3.1 requires OpenSSL 0.9.6 to build), but what the heck - require pam-devel by file (not by package name) again - add Markus's patch to compile with OpenSSL 0.9.5a (from http://bugzilla.mindrot.org/show_bug.cgi?id=141) and apply it if we're building for 6.x * Thu Mar 7 2002 Nalin Dahyabhai 3.1p1-0 - update to 3.1p1 * Tue Mar 5 2002 Nalin Dahyabhai SNAP-20020305 - update to SNAP-20020305 - drop debug patch, fixed upstream * Wed Feb 20 2002 Nalin Dahyabhai SNAP-20020220 - update to SNAP-20020220 for testing purposes (you've been warned, if there's anything to be warned about, gss patches won't apply, I don't mind) * Wed Feb 13 2002 Nalin Dahyabhai 3.0.2p1-3 - add patches from Simon Wilkinson and Nicolas Williams for GSSAPI key exchange, authentication, and named key support * Wed Jan 23 2002 Nalin Dahyabhai 3.0.2p1-2 - remove dependency on db1-devel, which has just been swallowed up whole by gnome-libs-devel * Sat Dec 29 2001 Nalin Dahyabhai - adjust build dependencies so that build6x actually works right (fix from Hugo van der Kooij) * Tue Dec 4 2001 Nalin Dahyabhai 3.0.2p1-1 - update to 3.0.2p1 * Fri Nov 16 2001 Nalin Dahyabhai 3.0.1p1-1 - update to 3.0.1p1 * Tue Nov 13 2001 Nalin Dahyabhai - update to current CVS (not for use in distribution) * Thu Nov 8 2001 Nalin Dahyabhai 3.0p1-1 - merge some of Damien Miller changes from the upstream 3.0p1 spec file and init script * Wed Nov 7 2001 Nalin Dahyabhai - update to 3.0p1 - update to x11-ssh-askpass 1.2.4.1 - change build dependency on a file from pam-devel to the pam-devel package - replace primes with moduli * Thu Sep 27 2001 Nalin Dahyabhai 2.9p2-9 - incorporate fix from Markus Friedl's advisory for IP-based authorization bugs * Thu Sep 13 2001 Bernhard Rosenkraenzer 2.9p2-8 - Merge changes to rescue build from current sysadmin survival cd * Thu Sep 6 2001 Nalin Dahyabhai 2.9p2-7 - fix scp's server's reporting of file sizes, and build with the proper preprocessor define to get large-file capable open(), stat(), etc. (sftp has been doing this correctly all along) (#51827) - configure without --with-ipv4-default on RHL 7.x and newer (#45987,#52247) - pull cvs patch to fix support for /etc/nologin for non-PAM logins (#47298) - mark profile.d scriptlets as config files (#42337) - refer to Jason Stone's mail for zsh workaround for exit-hanging quasi-bug - change a couple of log() statements to debug() statements (#50751) - pull cvs patch to add -t flag to sshd (#28611) - clear fd_sets correctly (one bit per FD, not one byte per FD) (#43221) * Mon Aug 20 2001 Nalin Dahyabhai 2.9p2-6 - add db1-devel as a BuildPrerequisite (noted by Hans Ecke) * Thu Aug 16 2001 Nalin Dahyabhai - pull cvs patch to fix remote port forwarding with protocol 2 * Thu Aug 9 2001 Nalin Dahyabhai - pull cvs patch to add session initialization to no-pty sessions - pull cvs patch to not cut off challengeresponse auth needlessly - refuse to do X11 forwarding if xauth isn't there, handy if you enable it by default on a system that doesn't have X installed (#49263) * Wed Aug 8 2001 Nalin Dahyabhai - don't apply patches to code we don't intend to build (spotted by Matt Galgoci) * Mon Aug 6 2001 Nalin Dahyabhai - pass OPTIONS correctly to initlog (#50151) * Wed Jul 25 2001 Nalin Dahyabhai - switch to x11-ssh-askpass 1.2.2 * Wed Jul 11 2001 Nalin Dahyabhai - rebuild in new environment * Mon Jun 25 2001 Nalin Dahyabhai - disable the gssapi patch * Mon Jun 18 2001 Nalin Dahyabhai - update to 2.9p2 - refresh to a new version of the gssapi patch * Thu Jun 7 2001 Nalin Dahyabhai - change Copyright: BSD to License: BSD - add Markus Friedl's unverified patch for the cookie file deletion problem so that we can verify it - drop patch to check if xauth is present (was folded into cookie patch) - don't apply gssapi patches for the errata candidate - clear supplemental groups list at startup * Fri May 25 2001 Nalin Dahyabhai - fix an error parsing the new default sshd_config - add a fix from Markus Friedl (via openssh-unix-dev) for ssh-keygen not dealing with comments right * Thu May 24 2001 Nalin Dahyabhai - add in Simon Wilkinson's GSSAPI patch to give it some testing in-house, to be removed before the next beta cycle because it's a big departure from the upstream version * Thu May 3 2001 Nalin Dahyabhai - finish marking strings in the init script for translation - modify init script to source /etc/sysconfig/sshd and pass $OPTIONS to sshd at startup (change merged from openssh.com init script, originally by Pekka Savola) - refuse to do X11 forwarding if xauth isn't there, handy if you enable it by default on a system that doesn't have X installed * Wed May 2 2001 Nalin Dahyabhai - update to 2.9 - drop various patches that came from or went upstream or to or from CVS * Wed Apr 18 2001 Nalin Dahyabhai - only require initscripts 5.00 on 6.2 (reported by Peter Bieringer) * Sun Apr 8 2001 Preston Brown - remove explicit openssl requirement, fixes builddistro issue - make initscript stop() function wait until sshd really dead to avoid races in condrestart * Mon Apr 2 2001 Nalin Dahyabhai - mention that challengereponse supports PAM, so disabling password doesn't limit users to pubkey and rsa auth (#34378) - bypass the daemon() function in the init script and call initlog directly, because daemon() won't start a daemon it detects is already running (like open connections) - require the version of openssl we had when we were built * Fri Mar 23 2001 Nalin Dahyabhai - make do_pam_setcred() smart enough to know when to establish creds and when to reinitialize them - add in a couple of other fixes from Damien for inclusion in the errata * Thu Mar 22 2001 Nalin Dahyabhai - update to 2.5.2p2 - call setcred() again after initgroups, because the "creds" could actually be group memberships * Tue Mar 20 2001 Nalin Dahyabhai - update to 2.5.2p1 (includes endianness fixes in the rijndael implementation) - don't enable challenge-response by default until we find a way to not have too many userauth requests (we may make up to six pubkey and up to three password attempts as it is) - remove build dependency on rsh to match openssh.com's packages more closely * Sat Mar 3 2001 Nalin Dahyabhai - remove dependency on openssl -- would need to be too precise * Fri Mar 2 2001 Nalin Dahyabhai - rebuild in new environment * Mon Feb 26 2001 Nalin Dahyabhai - Revert the patch to move pam_open_session. - Init script and spec file changes from Pekka Savola. (#28750) - Patch sftp to recognize '-o protocol' arguments. (#29540) * Thu Feb 22 2001 Nalin Dahyabhai - Chuck the closing patch. - Add a trigger to add host keys for protocol 2 to the config file, now that configuration file syntax requires us to specify it with HostKey if we specify any other HostKey values, which we do. * Tue Feb 20 2001 Nalin Dahyabhai - Redo patch to move pam_open_session after the server setuid()s to the user. - Rework the nopam patch to use be picked up by autoconf. * Mon Feb 19 2001 Nalin Dahyabhai - Update for 2.5.1p1. - Add init script mods from Pekka Savola. - Tweak the init script to match the CVS contrib script more closely. - Redo patch to ssh-add to try to adding both identity and id_dsa to also try adding id_rsa. * Fri Feb 16 2001 Nalin Dahyabhai - Update for 2.5.0p1. - Use $RPM_OPT_FLAGS instead of -O when building gnome-ssh-askpass - Resync with parts of Damien Miller's openssh.spec from CVS, including update of x11 askpass to 1.2.0. - Only require openssl (don't prereq) because we generate keys in the init script now. * Tue Feb 13 2001 Nalin Dahyabhai - Don't open a PAM session until we've forked and become the user (#25690). - Apply Andrew Bartlett's patch for letting pam_authenticate() know which host the user is attempting a login from. - Resync with parts of Damien Miller's openssh.spec from CVS. - Don't expose KbdInt responses in debug messages (from CVS). - Detect and handle errors in rsa_{public,private}_decrypt (from CVS). * Wed Feb 7 2001 Trond Eivind Glomsrxd - i18n-tweak to initscript. * Tue Jan 23 2001 Nalin Dahyabhai - More gettextizing. - Close all files after going into daemon mode (needs more testing). - Extract patch from CVS to handle auth banners (in the client). - Extract patch from CVS to handle compat weirdness. * Fri Jan 19 2001 Nalin Dahyabhai - Finish with the gettextizing. * Thu Jan 18 2001 Nalin Dahyabhai - Fix a bug in auth2-pam.c (#23877) - Gettextize the init script. * Wed Dec 20 2000 Nalin Dahyabhai - Incorporate a switch for using PAM configs for 6.x, just in case. * Tue Dec 5 2000 Nalin Dahyabhai - Incorporate Bero's changes for a build specifically for rescue CDs. * Wed Nov 29 2000 Nalin Dahyabhai - Don't treat pam_setcred() failure as fatal unless pam_authenticate() has succeeded, to allow public-key authentication after a failure with "none" authentication. (#21268) * Tue Nov 28 2000 Nalin Dahyabhai - Update to x11-askpass 1.1.1. (#21301) - Don't second-guess fixpaths, which causes paths to get fixed twice. (#21290) * Mon Nov 27 2000 Nalin Dahyabhai - Merge multiple PAM text messages into subsequent prompts when possible when doing keyboard-interactive authentication. * Sun Nov 26 2000 Nalin Dahyabhai - Disable the built-in MD5 password support. We're using PAM. - Take a crack at doing keyboard-interactive authentication with PAM, and enable use of it in the default client configuration so that the client will try it when the server disallows password authentication. - Build with debugging flags. Build root policies strip all binaries anyway. * Tue Nov 21 2000 Nalin Dahyabhai - Use DESTDIR instead of %%makeinstall. - Remove /usr/X11R6/bin from the path-fixing patch. * Mon Nov 20 2000 Nalin Dahyabhai - Add the primes file from the latest snapshot to the main package (#20884). - Add the dev package to the prereq list (#19984). - Remove the default path and mimic login's behavior in the server itself. * Fri Nov 17 2000 Nalin Dahyabhai - Resync with conditional options in Damien Miller's .spec file for an errata. - Change libexecdir from %%{_libexecdir}/ssh to %%{_libexecdir}/openssh. * Tue Nov 7 2000 Nalin Dahyabhai - Update to OpenSSH 2.3.0p1. - Update to x11-askpass 1.1.0. - Enable keyboard-interactive authentication. * Mon Oct 30 2000 Nalin Dahyabhai - Update to ssh-askpass-x11 1.0.3. - Change authentication related messages to be private (#19966). * Tue Oct 10 2000 Nalin Dahyabhai - Patch ssh-keygen to be able to list signatures for DSA public key files it generates. * Thu Oct 5 2000 Nalin Dahyabhai - Add BuildRequires on /usr/include/security/pam_appl.h to be sure we always build PAM authentication in. - Try setting SSH_ASKPASS if gnome-ssh-askpass is installed. - Clean out no-longer-used patches. - Patch ssh-add to try to add both identity and id_dsa, and to error only when neither exists. * Mon Oct 2 2000 Nalin Dahyabhai - Update x11-askpass to 1.0.2. (#17835) - Add BuildRequiress for /bin/login and /usr/bin/rsh so that configure will always find them in the right place. (#17909) - Set the default path to be the same as the one supplied by /bin/login, but add /usr/X11R6/bin. (#17909) - Try to handle obsoletion of ssh-server more cleanly. Package names are different, but init script name isn't. (#17865) * Wed Sep 6 2000 Nalin Dahyabhai - Update to 2.2.0p1. (#17835) - Tweak the init script to allow proper restarting. (#18023) * Wed Aug 23 2000 Nalin Dahyabhai - Update to 20000823 snapshot. - Change subpackage requirements from %%{version} to %%{version}-%%{release} - Back out the pipe patch. * Mon Jul 17 2000 Nalin Dahyabhai - Update to 2.1.1p4, which includes fixes for config file parsing problems. - Move the init script back. - Add Damien's quick fix for wackiness. * Wed Jul 12 2000 Nalin Dahyabhai - Update to 2.1.1p3, which includes fixes for X11 forwarding and strtok(). * Thu Jul 6 2000 Nalin Dahyabhai - Move condrestart to server postun. - Move key generation to init script. - Actually use the right patch for moving the key generation to the init script. - Clean up the init script a bit. * Wed Jul 5 2000 Nalin Dahyabhai - Fix X11 forwarding, from mail post by Chan Shih-Ping Richard. * Sun Jul 2 2000 Nalin Dahyabhai - Update to 2.1.1p2. - Use of strtok() considered harmful. * Sat Jul 1 2000 Nalin Dahyabhai - Get the build root out of the man pages. * Thu Jun 29 2000 Nalin Dahyabhai - Add and use condrestart support in the init script. - Add newer initscripts as a prereq. * Tue Jun 27 2000 Nalin Dahyabhai - Build in new environment (release 2) - Move -clients subpackage to Applications/Internet group * Fri Jun 9 2000 Nalin Dahyabhai - Update to 2.2.1p1 * Sat Jun 3 2000 Nalin Dahyabhai - Patch to build with neither RSA nor RSAref. - Miscellaneous FHS-compliance tweaks. - Fix for possibly-compressed man pages. * Wed Mar 15 2000 Damien Miller - Updated for new location - Updated for new gnome-ssh-askpass build * Sun Dec 26 1999 Damien Miller - Added Jim Knoble's askpass * Mon Nov 15 1999 Damien Miller - Split subpackages further based on patch from jim knoble * Sat Nov 13 1999 Damien Miller - Added 'Obsoletes' directives * Tue Nov 09 1999 Damien Miller - Use make install - Subpackages * Mon Nov 08 1999 Damien Miller - Added links for slogin - Fixed perms on manpages * Sat Oct 30 1999 Damien Miller - Renamed init script * Fri Oct 29 1999 Damien Miller - Back to old binary names * Thu Oct 28 1999 Damien Miller - Use autoconf - New binary names * Wed Oct 27 1999 Damien Miller - Initial RPMification, based on Jan "Yenya" Kasprzak's spec. openssh-10.0p1/contrib/redhat/PaxHeaders.10889/sshd.init100755 001750 001750 0000000003614775415623 0017714xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/redhat/sshd.init010075500017500001750000000032711477541562300163020ustar00djmdjm#!/bin/bash # # Init file for OpenSSH server daemon # # chkconfig: 2345 55 25 # description: OpenSSH server daemon # # processname: sshd # config: /etc/ssh/ssh_host_key # config: /etc/ssh/ssh_host_key.pub # config: /etc/ssh/ssh_random_seed # config: /etc/ssh/sshd_config # pidfile: /var/run/sshd.pid # source function library . /etc/rc.d/init.d/functions # pull in sysconfig settings [ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd RETVAL=0 prog="sshd" # Some functions to make the below more readable SSHD=/usr/sbin/sshd PID_FILE=/var/run/sshd.pid do_restart_sanity_check() { $SSHD -t RETVAL=$? if [ $RETVAL -ne 0 ]; then failure $"Configuration file or keys are invalid" echo fi } start() { # Create keys if necessary /usr/bin/ssh-keygen -A if [ -x /sbin/restorecon ]; then /sbin/restorecon /etc/ssh/ssh_host_rsa_key.pub /sbin/restorecon /etc/ssh/ssh_host_dsa_key.pub /sbin/restorecon /etc/ssh/ssh_host_ecdsa_key.pub fi echo -n $"Starting $prog:" $SSHD $OPTIONS && success || failure RETVAL=$? [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sshd echo } stop() { echo -n $"Stopping $prog:" killproc $SSHD -TERM RETVAL=$? [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sshd echo } reload() { echo -n $"Reloading $prog:" killproc $SSHD -HUP RETVAL=$? echo } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; reload) reload ;; condrestart) if [ -f /var/lock/subsys/sshd ] ; then do_restart_sanity_check if [ $RETVAL -eq 0 ] ; then stop # avoid race sleep 3 start fi fi ;; status) status $SSHD RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|restart|reload|condrestart|status}" RETVAL=1 esac exit $RETVAL openssh-10.0p1/contrib/redhat/PaxHeaders.10889/sshd.pam100644 001750 001750 0000000003614775415623 0017523xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/redhat/sshd.pam010064400017500001750000000004251477541562300161070ustar00djmdjm#%PAM-1.0 auth required pam_stack.so service=system-auth account required pam_nologin.so account required pam_stack.so service=system-auth password required pam_stack.so service=system-auth session required pam_stack.so service=system-auth openssh-10.0p1/contrib/PaxHeaders.10889/solaris040755 001750 001750 0000000003614775415623 0016221xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/solaris004075500017500001750000000000001477541562300145775ustar00djmdjmopenssh-10.0p1/contrib/solaris/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0017150xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/solaris/README010064400017500001750000000024471477541562300155420ustar00djmdjmThe following is a new package build script for Solaris. This is being introduced into OpenSSH 3.0 and above in hopes of simplifying the build process. As of 3.1p2 the script should work on all platforms that have 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 deferred until the first time the sshd is started. Directions: 1. make -F Makefile.in distprep (Only if you are getting from the CVS tree) 2. ./configure --with-pam [..any other options you want..] 3. look at the top of buildpkg.sh for the configurable options and put any changes you want in openssh-config.local. Additional customizations can be done to the build process by creating one or more of the following scripts that will be sourced by buildpkg.sh. pkg_post_make_install_fixes.sh pkg-post-prototype-edit.sh pkg-preinstall.local pkg-postinstall.local pkg-preremove.local pkg-postremove.local pkg-request.local 4. Run "make package" If all goes well you should have a solaris package ready to be installed. If you have any problems with this script please post them to openssh-unix-dev@mindrot.org and I will try to assist you as best as I can. - Ben Lindstrom openssh-10.0p1/contrib/PaxHeaders.10889/ssh-copy-id100644 001750 001750 0000000003614775415623 0016676xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/ssh-copy-id010064400017500001750000000335321477541562300152670ustar00djmdjm#!/bin/sh # Copyright (c) 1999-2024 Philip Hands # 2021 Carlos Rodríguez Gili # 2020 Matthias Blümel # 2017 Sebastien Boyron # 2013 Martin Kletzander # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= # 2010 Eric Moret # 2009 Xr # 2007 Justin Pryzby # 2004 Reini Urban # 2003 Colin Watson # 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. # Shell script to install your public key(s) on a remote machine # See the ssh-copy-id(1) man page for details # shellcheck shell=dash # check that we have something mildly sane as our shell, or try to find something better if false ^ printf "%s: WARNING: ancient shell, hunting for a more modern one... " "$0" then SANE_SH=${SANE_SH:-/usr/bin/ksh} if printf 'true ^ false\n' | "$SANE_SH" then printf "'%s' seems viable.\\n" "$SANE_SH" exec "$SANE_SH" "$0" "$@" else cat <<-EOF oh dear. If you have a more recent shell available, that supports \$(...) etc. please try setting the environment variable SANE_SH to the path of that shell, and then retry running this script. If that works, please report a bug describing your setup, and the shell you used to make it work. EOF printf '%s: ERROR: Less dimwitted shell required.\n' "$0" >&2 exit 1 fi fi # shellcheck disable=SC2010 DEFAULT_PUB_ID_FILE=$(ls -dt "${HOME}"/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1) SSH="ssh -a -x" TARGET_PATH=".ssh/authorized_keys" umask 0177 usage () { printf 'Usage: %s [-h|-?|-f|-n|-s|-x] [-i [identity_file]] [-t target_path] [-F ssh_config] [[-o ssh_option] ...] [-p port] [user@]hostname\n' "$0" >&2 printf '\t-f: force mode -- copy keys without trying to check if they are already installed\n' >&2 printf '\t-n: dry run -- no keys are actually copied\n' >&2 printf '\t-s: use sftp -- use sftp instead of executing remote-commands. Can be useful if the remote only allows sftp\n' >&2 printf '\t-x: debug -- enables -x in this shell, for debugging\n' >&2 printf '\t-h|-?: print this help\n' >&2 exit 1 } # escape any single quotes in an argument quote() { printf '%s\n' "$1" | sed -e "s/'/'\\\\''/g" } use_id_file() { L_ID_FILE="$1" if [ -z "$L_ID_FILE" ] ; then printf '%s: ERROR: no ID file found\n' "$0" >&2 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 [ "$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:+"$PRIV_ID_FILE"} ; do ErrMSG=$( { : < "$f" ; } 2>&1 ) || { 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/.*: *//')" >&2 exit 1 } done GET_ID="cat \"$PUB_ID_FILE\"" } if [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then GET_ID="ssh-add -L" fi OPTS="io:p:F:t:fnsxh?" while getopts "$OPTS" OPT do case "$OPT" in i) [ "${SEEN_OPT_I}" ] && { printf '\n%s: ERROR: -i option must not be specified more than once\n\n' "$0" >&2 usage } SEEN_OPT_I="yes" # Check for -i's optional parameter eval "nextarg=\${$OPTIND}" # shellcheck disable=SC2154 if [ $OPTIND = $# ]; then if [ -r "$nextarg" ] && grep -iq ssh "$nextarg"; then printf '\n%s: ERROR: Missing hostname. Use "-i -- %s" if you really mean to use this as the hostname\n\n' "$0" "$nextarg" >&2 usage fi elif ! expr -- "$nextarg" : "-[$(echo "$OPTS" | tr -d :)-]" >/dev/null ; then # when not at the last arg, and not followed by an option, -i has an argument OPTARG="$nextarg" OPTIND=$((OPTIND + 1)) fi use_id_file "${OPTARG:-$DEFAULT_PUB_ID_FILE}" ;; o|F) OPTS_oF="${OPTS_oF:+$OPTS_oF }-$OPT '$(quote "${OPTARG}")'" ;; f) FORCED=1 ;; n) DRY_RUN=1 ;; p) SSH_PORT=${OPTARG} ;; s) SFTP=sftp ;; t) TARGET_PATH="${OPTARG}" ;; x) SET_X="set -x;" set -x ;; h|\?) usage ;; esac done #shift all args to keep only USER_HOST shift $((OPTIND-1)) if [ $# = 0 ] ; then usage fi if [ $# != 1 ] ; then printf '%s: ERROR: Too many arguments. Expecting a target hostname, got: %s\n\n' "$0" "$SAVEARGS" >&2 usage fi USER_HOST="$*" # tack the hostname onto SSH_OPTS OPTS_USER_HOST="${OPTS_oF:+$OPTS_oF }'$(quote "$USER_HOST")'" SSH_OPTS="${SSH_PORT:+-p $SSH_PORT }$OPTS_USER_HOST" # and populate "$@" for later use (only way to get proper quoting of options) eval set -- "$SSH_OPTS" # shellcheck disable=SC2086 if [ -z "$(eval $GET_ID)" ] && [ -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ] ; then use_id_file "$PUB_ID_FILE" fi printf '%s: INFO: Source of key(s) to be installed: %s\n' "$0" "${GET_ID#cat }" >&2 # shellcheck disable=SC2086 if [ -z "$(eval $GET_ID)" ] ; then printf '%s: ERROR: No identities found\n' "$0" >&2 exit 1 fi # assert_scratch_ok() # ensures that $SCRATCH_DIR is setup. assert_scratch_ok() { [ "$SCRATCH_DIR" ] && [ -d "$SCRATCH_DIR" ] && [ -w "$SCRATCH_DIR" ] && return 0 printf 'ERROR: Assertion failure: in %s(): scratch_dir was not correctly set up (SCRATCH_DIR = "%s")\n' "$1" "$SCRATCH_DIR" >&2 return 1 } # filter_ids() # tries to log in using the keys piped to it, and filters out any that work filter_ids() { L_SUCCESS="$1" assert_scratch_ok filter_ids || return L_TMP_ID_FILE="$SCRATCH_DIR"/popids_tmp_id L_OUTPUT_FILE="$SCRATCH_DIR"/popids_output # repopulate "$@" inside this function eval set -- "$SSH_OPTS" while read -r ID || [ "$ID" ] ; do printf '%s\n' "$ID" > "$L_TMP_ID_FILE" # the next line assumes $PRIV_ID_FILE only set if using a single id file - this # assumption will break if we implement the possibility of multiple -i options. # The point being that if file based, ssh needs the private key, which it cannot # find if only given the contents of the .pub file in an unrelated tmpfile $SSH -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \ -o ControlPath=none \ -o LogLevel=INFO \ -o PreferredAuthentications=publickey \ -o IdentitiesOnly=yes "$@" exit >"$L_OUTPUT_FILE" 2>&1 /dev/null # this error counts as a success if we're setting up an sftp connection } then : > "$L_TMP_ID_FILE" else grep 'Permission denied' "$L_OUTPUT_FILE" >/dev/null || { sed -e 's/^/ERROR: /' <"$L_OUTPUT_FILE" >"$L_TMP_ID_FILE" cat >/dev/null #consume the other keys, causing loop to end } fi cat "$L_TMP_ID_FILE" done } # populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...) # and has the side effect of setting $NEW_IDS populate_new_ids() { if [ "$FORCED" ] ; then # shellcheck disable=SC2086 NEW_IDS=$(eval $GET_ID) return fi printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2 # shellcheck disable=SC2086 NEW_IDS=$(eval $GET_ID | filter_ids $1) if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2 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' "$0" >&2 printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2 exit 0 fi printf '%s: INFO: %d key(s) remain to be installed -- if you are prompted now it is to install the new keys\n' "$0" "$(printf '%s\n' "$NEW_IDS" | wc -l)" >&2 } # installkey_sh [target_path] # produce a one-liner to add the keys to remote $TARGET_PATH installkeys_sh() { # In setting INSTALLKEYS_SH: # the tr puts it all on one line (to placate tcsh) # (hence the excessive use of semi-colons (;) ) # then in the command: # cd to be at $HOME, just in case; # the -z `tail ...` checks for a trailing newline. The echo adds one if was missing # the cat adds the keys we're getting via STDIN # and if available restorecon is used to restore the SELinux context # OpenWrt has a special case for root only. INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF $SET_X cd; umask 077; AUTH_KEY_FILE="${TARGET_PATH}"; [ -f /etc/openwrt_release ] && [ "\$LOGNAME" = "root" ] && AUTH_KEY_FILE=/etc/dropbear/authorized_keys; AUTH_KEY_DIR=\`dirname "\${AUTH_KEY_FILE}"\`; mkdir -p "\${AUTH_KEY_DIR}" && { [ -z "\`tail -1c "\${AUTH_KEY_FILE}" 2>/dev/null\`" ] || echo >> "\${AUTH_KEY_FILE}" || exit 1; } && cat >> "\${AUTH_KEY_FILE}" || exit 1; if type restorecon >/dev/null 2>&1; then restorecon -F "\${AUTH_KEY_DIR}" "\${AUTH_KEY_FILE}"; fi EOF ) # to defend against quirky remote shells: use 'exec sh -c' to get POSIX; printf "exec sh -c '%s'" "${INSTALLKEYS_SH}" } #shellcheck disable=SC2120 # the 'eval set' confuses this installkeys_via_sftp() { AUTH_KEY_FILE=${TARGET_PATH} AUTH_KEY_DIR=$(dirname "${AUTH_KEY_FILE}") # repopulate "$@" inside this function eval set -- "$SSH_OPTS" assert_scratch_ok installkeys_via_sftp || return 1 L_KEYS="$SCRATCH_DIR"/authorized_keys L_SHARED_CON="$SCRATCH_DIR"/master-conn $SSH -f -N -M -S "$L_SHARED_CON" "$@" L_CLEANUP="$SSH -S '$L_SHARED_CON' -O exit 'ignored' >/dev/null 2>&1 ; $SCRATCH_CLEANUP" #shellcheck disable=SC2064 trap "$L_CLEANUP" EXIT TERM INT QUIT sftp -b - -o "ControlPath='$L_SHARED_CON'" "ignored" <<-EOF || return 1 -get "$AUTH_KEY_FILE" "$L_KEYS" EOF # add a newline or create file if it's missing, same like above [ -z "$(tail -1c "$L_KEYS" 2>/dev/null)" ] || echo >> "$L_KEYS" # append the keys being piped in here cat >> "$L_KEYS" sftp -b - -o "ControlPath='$L_SHARED_CON'" "ignored" <<-EOF || return 1 -mkdir "$AUTH_KEY_DIR" chmod 700 "$AUTH_KEY_DIR" put "$L_KEYS" "$AUTH_KEY_FILE" chmod 600 "$AUTH_KEY_FILE" EOF #shellcheck disable=SC2064 eval "$L_CLEANUP" && trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT } # create a scratch dir for any temporary files needed if SCRATCH_DIR=$(mktemp -d ~/.ssh/ssh-copy-id.XXXXXXXXXX) && [ "$SCRATCH_DIR" ] && [ -d "$SCRATCH_DIR" ] then chmod 0700 "$SCRATCH_DIR" SCRATCH_CLEANUP="rm -rf \"$SCRATCH_DIR\"" #shellcheck disable=SC2064 trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT else printf '%s: ERROR: failed to create required temporary directory under ~/.ssh (HOME="%s")\n' "$0" "$HOME" >&2 exit 1 fi REMOTE_VERSION=$($SSH -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 | sed -ne 's/.*remote software version //p') # shellcheck disable=SC2029 case "$REMOTE_VERSION" in NetScreen*) populate_new_ids 1 for KEY in $(printf "%s" "$NEW_IDS" | cut -d' ' -f2) ; do KEY_NO=$((KEY_NO + 1)) printf '%s\n' "$KEY" | grep ssh-dss >/dev/null || { printf '%s: WARNING: Non-dsa key (#%d) skipped (NetScreen only supports DSA keys)\n' "$0" "$KEY_NO" >&2 continue } [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | $SSH -T "$@" >/dev/null 2>&1 if [ $? = 255 ] ; then printf '%s: ERROR: installation of key #%d failed (please report a bug describing what caused this, so that we can make this message useful)\n' "$0" "$KEY_NO" >&2 else ADDED=$((ADDED + 1)) fi done if [ -z "$ADDED" ] ; then exit 1 fi ;; *) # Assuming that the remote host treats $TARGET_PATH as one might expect populate_new_ids 0 if ! [ "$DRY_RUN" ] ; then printf '%s\n' "$NEW_IDS" | \ if [ "$SFTP" ] ; then #shellcheck disable=SC2119 installkeys_via_sftp else $SSH "$@" "$(installkeys_sh)" fi || exit 1 fi ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) ;; esac if [ "$DRY_RUN" ] ; then cat <<-EOF =-=-=-=-=-=-=-= Would have added the following key(s): $NEW_IDS =-=-=-=-=-=-=-= EOF else [ -z "$SFTP" ] || PORT_OPT=P cat <<-EOF Number of key(s) added: $ADDED Now try logging into the machine, with: "${SFTP:-ssh} ${SEEN_OPT_I:+-i${PRIV_ID_FILE:+ $PRIV_ID_FILE} }${SSH_PORT:+-${PORT_OPT:-p} $SSH_PORT }${OPTS_USER_HOST}" and check to make sure that only the key(s) you wanted were added. EOF fi # =-=-=-= openssh-10.0p1/contrib/PaxHeaders.10889/ssh-copy-id.1100644 001750 001750 0000000003614775415623 0017035xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/ssh-copy-id.1010064400017500001750000000161701477541562300154250ustar00djmdjm.ig \" -*- nroff -*- Copyright (c) 1999-2024 Philip Hands Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. .Dd $Mdocdate: June 17 2010 $ .Dt SSH-COPY-ID 1 .Os .Sh NAME .Nm ssh-copy-id .Nd use locally available keys to authorise logins on a remote machine .Sh SYNOPSIS .Nm .Op Fl f .Op Fl n .Op Fl s .Op Fl x .Op Fl i Op Ar identity_file .Op Fl t Ar target_path .Op Fl F Ar ssh_config .Op Bo Fl o Ar ssh_option Bc ... .Op Fl p Ar port .Op Ar user Ns @ Ns .Ar hostname .Nm .Fl h | Fl ? .br .Sh DESCRIPTION .Nm is a script that uses .Xr ssh 1 to log into a remote machine (presumably using a login password, so password authentication should be enabled, unless you've done some clever use of multiple identities). It assembles a list of one or more fingerprints (as described below) and tries to log in with each key, to see if any of them are already installed (of course, if you are not using .Xr ssh-agent 1 this may result in you being repeatedly prompted for pass-phrases). It then assembles a list of those that failed to log in and, using .Xr ssh 1 , enables logins with those keys on the remote server. By default it adds the keys by appending them to the remote user's .Pa ~/.ssh/authorized_keys (creating the file, and directory, if necessary). It is also capable of detecting if the remote system is a NetScreen, and using its .Ql set ssh pka-dsa key ... command instead. .Pp The options are as follows: .Bl -tag -width Ds .It Fl i Op Ar identity_file Use only the key(s) contained in .Ar identity_file (rather than looking for identities via .Xr ssh-add 1 or in the .Ic default_ID_file ) . If the filename does not end in .Pa .pub this is added. If the filename is omitted, the .Ic default_ID_file is used. .Pp 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. .It Fl s SFTP mode: usually the public keys are installed by executing commands on the remote side. With this option the user's .Pa ~/.ssh/authorized_keys file will be downloaded, modified locally and uploaded with sftp. This option is useful if the server has restrictions on commands which can be used on the remote side. .It Fl t Ar target_path the path on the target system where the keys should be added (defaults to ".ssh/authorized_keys") .It Fl p Ar port Specifies the port to connect to on the remote host. .It Fl F Ar ssh_config , Fl o Ar ssh_option These options are simply passed through untouched (with their argument) to ssh/sftp, allowing one to set an alternative config file, or other options, respectively. .Pp Rather than specifying these as command line options, it is often better to use (per-host) settings in .Xr ssh 1 Ns 's configuration file: .Xr ssh_config 5 . .It Fl x This option is for debugging the .Nm script itself. It sets the shell's -x flag, so that you can see the commands being run. .It Fl h , Fl ? Print Usage summary .El .Pp Default behaviour without .Fl i , is to check if .Ql ssh-add -L provides any output, and if so those keys are used. Note that this results in the comment on the key being the filename that was given to .Xr ssh-add 1 when the key was loaded into your .Xr ssh-agent 1 rather than the comment contained in that file, which is a bit of a shame. Otherwise, if .Xr ssh-add 1 provides no keys contents of the .Ic default_ID_file will be used. .Pp The .Ic default_ID_file is the most recent file that matches: .Pa ~/.ssh/id*.pub , (excluding those that match .Pa ~/.ssh/*-cert.pub ) so if you create a key that is not the one you want .Nm to use, just use .Xr touch 1 on your preferred key's .Pa .pub file to reinstate it as the most recent. .Sh EXAMPLES If you have already installed keys from one system on a lot of remote hosts, and you then create a new key, on a new client machine, say, it can be difficult to keep track of which systems on which you've installed the new key. One way of dealing with this is to load both the new key and old key(s) into your .Xr ssh-agent 1 . Load the new key first, without the .Fl c option, then load one or more old keys into the agent, possibly by ssh-ing to the client machine that has that old key, using the .Fl A option to allow agent forwarding: .Pp .D1 user@newclient$ ssh-add .D1 user@newclient$ ssh -A old.client .D1 user@oldl$ ssh-add -c .D1 No ... prompt for pass-phrase ... .D1 user@old$ logoff .D1 user@newclient$ ssh someserver .Pp now, if the new key is installed on the server, you'll be allowed in unprompted, whereas if you only have the old key(s) enabled, you'll be asked for confirmation, which is your cue to log back out and run .Pp .D1 user@newclient$ ssh-copy-id -i someserver .Pp The reason you might want to specify the .Fl 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 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 . Of course, you can specify another id, or use the contents of the .Xr ssh-agent 1 as you prefer. .Pp Having mentioned .Xr ssh-add 1 Ns 's .Fl c option, you might consider using this whenever using agent forwarding to avoid your key being hijacked, but it is much better to instead use .Xr ssh 1 Ns 's .Ar ProxyCommand and .Fl W option, to bounce through remote servers while always doing direct end-to-end authentication. This way the middle hop(s) don't get access to your .Xr ssh-agent 1 . A web search for .Ql ssh proxycommand nc should prove enlightening (NB the modern approach is to use the .Fl W option, rather than .Xr nc 1 ) . .Sh "SEE ALSO" .Xr ssh 1 , .Xr ssh-agent 1 , .Xr sshd 8 openssh-10.0p1/contrib/PaxHeaders.10889/sshd.pam.freebsd100644 001750 001750 0000000003614775415623 0017665xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/sshd.pam.freebsd010064400017500001750000000002671477541562300162550ustar00djmdjmsshd auth required pam_unix.so try_first_pass sshd account required pam_unix.so sshd password required pam_permit.so sshd session required pam_permit.so openssh-10.0p1/contrib/PaxHeaders.10889/sshd.pam.generic100644 001750 001750 0000000003614775415623 0017667xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/sshd.pam.generic010064400017500001750000000006321477541562300162530ustar00djmdjm#%PAM-1.0 auth required /lib/security/pam_unix.so shadow nodelay account required /lib/security/pam_nologin.so account required /lib/security/pam_unix.so password required /lib/security/pam_cracklib.so password required /lib/security/pam_unix.so shadow nullok use_authtok session required /lib/security/pam_unix.so session required /lib/security/pam_limits.so openssh-10.0p1/contrib/PaxHeaders.10889/suse040755 001750 001750 0000000003614775415623 0015524xustar0030 atime=1744182234.562328967 openssh-10.0p1/contrib/suse004075500017500001750000000000001477541562300141025ustar00djmdjmopenssh-10.0p1/contrib/suse/PaxHeaders.10889/openssh.spec100644 001750 001750 0000000003614775415623 0020126xustar0030 atime=1744182234.563305524 openssh-10.0p1/contrib/suse/openssh.spec010064400017500001750000000214301477541562300165110ustar00djmdjm# Default values for additional components %define build_x11_askpass 1 # Define the UID/GID to use for privilege separation %define sshd_gid 65 %define sshd_uid 71 # The version of x11-ssh-askpass to use %define xversion 1.2.4.1 # Allow the ability to override defaults with -D skip_xxx=1 %{?skip_x11_askpass:%define build_x11_askpass 0} Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh Version: 10.0p1 URL: https://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz Source1: x11-ssh-askpass-%{xversion}.tar.gz License: BSD Group: Productivity/Networking/SSH BuildRoot: %{_tmppath}/openssh-%{version}-buildroot PreReq: openssl Obsoletes: ssh Provides: ssh # # (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.) # building prerequisites -- stuff for # OpenSSL (openssl-devel), # and Gnome (glibdev, gtkdev, and gnlibsd) # BuildPrereq: openssl BuildPrereq: zlib-devel #BuildPrereq: glibdev #BuildPrereq: gtkdev #BuildPrereq: gnlibsd %package askpass Summary: A passphrase dialog for OpenSSH and the X window System. Group: Productivity/Networking/SSH Requires: openssh = %{version} Obsoletes: ssh-extras Provides: openssh:${_libdir}/ssh/ssh-askpass %if %{build_x11_askpass} BuildPrereq: XFree86-devel %endif %description Ssh (Secure Shell) is a program for logging into a remote machine and for executing commands in a remote machine. It is intended to replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections and arbitrary TCP/IP ports can also be forwarded over the secure channel. OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it up to date in terms of security and features, as well as removing all patented algorithms to separate libraries (OpenSSL). This package includes all files necessary for both the OpenSSH client and server. %description askpass Ssh (Secure Shell) is a program for logging into a remote machine and for executing commands in a remote machine. It is intended to replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections and arbitrary TCP/IP ports can also be forwarded over the secure channel. OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it up to date in terms of security and features, as well as removing all patented algorithms to separate libraries (OpenSSL). This package contains an X Window System passphrase dialog for OpenSSH. %changelog * Mon Jul 20 2020 Damien Miller - Add ssh-sk-helper and corresponding manual page. * Wed Oct 26 2005 Iain Morgan - Removed accidental inclusion of --without-zlib-version-check * Tue Oct 25 2005 Iain Morgan - Overhaul to deal with newer versions of SuSE and OpenSSH * Mon Jun 12 2000 Damien Miller - Glob manpages to catch compressed files * Wed Mar 15 2000 Damien Miller - Updated for new location - Updated for new gnome-ssh-askpass build * Sun Dec 26 1999 Chris Saia - Made symlink to gnome-ssh-askpass called ssh-askpass * Wed Nov 24 1999 Chris Saia - Removed patches that included /etc/pam.d/sshd, /sbin/init.d/rc.sshd, and /var/adm/fillup-templates/rc.config.sshd, since Damien merged these into his released tarfile - Changed permissions on ssh_config in the install procedure to 644 from 600 even though it was correct in the %files section and thus right in the RPMs - Postinstall script for the server now only prints "Generating SSH host key..." if we need to actually do this, in order to eliminate a confusing message if an SSH host key is already in place - Marked all manual pages as %doc(umentation) * Mon Nov 22 1999 Chris Saia - Added flag to configure daemon with TCP Wrappers support - Added building prerequisites (works in RPM 3.0 and newer) * Thu Nov 18 1999 Chris Saia - Made this package correct for SuSE. - Changed instances of pam_pwdb.so to pam_unix.so, since it works more properly with SuSE, and lib_pwdb.so isn't installed by default. * Mon Nov 15 1999 Damien Miller - Split subpackages further based on patch from jim knoble * Sat Nov 13 1999 Damien Miller - Added 'Obsoletes' directives * Tue Nov 09 1999 Damien Miller - Use make install - Subpackages * Mon Nov 08 1999 Damien Miller - Added links for slogin - Fixed perms on manpages * Sat Oct 30 1999 Damien Miller - Renamed init script * Fri Oct 29 1999 Damien Miller - Back to old binary names * Thu Oct 28 1999 Damien Miller - Use autoconf - New binary names * Wed Oct 27 1999 Damien Miller - Initial RPMification, based on Jan "Yenya" Kasprzak's spec. %prep %if %{build_x11_askpass} %setup -q -a 1 %else %setup -q %endif %build CFLAGS="$RPM_OPT_FLAGS" \ %configure --prefix=/usr \ --sysconfdir=%{_sysconfdir}/ssh \ --mandir=%{_mandir} \ --with-privsep-path=/var/lib/empty \ --with-pam \ --libexecdir=%{_libdir}/ssh make %if %{build_x11_askpass} cd x11-ssh-askpass-%{xversion} %configure --mandir=/usr/X11R6/man \ --libexecdir=%{_libdir}/ssh xmkmf -a make cd .. %endif %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT/ install -d $RPM_BUILD_ROOT/etc/pam.d/ install -d $RPM_BUILD_ROOT/etc/init.d/ install -d $RPM_BUILD_ROOT/var/adm/fillup-templates install -m644 contrib/sshd.pam.generic $RPM_BUILD_ROOT/etc/pam.d/sshd install -m744 contrib/suse/rc.sshd $RPM_BUILD_ROOT/etc/init.d/sshd install -m744 contrib/suse/sysconfig.ssh \ $RPM_BUILD_ROOT/var/adm/fillup-templates %if %{build_x11_askpass} cd x11-ssh-askpass-%{xversion} make install install.man BINDIR=%{_libdir}/ssh DESTDIR=$RPM_BUILD_ROOT/ rm -f $RPM_BUILD_ROOT/usr/share/Ssh.bin %endif %clean rm -rf $RPM_BUILD_ROOT %pre /usr/sbin/groupadd -g %{sshd_gid} -o -r sshd 2> /dev/null || : /usr/sbin/useradd -r -o -g sshd -u %{sshd_uid} -s /bin/false -c "SSH Privilege Separation User" -d /var/lib/sshd sshd 2> /dev/null || : %post /usr/bin/ssh-keygen -A %{fillup_and_insserv -n -y ssh sshd} %run_permissions %verifyscript %verify_permissions -e /etc/ssh/sshd_config -e /etc/ssh/ssh_config -e /usr/bin/ssh %preun %stop_on_removal sshd %postun %restart_on_update sshd %{insserv_cleanup} %files %defattr(-,root,root) %doc ChangeLog OVERVIEW README* PROTOCOL* %doc TODO CREDITS LICENCE %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli %attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0755,root,root) %config /etc/init.d/sshd %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0755,root,root) %{_bindir}/scp %attr(0755,root,root) %{_bindir}/ssh %attr(0755,root,root) %{_bindir}/ssh-agent %attr(0755,root,root) %{_bindir}/ssh-add %attr(0755,root,root) %{_bindir}/ssh-keyscan %attr(0755,root,root) %{_bindir}/sftp %attr(0755,root,root) %{_sbindir}/sshd %attr(0755,root,root) %dir %{_libdir}/ssh %attr(0755,root,root) %{_libdir}/ssh/sftp-server %attr(0755,root,root) %{_libdir}/ssh/sshd-session %attr(4711,root,root) %{_libdir}/ssh/ssh-keysign %attr(0755,root,root) %{_libdir}/ssh/ssh-pkcs11-helper %attr(0755,root,root) %{_libdir}/ssh/ssh-sk-helper %attr(0644,root,root) %doc %{_mandir}/man1/scp.1* %attr(0644,root,root) %doc %{_mandir}/man1/sftp.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-add.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-agent.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-keygen.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-keyscan.1* %attr(0644,root,root) %doc %{_mandir}/man5/moduli.5* %attr(0644,root,root) %doc %{_mandir}/man5/ssh_config.5* %attr(0644,root,root) %doc %{_mandir}/man5/sshd_config.5* %attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-keysign.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-pkcs11-helper.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-sk-helper.8* %attr(0644,root,root) %doc %{_mandir}/man8/sshd.8* %attr(0644,root,root) /var/adm/fillup-templates/sysconfig.ssh %if %{build_x11_askpass} %files askpass %defattr(-,root,root) %doc x11-ssh-askpass-%{xversion}/README %doc x11-ssh-askpass-%{xversion}/ChangeLog %doc x11-ssh-askpass-%{xversion}/SshAskpass*.ad %attr(0755,root,root) %{_libdir}/ssh/ssh-askpass %attr(0755,root,root) %{_libdir}/ssh/x11-ssh-askpass %attr(0644,root,root) %doc /usr/X11R6/man/man1/ssh-askpass.1x* %attr(0644,root,root) %doc /usr/X11R6/man/man1/x11-ssh-askpass.1x* %attr(0644,root,root) %config /usr/X11R6/lib/X11/app-defaults/SshAskpass %endif openssh-10.0p1/contrib/suse/PaxHeaders.10889/rc.config.sshd100644 001750 001750 0000000003614775415623 0020326xustar0030 atime=1744182234.563305524 openssh-10.0p1/contrib/suse/rc.config.sshd010064400017500001750000000000751477541562300167130ustar00djmdjm# # Start the Secure Shell (SSH) Daemon? # START_SSHD="yes" openssh-10.0p1/contrib/suse/PaxHeaders.10889/rc.sshd100644 001750 001750 0000000003614775415623 0017062xustar0030 atime=1744182234.563305524 openssh-10.0p1/contrib/suse/rc.sshd010064400017500001750000000061421477541562300154500ustar00djmdjm#! /bin/sh # Copyright (c) 1995-2000 SuSE GmbH Nuernberg, Germany. # # Author: Jiri Smid # # /etc/init.d/sshd # # and symbolic its link # # /usr/sbin/rcsshd # ### BEGIN INIT INFO # Provides: sshd # Required-Start: $network $remote_fs # Required-Stop: $network $remote_fs # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Description: Start the sshd daemon ### END INIT INFO SSHD_BIN=/usr/sbin/sshd test -x $SSHD_BIN || exit 5 SSHD_SYSCONFIG=/etc/sysconfig/ssh test -r $SSHD_SYSCONFIG || exit 6 . $SSHD_SYSCONFIG SSHD_PIDFILE=/var/run/sshd.init.pid . /etc/rc.status # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v ditto but be verbose in local rc status # rc_status -v -r ditto and clear the local rc status # rc_failed set local and overall rc status to failed # rc_reset clear local rc status (overall remains) # rc_exit exit appropriate to overall rc status # First reset status of this service rc_reset case "$1" in start) # Generate any missing host keys ssh-keygen -A echo -n "Starting SSH daemon" ## Start daemon with startproc(8). If this fails ## the echo return value is set appropriate. startproc -f -p $SSHD_PIDFILE $SSHD_BIN $SSHD_OPTS -o "PidFile=$SSHD_PIDFILE" # Remember status and be verbose rc_status -v ;; stop) echo -n "Shutting down SSH daemon" ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. killproc -p $SSHD_PIDFILE -TERM $SSHD_BIN # Remember status and be verbose rc_status -v ;; try-restart) ## Stop the service and if this succeeds (i.e. the ## service was running before), start it again. $0 status >/dev/null && $0 restart # Remember status and be quiet rc_status ;; restart) ## Stop the service and regardless of whether it was ## running or not, start it again. $0 stop $0 start # Remember status and be quiet rc_status ;; force-reload|reload) ## Signal the daemon to reload its config. Most daemons ## do this on signal 1 (SIGHUP). echo -n "Reload service sshd" killproc -p $SSHD_PIDFILE -HUP $SSHD_BIN rc_status -v ;; status) echo -n "Checking for service sshd " ## Check status with checkproc(8), if process is running ## checkproc will return with exit status 0. # Status has a slightly different for the status command: # 0 - service running # 1 - service dead, but /var/run/ pid file exists # 2 - service dead, but /var/lock/ lock file exists # 3 - service not running checkproc -p $SSHD_PIDFILE $SSHD_BIN rc_status -v ;; probe) ## Optional: Probe for the necessity of a reload, ## give out the argument which is required for a reload. test /etc/ssh/sshd_config -nt $SSHD_PIDFILE && echo reload ;; *) echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}" exit 1 ;; esac rc_exit openssh-10.0p1/contrib/suse/PaxHeaders.10889/sysconfig.ssh100644 001750 001750 0000000003614775415623 0020316xustar0030 atime=1744182234.563305524 openssh-10.0p1/contrib/suse/sysconfig.ssh010064400017500001750000000002421477541562300166770ustar00djmdjm## Path: Network/Remote access/SSH ## Description: SSH server settings ## Type: string ## Default: "" ## ServiceRestart: sshd # # Options for sshd # SSHD_OPTS="" openssh-10.0p1/PaxHeaders.10889/crypto_api.h100644 001750 001750 0000000003614775415623 0015476xustar0030 atime=1744182234.563305524 openssh-10.0p1/crypto_api.h010064400017500001750000000036201477541562300140620ustar00djmdjm/* $OpenBSD: crypto_api.h,v 1.9 2024/09/02 12:13:56 djm Exp $ */ /* * Assembled from generated headers and source files by Markus Friedl. * Placed in the public domain. */ #ifndef crypto_api_h #define crypto_api_h #include "includes.h" #ifdef HAVE_STDINT_H # include #endif #include 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; typedef int64_t crypto_int64; typedef uint64_t crypto_uint64; #define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len)) #define small_random32() arc4random() #define crypto_hash_sha512_BYTES 64U int crypto_hash_sha512(unsigned char *, const unsigned char *, unsigned long long); #define crypto_sign_ed25519_SECRETKEYBYTES 64U #define crypto_sign_ed25519_PUBLICKEYBYTES 32U #define crypto_sign_ed25519_BYTES 64U int crypto_sign_ed25519(unsigned char *, unsigned long long *, const unsigned char *, unsigned long long, const unsigned char *); 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_sntrup761_PUBLICKEYBYTES 1158 #define crypto_kem_sntrup761_SECRETKEYBYTES 1763 #define crypto_kem_sntrup761_CIPHERTEXTBYTES 1039 #define crypto_kem_sntrup761_BYTES 32 int crypto_kem_sntrup761_enc(unsigned char *cstr, unsigned char *k, const unsigned char *pk); int crypto_kem_sntrup761_dec(unsigned char *k, const unsigned char *cstr, const unsigned char *sk); int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk); #define crypto_kem_mlkem768_PUBLICKEYBYTES 1184 #define crypto_kem_mlkem768_SECRETKEYBYTES 2400 #define crypto_kem_mlkem768_CIPHERTEXTBYTES 1088 #define crypto_kem_mlkem768_BYTES 32 #endif /* crypto_api_h */ openssh-10.0p1/PaxHeaders.10889/defines.h100644 001750 001750 0000000003614775415623 0014742xustar0030 atime=1744182234.564281741 openssh-10.0p1/defines.h010064400017500001750000000625031477541562300133330ustar00djmdjm/* * Copyright (c) 1999-2003 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. */ #ifndef _DEFINES_H #define _DEFINES_H /* Constants */ #if defined(HAVE_DECL_SHUT_RD) && HAVE_DECL_SHUT_RD == 0 enum { SHUT_RD = 0, /* No more receptions. */ SHUT_WR, /* No more transmissions. */ SHUT_RDWR /* No more receptions or transmissions. */ }; # define SHUT_RD SHUT_RD # define SHUT_WR SHUT_WR # define SHUT_RDWR SHUT_RDWR #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 #include #ifndef IPTOS_LOWDELAY # define IPTOS_LOWDELAY 0x10 # define IPTOS_THROUGHPUT 0x08 # define IPTOS_RELIABILITY 0x04 # define IPTOS_LOWCOST 0x02 # define IPTOS_MINCOST IPTOS_LOWCOST #endif /* IPTOS_LOWDELAY */ /* * Definitions for DiffServ Codepoints as per RFCs 2474, 3246, 4594 & 8622. * These are the 6 most significant bits as they appear on the wire, so the * two least significant bits must be zero. */ #ifndef IPTOS_DSCP_AF11 # define IPTOS_DSCP_AF11 0x28 # define IPTOS_DSCP_AF12 0x30 # define IPTOS_DSCP_AF13 0x38 # define IPTOS_DSCP_AF21 0x48 # define IPTOS_DSCP_AF22 0x50 # define IPTOS_DSCP_AF23 0x58 # define IPTOS_DSCP_AF31 0x68 # define IPTOS_DSCP_AF32 0x70 # define IPTOS_DSCP_AF33 0x78 # define IPTOS_DSCP_AF41 0x88 # define IPTOS_DSCP_AF42 0x90 # define IPTOS_DSCP_AF43 0x98 # define IPTOS_DSCP_EF 0xb8 #endif /* IPTOS_DSCP_AF11 */ #ifndef IPTOS_DSCP_CS0 # define IPTOS_DSCP_CS0 0x00 # define IPTOS_DSCP_CS1 0x20 # define IPTOS_DSCP_CS2 0x40 # define IPTOS_DSCP_CS3 0x60 # define IPTOS_DSCP_CS4 0x80 # define IPTOS_DSCP_CS5 0xa0 # define IPTOS_DSCP_CS6 0xc0 # define IPTOS_DSCP_CS7 0xe0 #endif /* IPTOS_DSCP_CS0 */ #ifndef IPTOS_DSCP_EF # define IPTOS_DSCP_EF 0xb8 #endif /* IPTOS_DSCP_EF */ #ifndef IPTOS_DSCP_LE # define IPTOS_DSCP_LE 0x04 #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 # define PATH_MAX _POSIX_PATH_MAX # endif #endif #ifndef MAXPATHLEN # ifdef PATH_MAX # define MAXPATHLEN PATH_MAX # else /* PATH_MAX */ # define MAXPATHLEN 64 # endif /* PATH_MAX */ #endif /* MAXPATHLEN */ #ifndef HOST_NAME_MAX # include "netdb.h" /* for MAXHOSTNAMELEN */ # if defined(_POSIX_HOST_NAME_MAX) # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX # elif defined(MAXHOSTNAMELEN) # define HOST_NAME_MAX MAXHOSTNAMELEN # else # define HOST_NAME_MAX 255 # endif #endif /* HOST_NAME_MAX */ #if defined(HAVE_DECL_MAXSYMLINKS) && HAVE_DECL_MAXSYMLINKS == 0 # define MAXSYMLINKS 5 #endif #ifndef STDIN_FILENO # define STDIN_FILENO 0 #endif #ifndef STDOUT_FILENO # define STDOUT_FILENO 1 #endif #ifndef STDERR_FILENO # define STDERR_FILENO 2 #endif #ifndef NGROUPS_MAX /* Disable groupaccess if NGROUP_MAX is not set */ #ifdef NGROUPS #define NGROUPS_MAX NGROUPS #else #define NGROUPS_MAX 0 #endif #endif #if defined(HAVE_DECL_O_NONBLOCK) && HAVE_DECL_O_NONBLOCK == 0 # define O_NONBLOCK 00004 /* Non Blocking Open */ #endif #ifndef S_IFSOCK # define S_IFSOCK 0 #endif /* S_IFSOCK */ #ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & (_S_IFMT)) == (_S_IFDIR)) #endif /* S_ISDIR */ #ifndef S_ISREG # define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG)) #endif /* S_ISREG */ #ifndef S_ISLNK # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) #endif /* S_ISLNK */ #ifndef S_IXUSR # define S_IXUSR 0000100 /* execute/search permission, */ # define S_IXGRP 0000010 /* execute/search permission, */ # define S_IXOTH 0000001 /* execute/search permission, */ # define _S_IWUSR 0000200 /* write permission, */ # define S_IWUSR _S_IWUSR /* write permission, owner */ # define S_IWGRP 0000020 /* write permission, group */ # define S_IWOTH 0000002 /* write permission, other */ # define S_IRUSR 0000400 /* read permission, owner */ # define S_IRGRP 0000040 /* read permission, group */ # define S_IROTH 0000004 /* read permission, other */ # define S_IRWXU 0000700 /* read, write, execute */ # define S_IRWXG 0000070 /* read, write, execute */ # define S_IRWXO 0000007 /* read, write, execute */ #endif /* S_IXUSR */ #if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) #define MAP_ANON MAP_ANONYMOUS #endif #ifndef MAP_FAILED # define MAP_FAILED ((void *)-1) #endif /* SCO Open Server 3 has INADDR_LOOPBACK defined in rpc/rpc.h but including rpc/rpc.h breaks Solaris 6 */ #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK ((u_long)0x7f000001) #endif /* Types */ /* If sys/types.h does not supply intXX_t, supply them ourselves */ /* (or die trying) */ #ifndef HAVE_U_INT typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; #endif #ifndef HAVE_INTXX_T typedef signed char int8_t; # if (SIZEOF_SHORT_INT == 2) typedef short int int16_t; # else # error "16 bit int type not found." # endif # if (SIZEOF_INT == 4) typedef int int32_t; # else # error "32 bit int type not found." # endif #endif /* If sys/types.h does not supply u_intXX_t, supply them ourselves */ #ifndef HAVE_U_INTXX_T # ifdef HAVE_UINTXX_T typedef uint8_t u_int8_t; typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; # define HAVE_U_INTXX_T 1 # else typedef unsigned char u_int8_t; # if (SIZEOF_SHORT_INT == 2) typedef unsigned short int u_int16_t; # else # error "16 bit int type not found." # endif # if (SIZEOF_INT == 4) typedef unsigned int u_int32_t; # else # error "32 bit int type not found." # 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) typedef long int int64_t; # else # if (SIZEOF_LONG_LONG_INT == 8) typedef long long int int64_t; # endif # endif #endif #ifndef HAVE_U_INT64_T # if (SIZEOF_LONG_INT == 8) typedef unsigned long int u_int64_t; # else # if (SIZEOF_LONG_LONG_INT == 8) typedef unsigned long long int u_int64_t; # endif # endif #endif #ifndef HAVE_UINTXX_T typedef u_int8_t uint8_t; typedef u_int16_t uint16_t; typedef u_int32_t uint32_t; typedef u_int64_t uint64_t; #endif #ifndef HAVE_INTMAX_T typedef long long intmax_t; #endif #ifndef HAVE_UINTMAX_T typedef unsigned long long uintmax_t; #endif #if SIZEOF_TIME_T == SIZEOF_LONG_LONG_INT # define SSH_TIME_T_MAX LLONG_MAX #else # define SSH_TIME_T_MAX INT_MAX #endif #ifndef HAVE_U_CHAR typedef unsigned char u_char; # define HAVE_U_CHAR #endif /* HAVE_U_CHAR */ #ifndef ULLONG_MAX # define ULLONG_MAX ((unsigned long long)-1) #endif #ifndef SIZE_T_MAX #define SIZE_T_MAX ULONG_MAX #endif /* SIZE_T_MAX */ #ifndef HAVE_SIZE_T typedef unsigned int size_t; # define HAVE_SIZE_T # define SIZE_T_MAX UINT_MAX #endif /* HAVE_SIZE_T */ #ifndef SIZE_MAX #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 */ #ifndef HAVE_CLOCK_T typedef long clock_t; # define HAVE_CLOCK_T #endif /* HAVE_CLOCK_T */ #ifndef HAVE_SA_FAMILY_T typedef int sa_family_t; # define HAVE_SA_FAMILY_T #endif /* HAVE_SA_FAMILY_T */ #ifndef HAVE_PID_T typedef int pid_t; # define HAVE_PID_T #endif /* HAVE_PID_T */ #ifndef HAVE_SIG_ATOMIC_T typedef int sig_atomic_t; # define HAVE_SIG_ATOMIC_T #endif /* HAVE_SIG_ATOMIC_T */ #ifndef HAVE_MODE_T typedef int mode_t; # define HAVE_MODE_T #endif /* HAVE_MODE_T */ #if !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE___SS_FAMILY_IN_SS) # define ss_family __ss_family #endif /* !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE_SA_FAMILY_IN_SS) */ #ifndef HAVE_SYS_UN_H struct sockaddr_un { short sun_family; /* AF_UNIX */ char sun_path[108]; /* path name (gag) */ }; #endif /* HAVE_SYS_UN_H */ #ifndef HAVE_IN_ADDR_T typedef u_int32_t in_addr_t; #endif #ifndef HAVE_IN_PORT_T typedef u_int16_t in_port_t; #endif #if defined(BROKEN_SYS_TERMIO_H) && !defined(_STRUCT_WINSIZE) #define _STRUCT_WINSIZE struct winsize { unsigned short ws_row; /* rows, in characters */ unsigned short ws_col; /* columns, in character */ unsigned short ws_xpixel; /* horizontal size, pixels */ unsigned short ws_ypixel; /* vertical size, pixels */ }; #endif /* bits needed for select that may not be in the system headers */ #ifndef HAVE_FD_MASK typedef unsigned long int fd_mask; #endif #if defined(HAVE_DECL_NFDBITS) && HAVE_DECL_NFDBITS == 0 # define NFDBITS (8 * sizeof(unsigned long)) #endif #if defined(HAVE_DECL_HOWMANY) && HAVE_DECL_HOWMANY == 0 # define howmany(x,y) (((x)+((y)-1))/(y)) #endif /* Paths */ #ifndef _PATH_BSHELL # define _PATH_BSHELL "/bin/sh" #endif #ifdef USER_PATH # ifdef _PATH_STDPATH # undef _PATH_STDPATH # endif # define _PATH_STDPATH USER_PATH #endif #ifndef _PATH_STDPATH # define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" #endif #ifndef SUPERUSER_PATH # define SUPERUSER_PATH _PATH_STDPATH #endif #ifndef _PATH_DEVNULL # define _PATH_DEVNULL "/dev/null" #endif /* user may have set a different path */ #if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) # undef _PATH_MAILDIR #endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */ #ifdef MAIL_DIRECTORY # define _PATH_MAILDIR MAIL_DIRECTORY #endif #ifndef _PATH_NOLOGIN # define _PATH_NOLOGIN "/etc/nologin" #endif /* Define this to be the path of the xauth program. */ #ifdef XAUTH_PATH #define _PATH_XAUTH XAUTH_PATH #endif /* XAUTH_PATH */ /* derived from XF4/xc/lib/dps/Xlibnet.h */ #ifndef X_UNIX_PATH # ifdef __hpux # define X_UNIX_PATH "/var/spool/sockets/X11/%u" # else # define X_UNIX_PATH "/tmp/.X11-unix/X%u" # endif #endif /* X_UNIX_PATH */ #define _PATH_UNIX_X X_UNIX_PATH #ifndef _PATH_TTY # define _PATH_TTY "/dev/tty" #endif /* Macros */ #if defined(HAVE_LOGIN_GETCAPBOOL) && defined(HAVE_LOGIN_CAP_H) # define HAVE_LOGIN_CAP #endif #ifndef MAX # define MAX(a,b) (((a)>(b))?(a):(b)) # define MIN(a,b) (((a)<(b))?(a):(b)) #endif #ifndef roundup # define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #endif #ifndef timersub #define timersub(a, b, result) \ do { \ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ if ((result)->tv_usec < 0) { \ --(result)->tv_sec; \ (result)->tv_usec += 1000000; \ } \ } while (0) #endif #ifndef TIMEVAL_TO_TIMESPEC #define TIMEVAL_TO_TIMESPEC(tv, ts) { \ (ts)->tv_sec = (tv)->tv_sec; \ (ts)->tv_nsec = (tv)->tv_usec * 1000; \ } #endif #ifndef TIMESPEC_TO_TIMEVAL #define TIMESPEC_TO_TIMEVAL(tv, ts) { \ (tv)->tv_sec = (ts)->tv_sec; \ (tv)->tv_usec = (ts)->tv_nsec / 1000; \ } #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 /* Operations on timespecs. */ #ifndef timespecclear #define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 #endif #ifndef timespeccmp #define timespeccmp(tsp, usp, cmp) \ (((tsp)->tv_sec == (usp)->tv_sec) ? \ ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ ((tsp)->tv_sec cmp (usp)->tv_sec)) #endif #ifndef timespecadd #define timespecadd(tsp, usp, vsp) \ do { \ (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ if ((vsp)->tv_nsec >= 1000000000L) { \ (vsp)->tv_sec++; \ (vsp)->tv_nsec -= 1000000000L; \ } \ } while (0) #endif #ifndef timespecsub #define timespecsub(tsp, usp, vsp) \ do { \ (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ if ((vsp)->tv_nsec < 0) { \ (vsp)->tv_sec--; \ (vsp)->tv_nsec += 1000000000L; \ } \ } while (0) #endif #ifndef __P # define __P(x) x #endif #if !defined(IN6_IS_ADDR_V4MAPPED) # define IN6_IS_ADDR_V4MAPPED(a) \ ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \ (((u_int32_t *) (a))[2] == htonl (0xffff))) #endif /* !defined(IN6_IS_ADDR_V4MAPPED) */ #if !defined(__GNUC__) || (__GNUC__ < 2) # define __attribute__(x) #endif /* !defined(__GNUC__) || (__GNUC__ < 2) */ #if !defined(HAVE_ATTRIBUTE__SENTINEL__) && !defined(__sentinel__) # define __sentinel__ #endif #if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__bounded__) # define __bounded__(x, y, z) #endif #if !defined(HAVE_ATTRIBUTE__NONNULL__) && !defined(__nonnull__) # define __nonnull__(x) #endif #ifndef OSSH_ALIGNBYTES #define OSSH_ALIGNBYTES (sizeof(int) - 1) #endif #ifndef __CMSG_ALIGN #define __CMSG_ALIGN(p) (((u_int)(p) + OSSH_ALIGNBYTES) &~ OSSH_ALIGNBYTES) #endif /* Length of the contents of a control message of length len */ #ifndef CMSG_LEN #define CMSG_LEN(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) #endif /* Length of the space taken up by a padded control message of length len */ #ifndef CMSG_SPACE #define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len)) #endif /* given pointer to struct cmsghdr, return pointer to data */ #ifndef CMSG_DATA #define CMSG_DATA(cmsg) ((u_char *)(cmsg) + __CMSG_ALIGN(sizeof(struct cmsghdr))) #endif /* CMSG_DATA */ /* * RFC 2292 requires to check msg_controllen, in case that the kernel returns * an empty list for some reasons. */ #ifndef CMSG_FIRSTHDR #define CMSG_FIRSTHDR(mhdr) \ ((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \ (struct cmsghdr *)(mhdr)->msg_control : \ (struct cmsghdr *)NULL) #endif /* CMSG_FIRSTHDR */ #if defined(HAVE_DECL_OFFSETOF) && HAVE_DECL_OFFSETOF == 0 # define offsetof(type, member) ((size_t) &((type *)0)->member) #endif /* Set up BSD-style BYTE_ORDER definition if it isn't there already */ /* XXX: doesn't try to cope with strange byte orders (PDP_ENDIAN) */ #ifndef BYTE_ORDER # ifndef LITTLE_ENDIAN # define LITTLE_ENDIAN 1234 # endif /* LITTLE_ENDIAN */ # ifndef BIG_ENDIAN # define BIG_ENDIAN 4321 # endif /* BIG_ENDIAN */ # ifdef WORDS_BIGENDIAN # define BYTE_ORDER BIG_ENDIAN # else /* WORDS_BIGENDIAN */ # define BYTE_ORDER LITTLE_ENDIAN # endif /* WORDS_BIGENDIAN */ #endif /* BYTE_ORDER */ #if (defined(HAVE_DECL_LE32TOH) && HAVE_DECL_LE32TOH == 0) || \ (defined(HAVE_DECL_LE64TOH) && HAVE_DECL_LE64TOH == 0) || \ (defined(HAVE_DECL_HTOLE64) && HAVE_DECL_HTOLE64 == 0) # define openssh_swap32(v) \ (uint32_t)(((uint32_t)(v) & 0xff) << 24 | \ ((uint32_t)(v) & 0xff00) << 8 | \ ((uint32_t)(v) & 0xff0000) >> 8 | \ ((uint32_t)(v) & 0xff000000) >> 24) # define openssh_swap64(v) \ (uint64_t)((((uint64_t)(v) & 0xff) << 56) | \ ((uint64_t)(v) & 0xff00ULL) << 40 | \ ((uint64_t)(v) & 0xff0000ULL) << 24 | \ ((uint64_t)(v) & 0xff000000ULL) << 8 | \ ((uint64_t)(v) & 0xff00000000ULL) >> 8 | \ ((uint64_t)(v) & 0xff0000000000ULL) >> 24 | \ ((uint64_t)(v) & 0xff000000000000ULL) >> 40 | \ ((uint64_t)(v) & 0xff00000000000000ULL) >> 56) # ifdef WORDS_BIGENDIAN # if defined(HAVE_DECL_LE32TOH) && HAVE_DECL_LE32TOH == 0 # define le32toh(v) (openssh_swap32(v)) # endif # if defined(HAVE_DECL_LE64TOH) && HAVE_DECL_LE64TOH == 0 # define le64toh(v) (openssh_swap64(v)) # endif # if defined(HAVE_DECL_HTOLE64) && HAVE_DECL_HTOLE64 == 0 # define htole64(v) (openssh_swap64(v)) # endif # else # if defined(HAVE_DECL_LE32TOH) && HAVE_DECL_LE32TOH == 0 # define le32toh(v) ((uint32_t)v) # endif # if defined(HAVE_DECL_LE64TOH) && HAVE_DECL_LE64TOH == 0 # define le64toh(v) ((uint64_t)v) # endif # if defined(HAVE_DECL_HTOLE64) && HAVE_DECL_HTOLE64 == 0 # define htole64(v) ((uint64_t)v) # endif # endif #endif /* Function replacement / compatibility hacks */ #if !defined(HAVE_GETADDRINFO) && (defined(HAVE_OGETADDRINFO) || defined(HAVE_NGETADDRINFO)) # define HAVE_GETADDRINFO #endif #ifndef HAVE_GETOPT_OPTRESET # undef getopt # undef opterr # undef optind # undef optopt # undef optreset # undef optarg # define getopt(ac, av, o) BSDgetopt(ac, av, o) # define opterr BSDopterr # define optind BSDoptind # define optopt BSDoptopt # define optreset BSDoptreset # define optarg BSDoptarg #endif #if defined(BROKEN_GETADDRINFO) && defined(HAVE_GETADDRINFO) # undef HAVE_GETADDRINFO #endif #if defined(BROKEN_GETADDRINFO) && defined(HAVE_FREEADDRINFO) # undef HAVE_FREEADDRINFO #endif #if defined(BROKEN_GETADDRINFO) && defined(HAVE_GAI_STRERROR) # undef HAVE_GAI_STRERROR #endif #if defined(HAVE_GETADDRINFO) # if defined(HAVE_DECL_AI_NUMERICSERV) && HAVE_DECL_AI_NUMERICSERV == 0 # define AI_NUMERICSERV 0 # endif #endif #if defined(BROKEN_UPDWTMPX) && defined(HAVE_UPDWTMPX) # undef HAVE_UPDWTMPX #endif #if defined(BROKEN_SHADOW_EXPIRE) && defined(HAS_SHADOW_EXPIRE) # undef HAS_SHADOW_EXPIRE #endif #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) && \ defined(SYSLOG_R_SAFE_IN_SIGHAND) # define DO_LOG_SAFE_IN_SIGHAND #endif #if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) # define memmove(s1, s2, n) bcopy((s2), (s1), (n)) #endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ #ifndef GETPGRP_VOID # include # define getpgrp() getpgrp(0) #endif #ifdef USE_BSM_AUDIT # define SSH_AUDIT_EVENTS # define CUSTOM_SSH_AUDIT_EVENTS #endif #ifdef USE_LINUX_AUDIT # define SSH_AUDIT_EVENTS # define CUSTOM_SSH_AUDIT_EVENTS #endif #if !defined(HAVE___func__) && defined(HAVE___FUNCTION__) # define __func__ __FUNCTION__ #elif !defined(HAVE___func__) # define __func__ "" #endif #if defined(KRB5) && !defined(HEIMDAL) # define krb5_get_err_text(context,code) error_message(code) #endif /* Maximum number of file descriptors available */ #ifdef HAVE_SYSCONF # define SSH_SYSFDMAX sysconf(_SC_OPEN_MAX) #else # define SSH_SYSFDMAX 10000 #endif #ifdef FSID_HAS_VAL /* encode f_fsid into a 64 bit value */ #define FSID_TO_ULONG(f) \ ((((u_int64_t)(f).val[0] & 0xffffffffUL) << 32) | \ ((f).val[1] & 0xffffffffUL)) #elif defined(FSID_HAS___VAL) #define FSID_TO_ULONG(f) \ ((((u_int64_t)(f).__val[0] & 0xffffffffUL) << 32) | \ ((f).__val[1] & 0xffffffffUL)) #else # define FSID_TO_ULONG(f) ((f)) #endif #if defined(__Lynx__) /* * LynxOS defines these in param.h which we do not want to include since * it will also pull in a bunch of kernel definitions. */ # define ALIGNBYTES (sizeof(int) - 1) # define ALIGN(p) (((unsigned)p + ALIGNBYTES) & ~ALIGNBYTES) /* Missing prototypes on LynxOS */ int snprintf (char *, size_t, const char *, ...); int mkstemp (char *); char *crypt (const char *, const char *); int seteuid (uid_t); int setegid (gid_t); char *mkdtemp (char *); int rresvport_af (int *, sa_family_t); int innetgr (const char *, const char *, const char *, const char *); #endif /* * Define this to use pipes instead of socketpairs for communicating with the * client program. Socketpairs do not seem to work on all systems. * * configure.ac sets this for a few OS's which are known to have problems * but you may need to set it yourself */ /* #define USE_PIPES 1 */ /** ** login recorder definitions **/ /* FIXME: put default paths back in */ #ifndef UTMP_FILE # ifdef _PATH_UTMP # define UTMP_FILE _PATH_UTMP # else # ifdef CONF_UTMP_FILE # define UTMP_FILE CONF_UTMP_FILE # endif # endif #endif #ifndef WTMP_FILE # ifdef _PATH_WTMP # define WTMP_FILE _PATH_WTMP # else # ifdef CONF_WTMP_FILE # define WTMP_FILE CONF_WTMP_FILE # endif # endif #endif /* pick up the user's location for lastlog if given */ #ifndef LASTLOG_FILE # ifdef _PATH_LASTLOG # define LASTLOG_FILE _PATH_LASTLOG # else # ifdef CONF_LASTLOG_FILE # define LASTLOG_FILE CONF_LASTLOG_FILE # endif # endif #endif #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) # define USE_SHADOW #endif /* The login() library function in libutil is first choice */ #if defined(HAVE_LOGIN) && !defined(DISABLE_LOGIN) # define USE_LOGIN #else /* Simply select your favourite login types. */ /* Can't do if-else because some systems use several... */ # if !defined(DISABLE_UTMPX) # define USE_UTMPX # endif # if defined(UTMP_FILE) && !defined(DISABLE_UTMP) # define USE_UTMP # endif # if defined(WTMPX_FILE) && !defined(DISABLE_WTMPX) # define USE_WTMPX # endif # if defined(WTMP_FILE) && !defined(DISABLE_WTMP) # define USE_WTMP # endif #endif #ifndef UT_LINESIZE # define UT_LINESIZE 8 #endif /* I hope that the presence of LASTLOG_FILE is enough to detect this */ #if defined(LASTLOG_FILE) && !defined(DISABLE_LASTLOG) # define USE_LASTLOG #endif #ifdef HAVE_OSF_SIA # ifdef USE_SHADOW # undef USE_SHADOW # endif # define CUSTOM_SYS_AUTH_PASSWD 1 #endif #if defined(HAVE_LIBIAF) && defined(HAVE_SET_ID) && !defined(HAVE_SECUREWARE) # define CUSTOM_SYS_AUTH_PASSWD 1 #endif #if defined(HAVE_LIBIAF) && defined(HAVE_SET_ID) && !defined(BROKEN_LIBIAF) # define USE_LIBIAF #endif /* HP-UX 11.11 */ #ifdef BTMP_FILE # define _PATH_BTMP BTMP_FILE #endif #if defined(USE_BTMP) && defined(_PATH_BTMP) # define CUSTOM_FAILED_LOGIN #endif /** end of login recorder definitions */ #ifdef BROKEN_GETGROUPS # define getgroups(a,b) ((a)==0 && (b)==NULL ? NGROUPS_MAX : getgroups((a),(b))) #endif #ifndef IOV_MAX # if defined(_XOPEN_IOV_MAX) # define IOV_MAX _XOPEN_IOV_MAX # elif defined(DEF_IOV_MAX) # define IOV_MAX DEF_IOV_MAX # else # define IOV_MAX 16 # endif #endif #ifndef EWOULDBLOCK # define EWOULDBLOCK EAGAIN #endif #ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ #define INET6_ADDRSTRLEN 46 #endif #ifndef SSH_IOBUFSZ # define SSH_IOBUFSZ 8192 #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. */ #if defined(HAVE_ARC4RANDOM) && defined(HAVE_ARC4RANDOM_UNIFORM) && \ !defined(HAVE_ARC4RANDOM_STIR) # define arc4random_stir() #endif #ifndef HAVE_VA_COPY # ifdef HAVE___VA_COPY # define va_copy(dest, src) __va_copy(dest, src) # else # define va_copy(dest, src) (dest) = (src) # endif #endif #ifndef __predict_true # if defined(__GNUC__) && \ ((__GNUC__ > (2)) || (__GNUC__ == (2) && __GNUC_MINOR__ >= (96))) # define __predict_true(exp) __builtin_expect(((exp) != 0), 1) # define __predict_false(exp) __builtin_expect(((exp) != 0), 0) # else # define __predict_true(exp) ((exp) != 0) # define __predict_false(exp) ((exp) != 0) # 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 /* * sntrup761 uses variable length arrays and c99-style declarations after code, * so only enable if the compiler supports them. */ #if defined(VARIABLE_LENGTH_ARRAYS) && defined(VARIABLE_DECLARATION_AFTER_CODE) # define USE_SNTRUP761X25519 1 /* The ML-KEM768 implementation also uses C89 features */ # define USE_MLKEM768X25519 1 #endif #endif /* _DEFINES_H */ openssh-10.0p1/PaxHeaders.10889/dh.c100644 001750 001750 0000000003614775415623 0013713xustar0030 atime=1744182234.564281741 openssh-10.0p1/dh.c010064400017500001750000000366111477541562300123050ustar00djmdjm/* $OpenBSD: dh.c,v 1.75 2024/12/03 16:27:53 dtucker Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #ifdef WITH_OPENSSL #include #include #include #include #include #include #include #include #include "dh.h" #include "pathnames.h" #include "log.h" #include "misc.h" #include "ssherr.h" #include "openbsd-compat/openssl-compat.h" static const char *moduli_filename; void dh_set_moduli_file(const char *filename) { moduli_filename = filename; } static const char * get_moduli_filename(void) { return moduli_filename ? moduli_filename : _PATH_DH_MODULI; } static int parse_prime(int linenum, char *line, struct dhgroup *dhg) { char *cp, *arg; char *strsize, *gen, *prime; const char *errstr = NULL; long long n; dhg->p = dhg->g = NULL; cp = line; if ((arg = strdelim(&cp)) == NULL) return 0; /* Ignore leading whitespace */ if (*arg == '\0') arg = strdelim(&cp); if (!arg || !*arg || *arg == '#') return 0; /* time */ if (cp == NULL || *arg == '\0') goto truncated; arg = strsep(&cp, " "); /* type */ if (cp == NULL || *arg == '\0') goto truncated; /* Ensure this is a safe prime */ n = strtonum(arg, 0, 5, &errstr); if (errstr != NULL || n != MODULI_TYPE_SAFE) { error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE); goto fail; } arg = strsep(&cp, " "); /* tests */ if (cp == NULL || *arg == '\0') goto truncated; /* Ensure prime has been tested and is not composite */ n = strtonum(arg, 0, 0x1f, &errstr); if (errstr != NULL || (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) { error("moduli:%d: invalid moduli tests flag", linenum); goto fail; } arg = strsep(&cp, " "); /* tries */ if (cp == NULL || *arg == '\0') goto truncated; n = strtonum(arg, 0, 1<<30, &errstr); if (errstr != NULL || n == 0) { error("moduli:%d: invalid primality trial count", linenum); goto fail; } strsize = strsep(&cp, " "); /* size */ if (cp == NULL || *strsize == '\0' || (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 || errstr) { error("moduli:%d: invalid prime length", linenum); goto fail; } /* The whole group is one bit larger */ dhg->size++; gen = strsep(&cp, " "); /* gen */ if (cp == NULL || *gen == '\0') goto truncated; prime = strsep(&cp, " "); /* prime */ if (cp != NULL || *prime == '\0') { truncated: error("moduli:%d: truncated", linenum); goto fail; } if ((dhg->g = BN_new()) == NULL || (dhg->p = BN_new()) == NULL) { error("parse_prime: BN_new failed"); goto fail; } if (BN_hex2bn(&dhg->g, gen) == 0) { error("moduli:%d: could not parse generator value", linenum); goto fail; } if (BN_hex2bn(&dhg->p, prime) == 0) { error("moduli:%d: could not parse prime value", linenum); goto fail; } if (BN_num_bits(dhg->p) != dhg->size) { error("moduli:%d: prime has wrong size: actual %d listed %d", linenum, BN_num_bits(dhg->p), dhg->size - 1); goto fail; } if (BN_cmp(dhg->g, BN_value_one()) <= 0) { error("moduli:%d: generator is invalid", linenum); goto fail; } return 1; fail: BN_clear_free(dhg->g); BN_clear_free(dhg->p); dhg->g = dhg->p = NULL; return 0; } DH * choose_dh(int min, int wantbits, int max) { FILE *f; char *line = NULL; size_t linesize = 0; int best, bestcount, which, linenum; struct dhgroup dhg; if ((f = fopen(get_moduli_filename(), "r")) == NULL) { logit("WARNING: could not open %s (%s), using fixed modulus", get_moduli_filename(), strerror(errno)); return (dh_new_group_fallback(max)); } linenum = 0; best = bestcount = 0; while (getline(&line, &linesize, f) != -1) { linenum++; if (!parse_prime(linenum, line, &dhg)) continue; BN_clear_free(dhg.g); BN_clear_free(dhg.p); if (dhg.size > max || dhg.size < min) continue; if ((dhg.size > wantbits && dhg.size < best) || (dhg.size > best && best < wantbits)) { best = dhg.size; bestcount = 0; } if (dhg.size == best) bestcount++; } free(line); line = NULL; linesize = 0; rewind(f); if (bestcount == 0) { fclose(f); logit("WARNING: no suitable primes (size %d/%d/%d) in %s", min, wantbits, max, get_moduli_filename()); return NULL; } which = arc4random_uniform(bestcount); linenum = 0; 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 || bestcount++ != which) { BN_clear_free(dhg.g); BN_clear_free(dhg.p); continue; } break; } free(line); line = NULL; fclose(f); if (bestcount != which + 1) { logit("WARNING: selected prime disappeared in %s, giving up", get_moduli_filename()); return (dh_new_group_fallback(max)); } return (dh_new_group(dhg.g, dhg.p)); } /* diffie-hellman-groupN-sha1 */ int 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; DH_get0_pqg(dh, &dh_p, NULL, NULL); if (BN_is_negative(dh_pub)) { logit("invalid public DH value: negative"); return 0; } if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */ logit("invalid public DH value: <= 1"); return 0; } if ((tmp = BN_new()) == NULL) { error_f("BN_new failed"); return 0; } 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"); return 0; } BN_clear_free(tmp); 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 < 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) return SSH_ERR_INVALID_ARGUMENT; 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; } 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) 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) { DH *dh; if ((dh = DH_new()) == NULL) return NULL; if (!DH_set0_pqg(dh, modulus, NULL, gen)) { DH_free(dh); return NULL; } return dh; } /* rfc2409 "Second Oakley Group" (1024 bits) */ DH * dh_new_group1(void) { static char *gen = "2", *group1 = "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" "ECE65381" "FFFFFFFF" "FFFFFFFF"; return (dh_new_group_asc(gen, group1)); } /* rfc3526 group 14 "2048-bit MODP Group" */ DH * dh_new_group14(void) { static char *gen = "2", *group14 = "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" "8AACAA68" "FFFFFFFF" "FFFFFFFF"; 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_f("requested max size %d", 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). * Values from NIST Special Publication 800-57: Recommendation for Key * Management Part 1 (rev 3) limited by the recommended maximum value * from RFC4419 section 3. */ u_int dh_estimate(int bits) { if (bits <= 112) return 2048; if (bits <= 128) return 3072; if (bits <= 192) return 7680; return 8192; } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/dh.h100644 001750 001750 0000000003614775415623 0013720xustar0030 atime=1744182234.564281741 openssh-10.0p1/dh.h010064400017500001750000000052371477541562300123120ustar00djmdjm/* $OpenBSD: dh.h,v 1.19 2021/03/12 04:08:19 dtucker Exp $ */ /* * Copyright (c) 2000 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. */ #ifndef DH_H #define DH_H #ifdef WITH_OPENSSL struct dhgroup { int size; BIGNUM *g; BIGNUM *p; }; DH *choose_dh(int, int, int); 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(const DH *, const BIGNUM *); u_int dh_estimate(int); void dh_set_moduli_file(const char *); /* * Max value from RFC4419. * Min value from RFC8270. */ #define DH_GRP_MIN 2048 #define DH_GRP_MAX 8192 /* * Values for "type" field of moduli(5) * Specifies the internal structure of the prime modulus. */ #define MODULI_TYPE_UNKNOWN (0) #define MODULI_TYPE_UNSTRUCTURED (1) #define MODULI_TYPE_SAFE (2) #define MODULI_TYPE_SCHNORR (3) #define MODULI_TYPE_SOPHIE_GERMAIN (4) #define MODULI_TYPE_STRONG (5) /* * Values for "tests" field of moduli(5) * Specifies the methods used in checking for primality. * Usually, more than one test is used. */ #define MODULI_TESTS_UNTESTED (0x00) #define MODULI_TESTS_COMPOSITE (0x01) #define MODULI_TESTS_SIEVE (0x02) #define MODULI_TESTS_MILLER_RABIN (0x04) #define MODULI_TESTS_JACOBI (0x08) #define MODULI_TESTS_ELLIPTIC (0x10) #endif /* WITH_OPENSSL */ #endif /* DH_H */ openssh-10.0p1/PaxHeaders.10889/digest-libc.c100644 001750 001750 0000000003614775415623 0015506xustar0030 atime=1744182234.564281741 openssh-10.0p1/digest-libc.c010064400017500001750000000141211477541562300140700ustar00djmdjm/* $OpenBSD: digest-libc.c,v 1.7 2020/02/26 13:40:09 jsg Exp $ */ /* * Copyright (c) 2013 Damien Miller * Copyright (c) 2014 Markus Friedl. All rights reserved. * * 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" #ifndef WITH_OPENSSL #include #include #include #include #if 0 #include #include #endif #ifdef HAVE_SHA1_H #include #endif #ifdef HAVE_SHA2_H #include #endif #if !defined(SHA256_BLOCK_LENGTH) && defined(SHA256_HMAC_BLOCK_SIZE) #define SHA256_BLOCK_LENGTH SHA256_HMAC_BLOCK_SIZE #endif #if !defined(SHA384_BLOCK_LENGTH) && defined(SHA512_HMAC_BLOCK_SIZE) #define SHA384_BLOCK_LENGTH SHA512_HMAC_BLOCK_SIZE #endif #if !defined(SHA512_BLOCK_LENGTH) && defined(SHA512_HMAC_BLOCK_SIZE) #define SHA512_BLOCK_LENGTH SHA512_HMAC_BLOCK_SIZE #endif #include "ssherr.h" #include "sshbuf.h" #include "digest.h" typedef void md_init_fn(void *mdctx); typedef void md_update_fn(void *mdctx, const u_int8_t *m, size_t mlen); typedef void md_final_fn(u_int8_t[], void *mdctx); struct ssh_digest_ctx { int alg; void *mdctx; }; struct ssh_digest { int id; const char *name; size_t block_len; size_t digest_len; size_t ctx_len; md_init_fn *md_init; md_update_fn *md_update; md_final_fn *md_final; }; /* NB. Indexed directly by algorithm number */ const struct ssh_digest digests[SSH_DIGEST_MAX] = { { SSH_DIGEST_MD5, "MD5", MD5_BLOCK_LENGTH, MD5_DIGEST_LENGTH, sizeof(MD5_CTX), (md_init_fn *) MD5Init, (md_update_fn *) MD5Update, (md_final_fn *) MD5Final }, { SSH_DIGEST_SHA1, "SHA1", SHA1_BLOCK_LENGTH, SHA1_DIGEST_LENGTH, sizeof(SHA1_CTX), (md_init_fn *) SHA1Init, (md_update_fn *) SHA1Update, (md_final_fn *) SHA1Final }, { SSH_DIGEST_SHA256, "SHA256", SHA256_BLOCK_LENGTH, SHA256_DIGEST_LENGTH, 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(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(SHA2_CTX), (md_init_fn *) SHA512Init, (md_update_fn *) SHA512Update, (md_final_fn *) SHA512Final } }; static const struct ssh_digest * ssh_digest_by_alg(int alg) { if (alg < 0 || alg >= SSH_DIGEST_MAX) return NULL; if (digests[alg].id != alg) /* sanity */ return NULL; return &(digests[alg]); } int ssh_digest_alg_by_name(const char *name) { int alg; for (alg = 0; alg < SSH_DIGEST_MAX; alg++) { if (strcasecmp(name, digests[alg].name) == 0) return digests[alg].id; } return -1; } const char * ssh_digest_alg_name(int alg) { const struct ssh_digest *digest = ssh_digest_by_alg(alg); return digest == NULL ? NULL : digest->name; } size_t ssh_digest_bytes(int alg) { const struct ssh_digest *digest = ssh_digest_by_alg(alg); return digest == NULL ? 0 : digest->digest_len; } size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx) { const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); return digest == NULL ? 0 : digest->block_len; } struct ssh_digest_ctx * 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) return NULL; if ((ret->mdctx = calloc(1, digest->ctx_len)) == NULL) { free(ret); return NULL; } ret->alg = alg; digest->md_init(ret->mdctx); return ret; } int ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) { const struct ssh_digest *digest = ssh_digest_by_alg(from->alg); if (digest == NULL || from->alg != to->alg) return SSH_ERR_INVALID_ARGUMENT; memcpy(to->mdctx, from->mdctx, digest->ctx_len); return 0; } int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) { const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); if (digest == NULL) return SSH_ERR_INVALID_ARGUMENT; digest->md_update(ctx->mdctx, m, mlen); return 0; } int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b) { return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b)); } int 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); if (digest == NULL) return SSH_ERR_INVALID_ARGUMENT; if (dlen > UINT_MAX) return SSH_ERR_INVALID_ARGUMENT; if (dlen < digest->digest_len) /* No truncation allowed */ return SSH_ERR_INVALID_ARGUMENT; digest->md_final(d, ctx->mdctx); return 0; } void ssh_digest_free(struct ssh_digest_ctx *ctx) { const struct ssh_digest *digest; if (ctx != NULL) { digest = ssh_digest_by_alg(ctx->alg); if (digest) { explicit_bzero(ctx->mdctx, digest->ctx_len); free(ctx->mdctx); freezero(ctx, sizeof(*ctx)); } } } int ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) { struct ssh_digest_ctx *ctx = ssh_digest_start(alg); if (ctx == NULL) return SSH_ERR_INVALID_ARGUMENT; if (ssh_digest_update(ctx, m, mlen) != 0 || ssh_digest_final(ctx, d, dlen) != 0) return SSH_ERR_INVALID_ARGUMENT; ssh_digest_free(ctx); return 0; } int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) { return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen); } #endif /* !WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/digest-openssl.c100644 001750 001750 0000000003614775415623 0016260xustar0030 atime=1744182234.565259149 openssh-10.0p1/digest-openssl.c010064400017500001750000000116311477541562300146450ustar00djmdjm/* $OpenBSD: digest-openssl.c,v 1.9 2020/10/29 02:52:43 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef WITH_OPENSSL #include #include #include #include #include #include "openbsd-compat/openssl-compat.h" #include "sshbuf.h" #include "digest.h" #include "ssherr.h" #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 struct ssh_digest_ctx { int alg; EVP_MD_CTX *mdctx; }; struct ssh_digest { int id; const char *name; size_t digest_len; const EVP_MD *(*mdfunc)(void); }; /* NB. Indexed directly by algorithm number */ const struct ssh_digest digests[] = { { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, { -1, NULL, 0, NULL }, }; static const struct ssh_digest * ssh_digest_by_alg(int alg) { if (alg < 0 || alg >= SSH_DIGEST_MAX) return NULL; if (digests[alg].id != alg) /* sanity */ return NULL; if (digests[alg].mdfunc == NULL) return NULL; return &(digests[alg]); } int ssh_digest_alg_by_name(const char *name) { int alg; for (alg = 0; digests[alg].id != -1; alg++) { if (strcasecmp(name, digests[alg].name) == 0) return digests[alg].id; } return -1; } const char * ssh_digest_alg_name(int alg) { const struct ssh_digest *digest = ssh_digest_by_alg(alg); return digest == NULL ? NULL : digest->name; } size_t ssh_digest_bytes(int alg) { const struct ssh_digest *digest = ssh_digest_by_alg(alg); return digest == NULL ? 0 : digest->digest_len; } size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx) { return EVP_MD_CTX_block_size(ctx->mdctx); } struct ssh_digest_ctx * 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)) return NULL; ret->alg = alg; 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; } int 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)) return SSH_ERR_LIBCRYPTO_ERROR; return 0; } int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) { if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1) return SSH_ERR_LIBCRYPTO_ERROR; return 0; } int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b) { return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b)); } int 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 (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) return SSH_ERR_LIBCRYPTO_ERROR; if (l != digest->digest_len) /* sanity */ return SSH_ERR_INTERNAL_ERROR; return 0; } void ssh_digest_free(struct ssh_digest_ctx *ctx) { if (ctx == NULL) return; EVP_MD_CTX_free(ctx->mdctx); freezero(ctx, sizeof(*ctx)); } int ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) { const struct ssh_digest *digest = ssh_digest_by_alg(alg); u_int mdlen; if (digest == NULL) return SSH_ERR_INVALID_ARGUMENT; if (dlen > UINT_MAX) return SSH_ERR_INVALID_ARGUMENT; if (dlen < digest->digest_len) return SSH_ERR_INVALID_ARGUMENT; mdlen = dlen; if (!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL)) return SSH_ERR_LIBCRYPTO_ERROR; return 0; } int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) { return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen); } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/digest.h100644 001750 001750 0000000003614775415623 0014604xustar0030 atime=1744182234.565259149 openssh-10.0p1/digest.h010064400017500001750000000050131477541562300131660ustar00djmdjm/* $OpenBSD: digest.h,v 1.8 2017/05/08 22:57:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _DIGEST_H #define _DIGEST_H /* Maximum digest output length */ #define SSH_DIGEST_MAX_LENGTH 64 /* Digest algorithms */ #define SSH_DIGEST_MD5 0 #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; /* Looks up a digest algorithm by name */ int ssh_digest_alg_by_name(const char *name); /* Returns the algorithm name for a digest identifier */ const char *ssh_digest_alg_name(int alg); /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ size_t ssh_digest_bytes(int alg); /* Returns the block size of the digest, e.g. for implementing HMAC */ size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx); /* Copies internal state of digest of 'from' to 'to' */ int ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to); /* One-shot API */ int ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 2, 3))) __attribute__((__bounded__(__buffer__, 4, 5))); int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 3, 4))); /* Update API */ struct ssh_digest_ctx *ssh_digest_start(int alg); int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) __attribute__((__bounded__(__buffer__, 2, 3))); int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b); int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 2, 3))); void ssh_digest_free(struct ssh_digest_ctx *ctx); #endif /* _DIGEST_H */ openssh-10.0p1/PaxHeaders.10889/dispatch.c100644 001750 001750 0000000003614775415623 0015117xustar0030 atime=1744182234.565259149 openssh-10.0p1/dispatch.c010064400017500001750000000070121477541562300135020ustar00djmdjm/* $OpenBSD: dispatch.c,v 1.33 2023/03/05 05:34:09 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include "ssh2.h" #include "log.h" #include "dispatch.h" #include "packet.h" #include "ssherr.h" int dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { int r; logit("dispatch_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 || (r = ssh_packet_write_wait(ssh)) != 0) sshpkt_fatal(ssh, r, "%s", __func__); return 0; } int dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh) { logit("dispatch_protocol_ignore: type %d seq %u", type, seq); return 0; } void ssh_dispatch_init(struct ssh *ssh, dispatch_fn *dflt) { u_int i; for (i = 0; i < DISPATCH_MAX; i++) ssh->dispatch[i] = dflt; } void ssh_dispatch_range(struct ssh *ssh, u_int from, u_int to, dispatch_fn *fn) { u_int i; for (i = from; i <= to; i++) { if (i >= DISPATCH_MAX) break; ssh->dispatch[i] = fn; } } void ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn) { ssh->dispatch[type] = fn; } int ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done) { int r; u_char type; u_int32_t seqnr; for (;;) { if (mode == DISPATCH_BLOCK) { r = ssh_packet_read_seqnr(ssh, &type, &seqnr); if (r != 0) return r; } else { r = ssh_packet_read_poll_seqnr(ssh, &type, &seqnr); if (r != 0) return r; if (type == SSH_MSG_NONE) return 0; } if (type > 0 && type < DISPATCH_MAX && ssh->dispatch[type] != NULL) { if (ssh->dispatch_skip_packets) { debug2("skipped packet (type %u)", type); ssh->dispatch_skip_packets--; continue; } r = (*ssh->dispatch[type])(type, seqnr, ssh); if (r != 0) return r; } else { r = sshpkt_disconnect(ssh, "protocol error: rcvd type %d", type); if (r != 0) return r; return SSH_ERR_DISCONNECTED; } if (done != NULL && *done) return 0; } } void ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done) { int r; if ((r = ssh_dispatch_run(ssh, mode, done)) != 0) sshpkt_fatal(ssh, r, "%s", __func__); } openssh-10.0p1/PaxHeaders.10889/dispatch.h100644 001750 001750 0000000003614775415623 0015124xustar0030 atime=1744182234.565259149 openssh-10.0p1/dispatch.h010064400017500001750000000037271477541562300135200ustar00djmdjm/* $OpenBSD: dispatch.h,v 1.15 2019/01/19 21:45:31 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. */ #ifndef DISPATCH_H #define DISPATCH_H #define DISPATCH_MAX 255 enum { DISPATCH_BLOCK, DISPATCH_NONBLOCK }; struct ssh; typedef int dispatch_fn(int, u_int32_t, struct ssh *); 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 ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *); #endif openssh-10.0p1/PaxHeaders.10889/dns.c100644 001750 001750 0000000003614775415623 0014104xustar0030 atime=1744182234.565259149 openssh-10.0p1/dns.c010064400017500001750000000215761477541562300125020ustar00djmdjm/* $OpenBSD: dns.c,v 1.44 2023/03/10 04:06:21 dtucker Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 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. */ #include "includes.h" #include #include #include #include #include #include #include #include "xmalloc.h" #include "sshkey.h" #include "ssherr.h" #include "dns.h" #include "log.h" #include "digest.h" static const char * const errset_text[] = { "success", /* 0 ERRSET_SUCCESS */ "out of memory", /* 1 ERRSET_NOMEMORY */ "general failure", /* 2 ERRSET_FAIL */ "invalid parameter", /* 3 ERRSET_INVAL */ "name does not exist", /* 4 ERRSET_NONAME */ "data does not exist", /* 5 ERRSET_NODATA */ }; static const char * dns_result_totext(unsigned int res) { switch (res) { case ERRSET_SUCCESS: return errset_text[ERRSET_SUCCESS]; case ERRSET_NOMEMORY: return errset_text[ERRSET_NOMEMORY]; case ERRSET_FAIL: return errset_text[ERRSET_FAIL]; case ERRSET_INVAL: return errset_text[ERRSET_INVAL]; case ERRSET_NONAME: return errset_text[ERRSET_NONAME]; case ERRSET_NODATA: return errset_text[ERRSET_NODATA]; default: return "unknown error"; } } /* * Read SSHFP parameters from key buffer. * Caller must free digest which is allocated by sshkey_fingerprint_raw(). */ static int dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, u_char **digest, size_t *digest_len, struct sshkey *key) { int r, success = 0; int fp_alg = -1; switch (key->type) { case KEY_RSA: *algorithm = SSHFP_KEY_RSA; break; case KEY_DSA: *algorithm = SSHFP_KEY_DSA; break; case KEY_ECDSA: *algorithm = SSHFP_KEY_ECDSA; break; case KEY_ED25519: *algorithm = SSHFP_KEY_ED25519; break; case KEY_XMSS: *algorithm = SSHFP_KEY_XMSS; break; default: *algorithm = SSHFP_KEY_RESERVED; /* 0 */ } switch (*digest_type) { case SSHFP_HASH_SHA1: fp_alg = SSH_DIGEST_SHA1; break; case SSHFP_HASH_SHA256: fp_alg = SSH_DIGEST_SHA256; break; default: *digest_type = SSHFP_HASH_RESERVED; /* 0 */ } if (*algorithm && *digest_type) { if ((r = sshkey_fingerprint_raw(key, fp_alg, digest, digest_len)) != 0) fatal_fr(r, "sshkey_fingerprint_raw"); success = 1; } else { *digest = NULL; *digest_len = 0; } return success; } /* * Read SSHFP parameters from rdata buffer. */ static int dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type, u_char **digest, size_t *digest_len, u_char *rdata, int rdata_len) { int success = 0; *algorithm = SSHFP_KEY_RESERVED; *digest_type = SSHFP_HASH_RESERVED; if (rdata_len >= 2) { *algorithm = rdata[0]; *digest_type = rdata[1]; *digest_len = rdata_len - 2; if (*digest_len > 0) { *digest = xmalloc(*digest_len); memcpy(*digest, rdata + 2, *digest_len); } else { *digest = (u_char *)xstrdup(""); } success = 1; } return success; } /* * Check if hostname is numerical. * Returns -1 if hostname is numeric, 0 otherwise */ static int is_numeric_hostname(const char *hostname) { struct addrinfo hints, *ai; /* * We shouldn't ever get a null host but if we do then log an error * and return -1 which stops DNS key fingerprint processing. */ if (hostname == NULL) { error("is_numeric_hostname called with NULL hostname"); return -1; } memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) { freeaddrinfo(ai); return -1; } return 0; } /* * Verify the given hostname, address and host key using DNS. * Returns 0 if lookup succeeds, -1 otherwise */ int verify_host_key_dns(const char *hostname, struct sockaddr *address, struct sshkey *hostkey, int *flags) { u_int counter; int result; struct rrsetinfo *fingerprints = NULL; u_int8_t hostkey_algorithm; u_char *hostkey_digest; size_t hostkey_digest_len; u_int8_t dnskey_algorithm; u_int8_t dnskey_digest_type; u_char *dnskey_digest; size_t dnskey_digest_len; *flags = 0; debug3("verify_host_key_dns"); if (hostkey == NULL) fatal("No key to look up!"); if (is_numeric_hostname(hostname)) { debug("skipped DNS lookup for numerical hostname"); return -1; } result = getrrsetbyname(hostname, DNS_RDATACLASS_IN, DNS_RDATATYPE_SSHFP, 0, &fingerprints); if (result) { verbose("DNS lookup error: %s", dns_result_totext(result)); return -1; } if (fingerprints->rri_flags & RRSET_VALIDATED) { *flags |= DNS_VERIFY_SECURE; debug("found %d secure fingerprints in DNS", fingerprints->rri_nrdatas); } else { debug("found %d insecure fingerprints in DNS", fingerprints->rri_nrdatas); } if (fingerprints->rri_nrdatas) *flags |= DNS_VERIFY_FOUND; for (counter = 0; counter < fingerprints->rri_nrdatas; counter++) { /* * Extract the key from the answer. Ignore any badly * formatted fingerprints. */ if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type, &dnskey_digest, &dnskey_digest_len, fingerprints->rri_rdatas[counter].rdi_data, fingerprints->rri_rdatas[counter].rdi_length)) { verbose("Error parsing fingerprint from DNS."); continue; } debug3_f("checking SSHFP type %d fptype %d", dnskey_algorithm, dnskey_digest_type); /* Calculate host key fingerprint. */ if (!dns_read_key(&hostkey_algorithm, &dnskey_digest_type, &hostkey_digest, &hostkey_digest_len, hostkey)) { error("Error calculating key fingerprint."); free(dnskey_digest); freerrset(fingerprints); return -1; } /* Check if the current key is the same as the given key */ if (hostkey_algorithm == dnskey_algorithm && hostkey_digest_len == dnskey_digest_len) { if (timingsafe_bcmp(hostkey_digest, dnskey_digest, hostkey_digest_len) == 0) { debug_f("matched SSHFP type %d fptype %d", dnskey_algorithm, dnskey_digest_type); *flags |= DNS_VERIFY_MATCH; } else { debug_f("failed SSHFP type %d fptype %d", dnskey_algorithm, dnskey_digest_type); *flags |= DNS_VERIFY_FAILED; } } free(dnskey_digest); free(hostkey_digest); /* from sshkey_fingerprint_raw() */ } freerrset(fingerprints); /* If any fingerprint failed to validate, return failure. */ if (*flags & DNS_VERIFY_FAILED) *flags &= ~DNS_VERIFY_MATCH; if (*flags & DNS_VERIFY_FOUND) if (*flags & DNS_VERIFY_MATCH) debug("matching host key fingerprint found in DNS"); else debug("mismatching host key fingerprint found in DNS"); else debug("no host key fingerprint found in DNS"); return 0; } /* * Export the fingerprint of a key as a DNS resource record */ int export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic, int alg) { u_int8_t rdata_pubkey_algorithm = 0; u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED; u_int8_t dtype; u_char *rdata_digest; size_t i, rdata_digest_len; int success = 0; for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) { if (alg != -1 && dtype != alg) continue; rdata_digest_type = dtype; if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, &rdata_digest, &rdata_digest_len, key)) { if (generic) { fprintf(f, "%s IN TYPE%d \\# %zu %02x %02x ", hostname, DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len, rdata_pubkey_algorithm, rdata_digest_type); } else { fprintf(f, "%s IN SSHFP %d %d ", hostname, rdata_pubkey_algorithm, rdata_digest_type); } for (i = 0; i < rdata_digest_len; i++) fprintf(f, "%02x", rdata_digest[i]); fprintf(f, "\n"); free(rdata_digest); /* from sshkey_fingerprint_raw() */ success = 1; } } /* No SSHFP record was generated at all */ if (success == 0) { error_f("unsupported algorithm and/or digest_type"); } return success; } openssh-10.0p1/PaxHeaders.10889/dns.h100644 001750 001750 0000000003614775415623 0014111xustar0030 atime=1744182234.565259149 openssh-10.0p1/dns.h010064400017500001750000000041041477541562300124730ustar00djmdjm/* $OpenBSD: dns.h,v 1.20 2023/02/10 04:56:30 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 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. */ #ifndef DNS_H #define DNS_H enum sshfp_types { SSHFP_KEY_RESERVED = 0, SSHFP_KEY_RSA = 1, SSHFP_KEY_DSA = 2, SSHFP_KEY_ECDSA = 3, SSHFP_KEY_ED25519 = 4, SSHFP_KEY_XMSS = 5 }; enum sshfp_hashes { SSHFP_HASH_RESERVED = 0, SSHFP_HASH_SHA1 = 1, SSHFP_HASH_SHA256 = 2, SSHFP_HASH_MAX = 3 }; #define DNS_RDATACLASS_IN 1 #define DNS_RDATATYPE_SSHFP 44 #define DNS_VERIFY_FOUND 0x00000001 #define DNS_VERIFY_MATCH 0x00000002 #define DNS_VERIFY_SECURE 0x00000004 #define DNS_VERIFY_FAILED 0x00000008 int verify_host_key_dns(const char *, struct sockaddr *, struct sshkey *, int *); int export_dns_rr(const char *, struct sshkey *, FILE *, int, int); #endif /* DNS_H */ openssh-10.0p1/PaxHeaders.10889/ed25519.c100644 001750 001750 0000000003614775415623 0014316xustar0030 atime=1744182234.567211683 openssh-10.0p1/ed25519.c010064400017500001750000006115401477541562300127100ustar00djmdjm/* $OpenBSD: ed25519.c,v 1.4 2023/01/15 23:05:32 djm Exp $ */ /* * Public Domain, Authors: * - Daniel J. Bernstein * - Niels Duif * - Tanja Lange * - lead: Peter Schwabe * - Bo-Yin Yang */ #include "includes.h" #include #include "crypto_api.h" #define int8 crypto_int8 #define uint8 crypto_uint8 #define int16 crypto_int16 #define uint16 crypto_uint16 #define int32 crypto_int32 #define uint32 crypto_uint32 #define int64 crypto_int64 #define uint64 crypto_uint64 /* from supercop-20221122/crypto_verify/32/ref/verify.c */ static int crypto_verify_32(const unsigned char *x,const unsigned char *y) { unsigned int differentbits = 0; #define F(i) differentbits |= x[i] ^ y[i]; F(0) F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8) F(9) F(10) F(11) F(12) F(13) F(14) F(15) F(16) F(17) F(18) F(19) F(20) F(21) F(22) F(23) F(24) F(25) F(26) F(27) F(28) F(29) F(30) F(31) return (1 & ((differentbits - 1) >> 8)) - 1; } /* from supercop-20221122/crypto_sign/ed25519/ref/fe25519.h */ #ifndef FE25519_H #define FE25519_H #define fe25519 crypto_sign_ed25519_ref_fe25519 #define fe25519_freeze crypto_sign_ed25519_ref_fe25519_freeze #define fe25519_unpack crypto_sign_ed25519_ref_fe25519_unpack #define fe25519_pack crypto_sign_ed25519_ref_fe25519_pack #define fe25519_iszero crypto_sign_ed25519_ref_fe25519_iszero #define fe25519_iseq_vartime crypto_sign_ed25519_ref_fe25519_iseq_vartime #define fe25519_cmov crypto_sign_ed25519_ref_fe25519_cmov #define fe25519_setone crypto_sign_ed25519_ref_fe25519_setone #define fe25519_setzero crypto_sign_ed25519_ref_fe25519_setzero #define fe25519_neg crypto_sign_ed25519_ref_fe25519_neg #define fe25519_getparity crypto_sign_ed25519_ref_fe25519_getparity #define fe25519_add crypto_sign_ed25519_ref_fe25519_add #define fe25519_sub crypto_sign_ed25519_ref_fe25519_sub #define fe25519_mul crypto_sign_ed25519_ref_fe25519_mul #define fe25519_square crypto_sign_ed25519_ref_fe25519_square #define fe25519_invert crypto_sign_ed25519_ref_fe25519_invert #define fe25519_pow2523 crypto_sign_ed25519_ref_fe25519_pow2523 typedef struct { crypto_uint32 v[32]; } fe25519; static void fe25519_freeze(fe25519 *r); static void fe25519_unpack(fe25519 *r, const unsigned char x[32]); static void fe25519_pack(unsigned char r[32], const fe25519 *x); static int fe25519_iszero(const fe25519 *x); static int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y); static void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b); static void fe25519_setone(fe25519 *r); static void fe25519_setzero(fe25519 *r); static void fe25519_neg(fe25519 *r, const fe25519 *x); unsigned char fe25519_getparity(const fe25519 *x); static void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y); static void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); static void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y); static void fe25519_square(fe25519 *r, const fe25519 *x); static void fe25519_invert(fe25519 *r, const fe25519 *x); static void fe25519_pow2523(fe25519 *r, const fe25519 *x); #endif /* from supercop-20221122/crypto_sign/ed25519/ref/fe25519.c */ #define WINDOWSIZE 1 /* Should be 1,2, or 4 */ #define WINDOWMASK ((1<>= 31; /* 1: yes; 0: no */ return x; } static crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */ x >>= 31; /* 0: yes; 1: no */ x ^= 1; /* 1: yes; 0: no */ return x; } static crypto_uint32 times19(crypto_uint32 a) { return (a << 4) + (a << 1) + a; } static crypto_uint32 times38(crypto_uint32 a) { return (a << 5) + (a << 2) + (a << 1); } static void fe25519_reduce_add_sub(fe25519 *r) { crypto_uint32 t; int i,rep; for(rep=0;rep<4;rep++) { t = r->v[31] >> 7; r->v[31] &= 127; t = times19(t); r->v[0] += t; for(i=0;i<31;i++) { t = r->v[i] >> 8; r->v[i+1] += t; r->v[i] &= 255; } } } static void reduce_mul(fe25519 *r) { crypto_uint32 t; int i,rep; for(rep=0;rep<2;rep++) { t = r->v[31] >> 7; r->v[31] &= 127; t = times19(t); r->v[0] += t; for(i=0;i<31;i++) { t = r->v[i] >> 8; r->v[i+1] += t; r->v[i] &= 255; } } } /* reduction modulo 2^255-19 */ static void fe25519_freeze(fe25519 *r) { int i; crypto_uint32 m = fe25519_equal(r->v[31],127); for(i=30;i>0;i--) m &= fe25519_equal(r->v[i],255); m &= ge(r->v[0],237); m = -m; r->v[31] -= m&127; for(i=30;i>0;i--) r->v[i] -= m&255; r->v[0] -= m&237; } static void fe25519_unpack(fe25519 *r, const unsigned char x[32]) { int i; for(i=0;i<32;i++) r->v[i] = x[i]; r->v[31] &= 127; } /* Assumes input x being reduced below 2^255 */ static void fe25519_pack(unsigned char r[32], const fe25519 *x) { int i; fe25519 y = *x; fe25519_freeze(&y); for(i=0;i<32;i++) r[i] = y.v[i]; } static int fe25519_iszero(const fe25519 *x) { int i; int r; fe25519 t = *x; fe25519_freeze(&t); r = fe25519_equal(t.v[0],0); for(i=1;i<32;i++) r &= fe25519_equal(t.v[i],0); return r; } static int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) { int i; fe25519 t1 = *x; fe25519 t2 = *y; fe25519_freeze(&t1); fe25519_freeze(&t2); for(i=0;i<32;i++) if(t1.v[i] != t2.v[i]) return 0; return 1; } static void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) { int i; crypto_uint32 mask = b; mask = -mask; for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); } unsigned char fe25519_getparity(const fe25519 *x) { fe25519 t = *x; fe25519_freeze(&t); return t.v[0] & 1; } static void fe25519_setone(fe25519 *r) { int i; r->v[0] = 1; for(i=1;i<32;i++) r->v[i]=0; } static void fe25519_setzero(fe25519 *r) { int i; for(i=0;i<32;i++) r->v[i]=0; } static void fe25519_neg(fe25519 *r, const fe25519 *x) { fe25519 t; int i; for(i=0;i<32;i++) t.v[i]=x->v[i]; fe25519_setzero(r); fe25519_sub(r, r, &t); } static void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; fe25519_reduce_add_sub(r); } static void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; crypto_uint32 t[32]; t[0] = x->v[0] + 0x1da; t[31] = x->v[31] + 0xfe; for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe; for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i]; fe25519_reduce_add_sub(r); } static void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i,j; crypto_uint32 t[63]; for(i=0;i<63;i++)t[i] = 0; for(i=0;i<32;i++) for(j=0;j<32;j++) t[i+j] += x->v[i] * y->v[j]; for(i=32;i<63;i++) r->v[i-32] = t[i-32] + times38(t[i]); r->v[31] = t[31]; /* result now in r[0]...r[31] */ reduce_mul(r); } static void fe25519_square(fe25519 *r, const fe25519 *x) { fe25519_mul(r, x, x); } static void fe25519_invert(fe25519 *r, const fe25519 *x) { fe25519 z2; fe25519 z9; fe25519 z11; fe25519 z2_5_0; fe25519 z2_10_0; fe25519 z2_20_0; fe25519 z2_50_0; fe25519 z2_100_0; fe25519 t0; fe25519 t1; int i; /* 2 */ fe25519_square(&z2,x); /* 4 */ fe25519_square(&t1,&z2); /* 8 */ fe25519_square(&t0,&t1); /* 9 */ fe25519_mul(&z9,&t0,x); /* 11 */ fe25519_mul(&z11,&z9,&z2); /* 22 */ fe25519_square(&t0,&z11); /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9); /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0); /* 2^7 - 2^2 */ fe25519_square(&t1,&t0); /* 2^8 - 2^3 */ fe25519_square(&t0,&t1); /* 2^9 - 2^4 */ fe25519_square(&t1,&t0); /* 2^10 - 2^5 */ fe25519_square(&t0,&t1); /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0); /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0); /* 2^12 - 2^2 */ fe25519_square(&t1,&t0); /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0); /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0); /* 2^22 - 2^2 */ fe25519_square(&t1,&t0); /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0); /* 2^41 - 2^1 */ fe25519_square(&t1,&t0); /* 2^42 - 2^2 */ fe25519_square(&t0,&t1); /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0); /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0); /* 2^52 - 2^2 */ fe25519_square(&t1,&t0); /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0); /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0); /* 2^102 - 2^2 */ fe25519_square(&t0,&t1); /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0); /* 2^201 - 2^1 */ fe25519_square(&t0,&t1); /* 2^202 - 2^2 */ fe25519_square(&t1,&t0); /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0); /* 2^251 - 2^1 */ fe25519_square(&t1,&t0); /* 2^252 - 2^2 */ fe25519_square(&t0,&t1); /* 2^253 - 2^3 */ fe25519_square(&t1,&t0); /* 2^254 - 2^4 */ fe25519_square(&t0,&t1); /* 2^255 - 2^5 */ fe25519_square(&t1,&t0); /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11); } static void fe25519_pow2523(fe25519 *r, const fe25519 *x) { fe25519 z2; fe25519 z9; fe25519 z11; fe25519 z2_5_0; fe25519 z2_10_0; fe25519 z2_20_0; fe25519 z2_50_0; fe25519 z2_100_0; fe25519 t; int i; /* 2 */ fe25519_square(&z2,x); /* 4 */ fe25519_square(&t,&z2); /* 8 */ fe25519_square(&t,&t); /* 9 */ fe25519_mul(&z9,&t,x); /* 11 */ fe25519_mul(&z11,&z9,&z2); /* 22 */ fe25519_square(&t,&z11); /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9); /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0); /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); } /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0); /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0); /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0); /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0); /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); } /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0); /* 2^41 - 2^1 */ fe25519_square(&t,&t); /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0); /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0); /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0); /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0); /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); } /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0); /* 2^201 - 2^1 */ fe25519_square(&t,&t); /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0); /* 2^251 - 2^1 */ fe25519_square(&t,&t); /* 2^252 - 2^2 */ fe25519_square(&t,&t); /* 2^252 - 3 */ fe25519_mul(r,&t,x); } /* from supercop-20221122/crypto_sign/ed25519/ref/sc25519.h */ #ifndef SC25519_H #define SC25519_H #define sc25519 crypto_sign_ed25519_ref_sc25519 #define shortsc25519 crypto_sign_ed25519_ref_shortsc25519 #define sc25519_from32bytes crypto_sign_ed25519_ref_sc25519_from32bytes #define sc25519_from64bytes crypto_sign_ed25519_ref_sc25519_from64bytes #define sc25519_to32bytes crypto_sign_ed25519_ref_sc25519_to32bytes #define sc25519_add crypto_sign_ed25519_ref_sc25519_add #define sc25519_mul crypto_sign_ed25519_ref_sc25519_mul #define sc25519_window3 crypto_sign_ed25519_ref_sc25519_window3 #define sc25519_2interleave2 crypto_sign_ed25519_ref_sc25519_2interleave2 typedef struct { crypto_uint32 v[32]; } sc25519; typedef struct { crypto_uint32 v[16]; } shortsc25519; static void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]); static void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]); static void sc25519_to32bytes(unsigned char r[32], const sc25519 *x); static void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y); static void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y); /* Convert s into a representation of the form \sum_{i=0}^{84}r[i]2^3 * with r[i] in {-4,...,3} */ static void sc25519_window3(signed char r[85], const sc25519 *s); /* Convert s into a representation of the form \sum_{i=0}^{50}r[i]2^5 * with r[i] in {-16,...,15} */ static void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2); #endif /* from supercop-20221122/crypto_sign/ed25519/ref/sc25519.c */ /*Arithmetic modulo the group order m = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989 */ static const crypto_uint32 sc25519_m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; static const crypto_uint32 sc25519_mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; static crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ x >>= 31; /* 0: no; 1: yes */ return x; } /* Reduce coefficients of r before calling sc25519_reduce_add_sub */ static void sc25519_reduce_add_sub(sc25519 *r) { crypto_uint32 pb = 0; crypto_uint32 b; crypto_uint32 mask; int i; unsigned char t[32]; for(i=0;i<32;i++) { pb += sc25519_m[i]; b = lt(r->v[i],pb); t[i] = r->v[i]-pb+(b<<8); pb = b; } mask = b - 1; for(i=0;i<32;i++) r->v[i] ^= mask & (r->v[i] ^ t[i]); } /* Reduce coefficients of x before calling barrett_reduce */ static void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) { /* See HAC, Alg. 14.42 */ int i,j; crypto_uint32 q2[66]; crypto_uint32 *q3 = q2 + 33; crypto_uint32 r1[33]; crypto_uint32 r2[33]; crypto_uint32 carry; crypto_uint32 pb = 0; crypto_uint32 b; for (i = 0;i < 66;++i) q2[i] = 0; for (i = 0;i < 33;++i) r2[i] = 0; for(i=0;i<33;i++) for(j=0;j<33;j++) if(i+j >= 31) q2[i+j] += sc25519_mu[i]*x[j+31]; carry = q2[31] >> 8; q2[32] += carry; carry = q2[32] >> 8; q2[33] += carry; for(i=0;i<33;i++)r1[i] = x[i]; for(i=0;i<32;i++) for(j=0;j<33;j++) if(i+j < 33) r2[i+j] += sc25519_m[i]*q3[j]; for(i=0;i<32;i++) { carry = r2[i] >> 8; r2[i+1] += carry; r2[i] &= 0xff; } for(i=0;i<32;i++) { pb += r2[i]; b = lt(r1[i],pb); r->v[i] = r1[i]-pb+(b<<8); pb = b; } /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 * If so: Handle it here! */ sc25519_reduce_add_sub(r); sc25519_reduce_add_sub(r); } static void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) { int i; crypto_uint32 t[64]; for(i=0;i<32;i++) t[i] = x[i]; for(i=32;i<64;++i) t[i] = 0; barrett_reduce(r, t); } static void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) { int i; crypto_uint32 t[64]; for(i=0;i<64;i++) t[i] = x[i]; barrett_reduce(r, t); } static void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) { int i; for(i=0;i<32;i++) r[i] = x->v[i]; } static void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) { int i, carry; for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; for(i=0;i<31;i++) { carry = r->v[i] >> 8; r->v[i+1] += carry; r->v[i] &= 0xff; } sc25519_reduce_add_sub(r); } static void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) { int i,j,carry; crypto_uint32 t[64]; for(i=0;i<64;i++)t[i] = 0; for(i=0;i<32;i++) for(j=0;j<32;j++) t[i+j] += x->v[i] * y->v[j]; /* Reduce coefficients */ for(i=0;i<63;i++) { carry = t[i] >> 8; t[i+1] += carry; t[i] &= 0xff; } barrett_reduce(r, t); } static void sc25519_window3(signed char r[85], const sc25519 *s) { char carry; int i; for(i=0;i<10;i++) { r[8*i+0] = s->v[3*i+0] & 7; r[8*i+1] = (s->v[3*i+0] >> 3) & 7; r[8*i+2] = (s->v[3*i+0] >> 6) & 7; r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; r[8*i+3] = (s->v[3*i+1] >> 1) & 7; r[8*i+4] = (s->v[3*i+1] >> 4) & 7; r[8*i+5] = (s->v[3*i+1] >> 7) & 7; r[8*i+5] ^= (s->v[3*i+2] << 1) & 7; r[8*i+6] = (s->v[3*i+2] >> 2) & 7; r[8*i+7] = (s->v[3*i+2] >> 5) & 7; } r[8*i+0] = s->v[3*i+0] & 7; r[8*i+1] = (s->v[3*i+0] >> 3) & 7; r[8*i+2] = (s->v[3*i+0] >> 6) & 7; r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; r[8*i+3] = (s->v[3*i+1] >> 1) & 7; r[8*i+4] = (s->v[3*i+1] >> 4) & 7; /* Making it signed */ carry = 0; for(i=0;i<84;i++) { r[i] += carry; r[i+1] += r[i] >> 3; r[i] &= 7; carry = r[i] >> 2; r[i] -= carry<<3; } r[84] += carry; } static void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) { int i; for(i=0;i<31;i++) { r[4*i] = ( s1->v[i] & 3) ^ (( s2->v[i] & 3) << 2); r[4*i+1] = ((s1->v[i] >> 2) & 3) ^ (((s2->v[i] >> 2) & 3) << 2); r[4*i+2] = ((s1->v[i] >> 4) & 3) ^ (((s2->v[i] >> 4) & 3) << 2); r[4*i+3] = ((s1->v[i] >> 6) & 3) ^ (((s2->v[i] >> 6) & 3) << 2); } r[124] = ( s1->v[31] & 3) ^ (( s2->v[31] & 3) << 2); r[125] = ((s1->v[31] >> 2) & 3) ^ (((s2->v[31] >> 2) & 3) << 2); r[126] = ((s1->v[31] >> 4) & 3) ^ (((s2->v[31] >> 4) & 3) << 2); } /* from supercop-20221122/crypto_sign/ed25519/ref/ge25519.h */ #ifndef GE25519_H #define GE25519_H #define ge25519 crypto_sign_ed25519_ref_ge25519 #define ge25519_base crypto_sign_ed25519_ref_ge25519_base #define ge25519_unpackneg_vartime crypto_sign_ed25519_ref_unpackneg_vartime #define ge25519_pack crypto_sign_ed25519_ref_pack #define ge25519_isneutral_vartime crypto_sign_ed25519_ref_isneutral_vartime #define ge25519_double_scalarmult_vartime crypto_sign_ed25519_ref_double_scalarmult_vartime #define ge25519_scalarmult_base crypto_sign_ed25519_ref_scalarmult_base typedef struct { fe25519 x; fe25519 y; fe25519 z; fe25519 t; } ge25519; const ge25519 ge25519_base; int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]); static void ge25519_pack(unsigned char r[32], const ge25519 *p); int ge25519_isneutral_vartime(const ge25519 *p); static void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25519 *s1, const ge25519 *p2, const sc25519 *s2); static void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s); #endif /* from supercop-20221122/crypto_sign/ed25519/ref/ge25519.c */ /* * Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2 * with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555 * Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960); */ /* d */ static const fe25519 ge25519_ecd = {{0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, 0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52}}; /* 2*d */ static const fe25519 ge25519_ec2d = {{0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00, 0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24}}; /* sqrt(-1) */ static const fe25519 ge25519_sqrtm1 = {{0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F, 0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B}}; #define ge25519_p3 ge25519 typedef struct { fe25519 x; fe25519 z; fe25519 y; fe25519 t; } ge25519_p1p1; typedef struct { fe25519 x; fe25519 y; fe25519 z; } ge25519_p2; typedef struct { fe25519 x; fe25519 y; } ge25519_aff; /* Packed coordinates of the base point */ const ge25519 ge25519_base = {{{0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}}, {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20, 0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67}}}; /* Multiples of the base point in affine representation */ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}} , {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}}, {{{0x0e, 0xce, 0x43, 0x28, 0x4e, 0xa1, 0xc5, 0x83, 0x5f, 0xa4, 0xd7, 0x15, 0x45, 0x8e, 0x0d, 0x08, 0xac, 0xe7, 0x33, 0x18, 0x7d, 0x3b, 0x04, 0x3d, 0x6c, 0x04, 0x5a, 0x9f, 0x4c, 0x38, 0xab, 0x36}} , {{0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0x0e, 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97, 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22}}}, {{{0x5c, 0xe2, 0xf8, 0xd3, 0x5f, 0x48, 0x62, 0xac, 0x86, 0x48, 0x62, 0x81, 0x19, 0x98, 0x43, 0x63, 0x3a, 0xc8, 0xda, 0x3e, 0x74, 0xae, 0xf4, 0x1f, 0x49, 0x8f, 0x92, 0x22, 0x4a, 0x9c, 0xae, 0x67}} , {{0xd4, 0xb4, 0xf5, 0x78, 0x48, 0x68, 0xc3, 0x02, 0x04, 0x03, 0x24, 0x67, 0x17, 0xec, 0x16, 0x9f, 0xf7, 0x9e, 0x26, 0x60, 0x8e, 0xa1, 0x26, 0xa1, 0xab, 0x69, 0xee, 0x77, 0xd1, 0xb1, 0x67, 0x12}}}, {{{0x70, 0xf8, 0xc9, 0xc4, 0x57, 0xa6, 0x3a, 0x49, 0x47, 0x15, 0xce, 0x93, 0xc1, 0x9e, 0x73, 0x1a, 0xf9, 0x20, 0x35, 0x7a, 0xb8, 0xd4, 0x25, 0x83, 0x46, 0xf1, 0xcf, 0x56, 0xdb, 0xa8, 0x3d, 0x20}} , {{0x2f, 0x11, 0x32, 0xca, 0x61, 0xab, 0x38, 0xdf, 0xf0, 0x0f, 0x2f, 0xea, 0x32, 0x28, 0xf2, 0x4c, 0x6c, 0x71, 0xd5, 0x80, 0x85, 0xb8, 0x0e, 0x47, 0xe1, 0x95, 0x15, 0xcb, 0x27, 0xe8, 0xd0, 0x47}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc8, 0x84, 0xa5, 0x08, 0xbc, 0xfd, 0x87, 0x3b, 0x99, 0x8b, 0x69, 0x80, 0x7b, 0xc6, 0x3a, 0xeb, 0x93, 0xcf, 0x4e, 0xf8, 0x5c, 0x2d, 0x86, 0x42, 0xb6, 0x71, 0xd7, 0x97, 0x5f, 0xe1, 0x42, 0x67}} , {{0xb4, 0xb9, 0x37, 0xfc, 0xa9, 0x5b, 0x2f, 0x1e, 0x93, 0xe4, 0x1e, 0x62, 0xfc, 0x3c, 0x78, 0x81, 0x8f, 0xf3, 0x8a, 0x66, 0x09, 0x6f, 0xad, 0x6e, 0x79, 0x73, 0xe5, 0xc9, 0x00, 0x06, 0xd3, 0x21}}}, {{{0xf8, 0xf9, 0x28, 0x6c, 0x6d, 0x59, 0xb2, 0x59, 0x74, 0x23, 0xbf, 0xe7, 0x33, 0x8d, 0x57, 0x09, 0x91, 0x9c, 0x24, 0x08, 0x15, 0x2b, 0xe2, 0xb8, 0xee, 0x3a, 0xe5, 0x27, 0x06, 0x86, 0xa4, 0x23}} , {{0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0, 0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f, 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70}}}, {{{0x81, 0x6b, 0x88, 0xe8, 0x1e, 0xc7, 0x77, 0x96, 0x0e, 0xa1, 0xa9, 0x52, 0xe0, 0xd8, 0x0e, 0x61, 0x9e, 0x79, 0x2d, 0x95, 0x9c, 0x8d, 0x96, 0xe0, 0x06, 0x40, 0x5d, 0x87, 0x28, 0x5f, 0x98, 0x70}} , {{0xf1, 0x79, 0x7b, 0xed, 0x4f, 0x44, 0xb2, 0xe7, 0x08, 0x0d, 0xc2, 0x08, 0x12, 0xd2, 0x9f, 0xdf, 0xcd, 0x93, 0x20, 0x8a, 0xcf, 0x33, 0xca, 0x6d, 0x89, 0xb9, 0x77, 0xc8, 0x93, 0x1b, 0x4e, 0x60}}}, {{{0x26, 0x4f, 0x7e, 0x97, 0xf6, 0x40, 0xdd, 0x4f, 0xfc, 0x52, 0x78, 0xf9, 0x90, 0x31, 0x03, 0xe6, 0x7d, 0x56, 0x39, 0x0b, 0x1d, 0x56, 0x82, 0x85, 0xf9, 0x1a, 0x42, 0x17, 0x69, 0x6c, 0xcf, 0x39}} , {{0x69, 0xd2, 0x06, 0x3a, 0x4f, 0x39, 0x2d, 0xf9, 0x38, 0x40, 0x8c, 0x4c, 0xe7, 0x05, 0x12, 0xb4, 0x78, 0x8b, 0xf8, 0xc0, 0xec, 0x93, 0xde, 0x7a, 0x6b, 0xce, 0x2c, 0xe1, 0x0e, 0xa9, 0x34, 0x44}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0b, 0xa4, 0x3c, 0xb0, 0x0f, 0x7a, 0x51, 0xf1, 0x78, 0xd6, 0xd9, 0x6a, 0xfd, 0x46, 0xe8, 0xb8, 0xa8, 0x79, 0x1d, 0x87, 0xf9, 0x90, 0xf2, 0x9c, 0x13, 0x29, 0xf8, 0x0b, 0x20, 0x64, 0xfa, 0x05}} , {{0x26, 0x09, 0xda, 0x17, 0xaf, 0x95, 0xd6, 0xfb, 0x6a, 0x19, 0x0d, 0x6e, 0x5e, 0x12, 0xf1, 0x99, 0x4c, 0xaa, 0xa8, 0x6f, 0x79, 0x86, 0xf4, 0x72, 0x28, 0x00, 0x26, 0xf9, 0xea, 0x9e, 0x19, 0x3d}}}, {{{0x87, 0xdd, 0xcf, 0xf0, 0x5b, 0x49, 0xa2, 0x5d, 0x40, 0x7a, 0x23, 0x26, 0xa4, 0x7a, 0x83, 0x8a, 0xb7, 0x8b, 0xd2, 0x1a, 0xbf, 0xea, 0x02, 0x24, 0x08, 0x5f, 0x7b, 0xa9, 0xb1, 0xbe, 0x9d, 0x37}} , {{0xfc, 0x86, 0x4b, 0x08, 0xee, 0xe7, 0xa0, 0xfd, 0x21, 0x45, 0x09, 0x34, 0xc1, 0x61, 0x32, 0x23, 0xfc, 0x9b, 0x55, 0x48, 0x53, 0x99, 0xf7, 0x63, 0xd0, 0x99, 0xce, 0x01, 0xe0, 0x9f, 0xeb, 0x28}}}, {{{0x47, 0xfc, 0xab, 0x5a, 0x17, 0xf0, 0x85, 0x56, 0x3a, 0x30, 0x86, 0x20, 0x28, 0x4b, 0x8e, 0x44, 0x74, 0x3a, 0x6e, 0x02, 0xf1, 0x32, 0x8f, 0x9f, 0x3f, 0x08, 0x35, 0xe9, 0xca, 0x16, 0x5f, 0x6e}} , {{0x1c, 0x59, 0x1c, 0x65, 0x5d, 0x34, 0xa4, 0x09, 0xcd, 0x13, 0x9c, 0x70, 0x7d, 0xb1, 0x2a, 0xc5, 0x88, 0xaf, 0x0b, 0x60, 0xc7, 0x9f, 0x34, 0x8d, 0xd6, 0xb7, 0x7f, 0xea, 0x78, 0x65, 0x8d, 0x77}}}, {{{0x56, 0xa5, 0xc2, 0x0c, 0xdd, 0xbc, 0xb8, 0x20, 0x6d, 0x57, 0x61, 0xb5, 0xfb, 0x78, 0xb5, 0xd4, 0x49, 0x54, 0x90, 0x26, 0xc1, 0xcb, 0xe9, 0xe6, 0xbf, 0xec, 0x1d, 0x4e, 0xed, 0x07, 0x7e, 0x5e}} , {{0xc7, 0xf6, 0x6c, 0x56, 0x31, 0x20, 0x14, 0x0e, 0xa8, 0xd9, 0x27, 0xc1, 0x9a, 0x3d, 0x1b, 0x7d, 0x0e, 0x26, 0xd3, 0x81, 0xaa, 0xeb, 0xf5, 0x6b, 0x79, 0x02, 0xf1, 0x51, 0x5c, 0x75, 0x55, 0x0f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0a, 0x34, 0xcd, 0x82, 0x3c, 0x33, 0x09, 0x54, 0xd2, 0x61, 0x39, 0x30, 0x9b, 0xfd, 0xef, 0x21, 0x26, 0xd4, 0x70, 0xfa, 0xee, 0xf9, 0x31, 0x33, 0x73, 0x84, 0xd0, 0xb3, 0x81, 0xbf, 0xec, 0x2e}} , {{0xe8, 0x93, 0x8b, 0x00, 0x64, 0xf7, 0x9c, 0xb8, 0x74, 0xe0, 0xe6, 0x49, 0x48, 0x4d, 0x4d, 0x48, 0xb6, 0x19, 0xa1, 0x40, 0xb7, 0xd9, 0x32, 0x41, 0x7c, 0x82, 0x37, 0xa1, 0x2d, 0xdc, 0xd2, 0x54}}}, {{{0x68, 0x2b, 0x4a, 0x5b, 0xd5, 0xc7, 0x51, 0x91, 0x1d, 0xe1, 0x2a, 0x4b, 0xc4, 0x47, 0xf1, 0xbc, 0x7a, 0xb3, 0xcb, 0xc8, 0xb6, 0x7c, 0xac, 0x90, 0x05, 0xfd, 0xf3, 0xf9, 0x52, 0x3a, 0x11, 0x6b}} , {{0x3d, 0xc1, 0x27, 0xf3, 0x59, 0x43, 0x95, 0x90, 0xc5, 0x96, 0x79, 0xf5, 0xf4, 0x95, 0x65, 0x29, 0x06, 0x9c, 0x51, 0x05, 0x18, 0xda, 0xb8, 0x2e, 0x79, 0x7e, 0x69, 0x59, 0x71, 0x01, 0xeb, 0x1a}}}, {{{0x15, 0x06, 0x49, 0xb6, 0x8a, 0x3c, 0xea, 0x2f, 0x34, 0x20, 0x14, 0xc3, 0xaa, 0xd6, 0xaf, 0x2c, 0x3e, 0xbd, 0x65, 0x20, 0xe2, 0x4d, 0x4b, 0x3b, 0xeb, 0x9f, 0x4a, 0xc3, 0xad, 0xa4, 0x3b, 0x60}} , {{0xbc, 0x58, 0xe6, 0xc0, 0x95, 0x2a, 0x2a, 0x81, 0x9a, 0x7a, 0xf3, 0xd2, 0x06, 0xbe, 0x48, 0xbc, 0x0c, 0xc5, 0x46, 0xe0, 0x6a, 0xd4, 0xac, 0x0f, 0xd9, 0xcc, 0x82, 0x34, 0x2c, 0xaf, 0xdb, 0x1f}}}, {{{0xf7, 0x17, 0x13, 0xbd, 0xfb, 0xbc, 0xd2, 0xec, 0x45, 0xb3, 0x15, 0x31, 0xe9, 0xaf, 0x82, 0x84, 0x3d, 0x28, 0xc6, 0xfc, 0x11, 0xf5, 0x41, 0xb5, 0x8b, 0xd3, 0x12, 0x76, 0x52, 0xe7, 0x1a, 0x3c}} , {{0x4e, 0x36, 0x11, 0x07, 0xa2, 0x15, 0x20, 0x51, 0xc4, 0x2a, 0xc3, 0x62, 0x8b, 0x5e, 0x7f, 0xa6, 0x0f, 0xf9, 0x45, 0x85, 0x6c, 0x11, 0x86, 0xb7, 0x7e, 0xe5, 0xd7, 0xf9, 0xc3, 0x91, 0x1c, 0x05}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xea, 0xd6, 0xde, 0x29, 0x3a, 0x00, 0xb9, 0x02, 0x59, 0xcb, 0x26, 0xc4, 0xba, 0x99, 0xb1, 0x97, 0x2f, 0x8e, 0x00, 0x92, 0x26, 0x4f, 0x52, 0xeb, 0x47, 0x1b, 0x89, 0x8b, 0x24, 0xc0, 0x13, 0x7d}} , {{0xd5, 0x20, 0x5b, 0x80, 0xa6, 0x80, 0x20, 0x95, 0xc3, 0xe9, 0x9f, 0x8e, 0x87, 0x9e, 0x1e, 0x9e, 0x7a, 0xc7, 0xcc, 0x75, 0x6c, 0xa5, 0xf1, 0x91, 0x1a, 0xa8, 0x01, 0x2c, 0xab, 0x76, 0xa9, 0x59}}}, {{{0xde, 0xc9, 0xb1, 0x31, 0x10, 0x16, 0xaa, 0x35, 0x14, 0x6a, 0xd4, 0xb5, 0x34, 0x82, 0x71, 0xd2, 0x4a, 0x5d, 0x9a, 0x1f, 0x53, 0x26, 0x3c, 0xe5, 0x8e, 0x8d, 0x33, 0x7f, 0xff, 0xa9, 0xd5, 0x17}} , {{0x89, 0xaf, 0xf6, 0xa4, 0x64, 0xd5, 0x10, 0xe0, 0x1d, 0xad, 0xef, 0x44, 0xbd, 0xda, 0x83, 0xac, 0x7a, 0xa8, 0xf0, 0x1c, 0x07, 0xf9, 0xc3, 0x43, 0x6c, 0x3f, 0xb7, 0xd3, 0x87, 0x22, 0x02, 0x73}}}, {{{0x64, 0x1d, 0x49, 0x13, 0x2f, 0x71, 0xec, 0x69, 0x87, 0xd0, 0x42, 0xee, 0x13, 0xec, 0xe3, 0xed, 0x56, 0x7b, 0xbf, 0xbd, 0x8c, 0x2f, 0x7d, 0x7b, 0x9d, 0x28, 0xec, 0x8e, 0x76, 0x2f, 0x6f, 0x08}} , {{0x22, 0xf5, 0x5f, 0x4d, 0x15, 0xef, 0xfc, 0x4e, 0x57, 0x03, 0x36, 0x89, 0xf0, 0xeb, 0x5b, 0x91, 0xd6, 0xe2, 0xca, 0x01, 0xa5, 0xee, 0x52, 0xec, 0xa0, 0x3c, 0x8f, 0x33, 0x90, 0x5a, 0x94, 0x72}}}, {{{0x8a, 0x4b, 0xe7, 0x38, 0xbc, 0xda, 0xc2, 0xb0, 0x85, 0xe1, 0x4a, 0xfe, 0x2d, 0x44, 0x84, 0xcb, 0x20, 0x6b, 0x2d, 0xbf, 0x11, 0x9c, 0xd7, 0xbe, 0xd3, 0x3e, 0x5f, 0xbf, 0x68, 0xbc, 0xa8, 0x07}} , {{0x01, 0x89, 0x28, 0x22, 0x6a, 0x78, 0xaa, 0x29, 0x03, 0xc8, 0x74, 0x95, 0x03, 0x3e, 0xdc, 0xbd, 0x07, 0x13, 0xa8, 0xa2, 0x20, 0x2d, 0xb3, 0x18, 0x70, 0x42, 0xfd, 0x7a, 0xc4, 0xd7, 0x49, 0x72}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x02, 0xff, 0x32, 0x2b, 0x5c, 0x93, 0x54, 0x32, 0xe8, 0x57, 0x54, 0x1a, 0x8b, 0x33, 0x60, 0x65, 0xd3, 0x67, 0xa4, 0xc1, 0x26, 0xc4, 0xa4, 0x34, 0x1f, 0x9b, 0xa7, 0xa9, 0xf4, 0xd9, 0x4f, 0x5b}} , {{0x46, 0x8d, 0xb0, 0x33, 0x54, 0x26, 0x5b, 0x68, 0xdf, 0xbb, 0xc5, 0xec, 0xc2, 0xf9, 0x3c, 0x5a, 0x37, 0xc1, 0x8e, 0x27, 0x47, 0xaa, 0x49, 0x5a, 0xf8, 0xfb, 0x68, 0x04, 0x23, 0xd1, 0xeb, 0x40}}}, {{{0x65, 0xa5, 0x11, 0x84, 0x8a, 0x67, 0x9d, 0x9e, 0xd1, 0x44, 0x68, 0x7a, 0x34, 0xe1, 0x9f, 0xa3, 0x54, 0xcd, 0x07, 0xca, 0x79, 0x1f, 0x54, 0x2f, 0x13, 0x70, 0x4e, 0xee, 0xa2, 0xfa, 0xe7, 0x5d}} , {{0x36, 0xec, 0x54, 0xf8, 0xce, 0xe4, 0x85, 0xdf, 0xf6, 0x6f, 0x1d, 0x90, 0x08, 0xbc, 0xe8, 0xc0, 0x92, 0x2d, 0x43, 0x6b, 0x92, 0xa9, 0x8e, 0xab, 0x0a, 0x2e, 0x1c, 0x1e, 0x64, 0x23, 0x9f, 0x2c}}}, {{{0xa7, 0xd6, 0x2e, 0xd5, 0xcc, 0xd4, 0xcb, 0x5a, 0x3b, 0xa7, 0xf9, 0x46, 0x03, 0x1d, 0xad, 0x2b, 0x34, 0x31, 0x90, 0x00, 0x46, 0x08, 0x82, 0x14, 0xc4, 0xe0, 0x9c, 0xf0, 0xe3, 0x55, 0x43, 0x31}} , {{0x60, 0xd6, 0xdd, 0x78, 0xe6, 0xd4, 0x22, 0x42, 0x1f, 0x00, 0xf9, 0xb1, 0x6a, 0x63, 0xe2, 0x92, 0x59, 0xd1, 0x1a, 0xb7, 0x00, 0x54, 0x29, 0xc9, 0xc1, 0xf6, 0x6f, 0x7a, 0xc5, 0x3c, 0x5f, 0x65}}}, {{{0x27, 0x4f, 0xd0, 0x72, 0xb1, 0x11, 0x14, 0x27, 0x15, 0x94, 0x48, 0x81, 0x7e, 0x74, 0xd8, 0x32, 0xd5, 0xd1, 0x11, 0x28, 0x60, 0x63, 0x36, 0x32, 0x37, 0xb5, 0x13, 0x1c, 0xa0, 0x37, 0xe3, 0x74}} , {{0xf1, 0x25, 0x4e, 0x11, 0x96, 0x67, 0xe6, 0x1c, 0xc2, 0xb2, 0x53, 0xe2, 0xda, 0x85, 0xee, 0xb2, 0x9f, 0x59, 0xf3, 0xba, 0xbd, 0xfa, 0xcf, 0x6e, 0xf9, 0xda, 0xa4, 0xb3, 0x02, 0x8f, 0x64, 0x08}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x34, 0x94, 0xf2, 0x64, 0x54, 0x47, 0x37, 0x07, 0x40, 0x8a, 0x20, 0xba, 0x4a, 0x55, 0xd7, 0x3f, 0x47, 0xba, 0x25, 0x23, 0x14, 0xb0, 0x2c, 0xe8, 0x55, 0xa8, 0xa6, 0xef, 0x51, 0xbd, 0x6f, 0x6a}} , {{0x71, 0xd6, 0x16, 0x76, 0xb2, 0x06, 0xea, 0x79, 0xf5, 0xc4, 0xc3, 0x52, 0x7e, 0x61, 0xd1, 0xe1, 0xad, 0x70, 0x78, 0x1d, 0x16, 0x11, 0xf8, 0x7c, 0x2b, 0xfc, 0x55, 0x9f, 0x52, 0xf8, 0xf5, 0x16}}}, {{{0x34, 0x96, 0x9a, 0xf6, 0xc5, 0xe0, 0x14, 0x03, 0x24, 0x0e, 0x4c, 0xad, 0x9e, 0x9a, 0x70, 0x23, 0x96, 0xb2, 0xf1, 0x2e, 0x9d, 0xc3, 0x32, 0x9b, 0x54, 0xa5, 0x73, 0xde, 0x88, 0xb1, 0x3e, 0x24}} , {{0xf6, 0xe2, 0x4c, 0x1f, 0x5b, 0xb2, 0xaf, 0x82, 0xa5, 0xcf, 0x81, 0x10, 0x04, 0xef, 0xdb, 0xa2, 0xcc, 0x24, 0xb2, 0x7e, 0x0b, 0x7a, 0xeb, 0x01, 0xd8, 0x52, 0xf4, 0x51, 0x89, 0x29, 0x79, 0x37}}}, {{{0x74, 0xde, 0x12, 0xf3, 0x68, 0xb7, 0x66, 0xc3, 0xee, 0x68, 0xdc, 0x81, 0xb5, 0x55, 0x99, 0xab, 0xd9, 0x28, 0x63, 0x6d, 0x8b, 0x40, 0x69, 0x75, 0x6c, 0xcd, 0x5c, 0x2a, 0x7e, 0x32, 0x7b, 0x29}} , {{0x02, 0xcc, 0x22, 0x74, 0x4d, 0x19, 0x07, 0xc0, 0xda, 0xb5, 0x76, 0x51, 0x2a, 0xaa, 0xa6, 0x0a, 0x5f, 0x26, 0xd4, 0xbc, 0xaf, 0x48, 0x88, 0x7f, 0x02, 0xbc, 0xf2, 0xe1, 0xcf, 0xe9, 0xdd, 0x15}}}, {{{0xed, 0xb5, 0x9a, 0x8c, 0x9a, 0xdd, 0x27, 0xf4, 0x7f, 0x47, 0xd9, 0x52, 0xa7, 0xcd, 0x65, 0xa5, 0x31, 0x22, 0xed, 0xa6, 0x63, 0x5b, 0x80, 0x4a, 0xad, 0x4d, 0xed, 0xbf, 0xee, 0x49, 0xb3, 0x06}} , {{0xf8, 0x64, 0x8b, 0x60, 0x90, 0xe9, 0xde, 0x44, 0x77, 0xb9, 0x07, 0x36, 0x32, 0xc2, 0x50, 0xf5, 0x65, 0xdf, 0x48, 0x4c, 0x37, 0xaa, 0x68, 0xab, 0x9a, 0x1f, 0x3e, 0xff, 0x89, 0x92, 0xa0, 0x07}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x7d, 0x4f, 0x9c, 0x19, 0xc0, 0x4a, 0x31, 0xec, 0xf9, 0xaa, 0xeb, 0xb2, 0x16, 0x9c, 0xa3, 0x66, 0x5f, 0xd1, 0xd4, 0xed, 0xb8, 0x92, 0x1c, 0xab, 0xda, 0xea, 0xd9, 0x57, 0xdf, 0x4c, 0x2a, 0x48}} , {{0x4b, 0xb0, 0x4e, 0x6e, 0x11, 0x3b, 0x51, 0xbd, 0x6a, 0xfd, 0xe4, 0x25, 0xa5, 0x5f, 0x11, 0x3f, 0x98, 0x92, 0x51, 0x14, 0xc6, 0x5f, 0x3c, 0x0b, 0xa8, 0xf7, 0xc2, 0x81, 0x43, 0xde, 0x91, 0x73}}}, {{{0x3c, 0x8f, 0x9f, 0x33, 0x2a, 0x1f, 0x43, 0x33, 0x8f, 0x68, 0xff, 0x1f, 0x3d, 0x73, 0x6b, 0xbf, 0x68, 0xcc, 0x7d, 0x13, 0x6c, 0x24, 0x4b, 0xcc, 0x4d, 0x24, 0x0d, 0xfe, 0xde, 0x86, 0xad, 0x3b}} , {{0x79, 0x51, 0x81, 0x01, 0xdc, 0x73, 0x53, 0xe0, 0x6e, 0x9b, 0xea, 0x68, 0x3f, 0x5c, 0x14, 0x84, 0x53, 0x8d, 0x4b, 0xc0, 0x9f, 0x9f, 0x89, 0x2b, 0x8c, 0xba, 0x86, 0xfa, 0xf2, 0xcd, 0xe3, 0x2d}}}, {{{0x06, 0xf9, 0x29, 0x5a, 0xdb, 0x3d, 0x84, 0x52, 0xab, 0xcc, 0x6b, 0x60, 0x9d, 0xb7, 0x4a, 0x0e, 0x36, 0x63, 0x91, 0xad, 0xa0, 0x95, 0xb0, 0x97, 0x89, 0x4e, 0xcf, 0x7d, 0x3c, 0xe5, 0x7c, 0x28}} , {{0x2e, 0x69, 0x98, 0xfd, 0xc6, 0xbd, 0xcc, 0xca, 0xdf, 0x9a, 0x44, 0x7e, 0x9d, 0xca, 0x89, 0x6d, 0xbf, 0x27, 0xc2, 0xf8, 0xcd, 0x46, 0x00, 0x2b, 0xb5, 0x58, 0x4e, 0xb7, 0x89, 0x09, 0xe9, 0x2d}}}, {{{0x54, 0xbe, 0x75, 0xcb, 0x05, 0xb0, 0x54, 0xb7, 0xe7, 0x26, 0x86, 0x4a, 0xfc, 0x19, 0xcf, 0x27, 0x46, 0xd4, 0x22, 0x96, 0x5a, 0x11, 0xe8, 0xd5, 0x1b, 0xed, 0x71, 0xc5, 0x5d, 0xc8, 0xaf, 0x45}} , {{0x40, 0x7b, 0x77, 0x57, 0x49, 0x9e, 0x80, 0x39, 0x23, 0xee, 0x81, 0x0b, 0x22, 0xcf, 0xdb, 0x7a, 0x2f, 0x14, 0xb8, 0x57, 0x8f, 0xa1, 0x39, 0x1e, 0x77, 0xfc, 0x0b, 0xa6, 0xbf, 0x8a, 0x0c, 0x6c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x77, 0x3a, 0xd4, 0xd8, 0x27, 0xcf, 0xe8, 0xa1, 0x72, 0x9d, 0xca, 0xdd, 0x0d, 0x96, 0xda, 0x79, 0xed, 0x56, 0x42, 0x15, 0x60, 0xc7, 0x1c, 0x6b, 0x26, 0x30, 0xf6, 0x6a, 0x95, 0x67, 0xf3, 0x0a}} , {{0xc5, 0x08, 0xa4, 0x2b, 0x2f, 0xbd, 0x31, 0x81, 0x2a, 0xa6, 0xb6, 0xe4, 0x00, 0x91, 0xda, 0x3d, 0xb2, 0xb0, 0x96, 0xce, 0x8a, 0xd2, 0x8d, 0x70, 0xb3, 0xd3, 0x34, 0x01, 0x90, 0x8d, 0x10, 0x21}}}, {{{0x33, 0x0d, 0xe7, 0xba, 0x4f, 0x07, 0xdf, 0x8d, 0xea, 0x7d, 0xa0, 0xc5, 0xd6, 0xb1, 0xb0, 0xe5, 0x57, 0x1b, 0x5b, 0xf5, 0x45, 0x13, 0x14, 0x64, 0x5a, 0xeb, 0x5c, 0xfc, 0x54, 0x01, 0x76, 0x2b}} , {{0x02, 0x0c, 0xc2, 0xaf, 0x96, 0x36, 0xfe, 0x4a, 0xe2, 0x54, 0x20, 0x6a, 0xeb, 0xb2, 0x9f, 0x62, 0xd7, 0xce, 0xa2, 0x3f, 0x20, 0x11, 0x34, 0x37, 0xe0, 0x42, 0xed, 0x6f, 0xf9, 0x1a, 0xc8, 0x7d}}}, {{{0xd8, 0xb9, 0x11, 0xe8, 0x36, 0x3f, 0x42, 0xc1, 0xca, 0xdc, 0xd3, 0xf1, 0xc8, 0x23, 0x3d, 0x4f, 0x51, 0x7b, 0x9d, 0x8d, 0xd8, 0xe4, 0xa0, 0xaa, 0xf3, 0x04, 0xd6, 0x11, 0x93, 0xc8, 0x35, 0x45}} , {{0x61, 0x36, 0xd6, 0x08, 0x90, 0xbf, 0xa7, 0x7a, 0x97, 0x6c, 0x0f, 0x84, 0xd5, 0x33, 0x2d, 0x37, 0xc9, 0x6a, 0x80, 0x90, 0x3d, 0x0a, 0xa2, 0xaa, 0xe1, 0xb8, 0x84, 0xba, 0x61, 0x36, 0xdd, 0x69}}}, {{{0x6b, 0xdb, 0x5b, 0x9c, 0xc6, 0x92, 0xbc, 0x23, 0xaf, 0xc5, 0xb8, 0x75, 0xf8, 0x42, 0xfa, 0xd6, 0xb6, 0x84, 0x94, 0x63, 0x98, 0x93, 0x48, 0x78, 0x38, 0xcd, 0xbb, 0x18, 0x34, 0xc3, 0xdb, 0x67}} , {{0x96, 0xf3, 0x3a, 0x09, 0x56, 0xb0, 0x6f, 0x7c, 0x51, 0x1e, 0x1b, 0x39, 0x48, 0xea, 0xc9, 0x0c, 0x25, 0xa2, 0x7a, 0xca, 0xe7, 0x92, 0xfc, 0x59, 0x30, 0xa3, 0x89, 0x85, 0xdf, 0x6f, 0x43, 0x38}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x79, 0x84, 0x44, 0x19, 0xbd, 0xe9, 0x54, 0xc4, 0xc0, 0x6e, 0x2a, 0xa8, 0xa8, 0x9b, 0x43, 0xd5, 0x71, 0x22, 0x5f, 0xdc, 0x01, 0xfa, 0xdf, 0xb3, 0xb8, 0x47, 0x4b, 0x0a, 0xa5, 0x44, 0xea, 0x29}} , {{0x05, 0x90, 0x50, 0xaf, 0x63, 0x5f, 0x9d, 0x9e, 0xe1, 0x9d, 0x38, 0x97, 0x1f, 0x6c, 0xac, 0x30, 0x46, 0xb2, 0x6a, 0x19, 0xd1, 0x4b, 0xdb, 0xbb, 0x8c, 0xda, 0x2e, 0xab, 0xc8, 0x5a, 0x77, 0x6c}}}, {{{0x2b, 0xbe, 0xaf, 0xa1, 0x6d, 0x2f, 0x0b, 0xb1, 0x8f, 0xe3, 0xe0, 0x38, 0xcd, 0x0b, 0x41, 0x1b, 0x4a, 0x15, 0x07, 0xf3, 0x6f, 0xdc, 0xb8, 0xe9, 0xde, 0xb2, 0xa3, 0x40, 0x01, 0xa6, 0x45, 0x1e}} , {{0x76, 0x0a, 0xda, 0x8d, 0x2c, 0x07, 0x3f, 0x89, 0x7d, 0x04, 0xad, 0x43, 0x50, 0x6e, 0xd2, 0x47, 0xcb, 0x8a, 0xe6, 0x85, 0x1a, 0x24, 0xf3, 0xd2, 0x60, 0xfd, 0xdf, 0x73, 0xa4, 0x0d, 0x73, 0x0e}}}, {{{0xfd, 0x67, 0x6b, 0x71, 0x9b, 0x81, 0x53, 0x39, 0x39, 0xf4, 0xb8, 0xd5, 0xc3, 0x30, 0x9b, 0x3b, 0x7c, 0xa3, 0xf0, 0xd0, 0x84, 0x21, 0xd6, 0xbf, 0xb7, 0x4c, 0x87, 0x13, 0x45, 0x2d, 0xa7, 0x55}} , {{0x5d, 0x04, 0xb3, 0x40, 0x28, 0x95, 0x2d, 0x30, 0x83, 0xec, 0x5e, 0xe4, 0xff, 0x75, 0xfe, 0x79, 0x26, 0x9d, 0x1d, 0x36, 0xcd, 0x0a, 0x15, 0xd2, 0x24, 0x14, 0x77, 0x71, 0xd7, 0x8a, 0x1b, 0x04}}}, {{{0x5d, 0x93, 0xc9, 0xbe, 0xaa, 0x90, 0xcd, 0x9b, 0xfb, 0x73, 0x7e, 0xb0, 0x64, 0x98, 0x57, 0x44, 0x42, 0x41, 0xb1, 0xaf, 0xea, 0xc1, 0xc3, 0x22, 0xff, 0x60, 0x46, 0xcb, 0x61, 0x81, 0x70, 0x61}} , {{0x0d, 0x82, 0xb9, 0xfe, 0x21, 0xcd, 0xc4, 0xf5, 0x98, 0x0c, 0x4e, 0x72, 0xee, 0x87, 0x49, 0xf8, 0xa1, 0x95, 0xdf, 0x8f, 0x2d, 0xbd, 0x21, 0x06, 0x7c, 0x15, 0xe8, 0x12, 0x6d, 0x93, 0xd6, 0x38}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x91, 0xf7, 0x51, 0xd9, 0xef, 0x7d, 0x42, 0x01, 0x13, 0xe9, 0xb8, 0x7f, 0xa6, 0x49, 0x17, 0x64, 0x21, 0x80, 0x83, 0x2c, 0x63, 0x4c, 0x60, 0x09, 0x59, 0x91, 0x92, 0x77, 0x39, 0x51, 0xf4, 0x48}} , {{0x60, 0xd5, 0x22, 0x83, 0x08, 0x2f, 0xff, 0x99, 0x3e, 0x69, 0x6d, 0x88, 0xda, 0xe7, 0x5b, 0x52, 0x26, 0x31, 0x2a, 0xe5, 0x89, 0xde, 0x68, 0x90, 0xb6, 0x22, 0x5a, 0xbd, 0xd3, 0x85, 0x53, 0x31}}}, {{{0xd8, 0xce, 0xdc, 0xf9, 0x3c, 0x4b, 0xa2, 0x1d, 0x2c, 0x2f, 0x36, 0xbe, 0x7a, 0xfc, 0xcd, 0xbc, 0xdc, 0xf9, 0x30, 0xbd, 0xff, 0x05, 0xc7, 0xe4, 0x8e, 0x17, 0x62, 0xf8, 0x4d, 0xa0, 0x56, 0x79}} , {{0x82, 0xe7, 0xf6, 0xba, 0x53, 0x84, 0x0a, 0xa3, 0x34, 0xff, 0x3c, 0xa3, 0x6a, 0xa1, 0x37, 0xea, 0xdd, 0xb6, 0x95, 0xb3, 0x78, 0x19, 0x76, 0x1e, 0x55, 0x2f, 0x77, 0x2e, 0x7f, 0xc1, 0xea, 0x5e}}}, {{{0x83, 0xe1, 0x6e, 0xa9, 0x07, 0x33, 0x3e, 0x83, 0xff, 0xcb, 0x1c, 0x9f, 0xb1, 0xa3, 0xb4, 0xc9, 0xe1, 0x07, 0x97, 0xff, 0xf8, 0x23, 0x8f, 0xce, 0x40, 0xfd, 0x2e, 0x5e, 0xdb, 0x16, 0x43, 0x2d}} , {{0xba, 0x38, 0x02, 0xf7, 0x81, 0x43, 0x83, 0xa3, 0x20, 0x4f, 0x01, 0x3b, 0x8a, 0x04, 0x38, 0x31, 0xc6, 0x0f, 0xc8, 0xdf, 0xd7, 0xfa, 0x2f, 0x88, 0x3f, 0xfc, 0x0c, 0x76, 0xc4, 0xa6, 0x45, 0x72}}}, {{{0xbb, 0x0c, 0xbc, 0x6a, 0xa4, 0x97, 0x17, 0x93, 0x2d, 0x6f, 0xde, 0x72, 0x10, 0x1c, 0x08, 0x2c, 0x0f, 0x80, 0x32, 0x68, 0x27, 0xd4, 0xab, 0xdd, 0xc5, 0x58, 0x61, 0x13, 0x6d, 0x11, 0x1e, 0x4d}} , {{0x1a, 0xb9, 0xc9, 0x10, 0xfb, 0x1e, 0x4e, 0xf4, 0x84, 0x4b, 0x8a, 0x5e, 0x7b, 0x4b, 0xe8, 0x43, 0x8c, 0x8f, 0x00, 0xb5, 0x54, 0x13, 0xc5, 0x5c, 0xb6, 0x35, 0x4e, 0x9d, 0xe4, 0x5b, 0x41, 0x6d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x15, 0x7d, 0x12, 0x48, 0x82, 0x14, 0x42, 0xcd, 0x32, 0xd4, 0x4b, 0xc1, 0x72, 0x61, 0x2a, 0x8c, 0xec, 0xe2, 0xf8, 0x24, 0x45, 0x94, 0xe3, 0xbe, 0xdd, 0x67, 0xa8, 0x77, 0x5a, 0xae, 0x5b, 0x4b}} , {{0xcb, 0x77, 0x9a, 0x20, 0xde, 0xb8, 0x23, 0xd9, 0xa0, 0x0f, 0x8c, 0x7b, 0xa5, 0xcb, 0xae, 0xb6, 0xec, 0x42, 0x67, 0x0e, 0x58, 0xa4, 0x75, 0x98, 0x21, 0x71, 0x84, 0xb3, 0xe0, 0x76, 0x94, 0x73}}}, {{{0xdf, 0xfc, 0x69, 0x28, 0x23, 0x3f, 0x5b, 0xf8, 0x3b, 0x24, 0x37, 0xf3, 0x1d, 0xd5, 0x22, 0x6b, 0xd0, 0x98, 0xa8, 0x6c, 0xcf, 0xff, 0x06, 0xe1, 0x13, 0xdf, 0xb9, 0xc1, 0x0c, 0xa9, 0xbf, 0x33}} , {{0xd9, 0x81, 0xda, 0xb2, 0x4f, 0x82, 0x9d, 0x43, 0x81, 0x09, 0xf1, 0xd2, 0x01, 0xef, 0xac, 0xf4, 0x2d, 0x7d, 0x01, 0x09, 0xf1, 0xff, 0xa5, 0x9f, 0xe5, 0xca, 0x27, 0x63, 0xdb, 0x20, 0xb1, 0x53}}}, {{{0x67, 0x02, 0xe8, 0xad, 0xa9, 0x34, 0xd4, 0xf0, 0x15, 0x81, 0xaa, 0xc7, 0x4d, 0x87, 0x94, 0xea, 0x75, 0xe7, 0x4c, 0x94, 0x04, 0x0e, 0x69, 0x87, 0xe7, 0x51, 0x91, 0x10, 0x03, 0xc7, 0xbe, 0x56}} , {{0x32, 0xfb, 0x86, 0xec, 0x33, 0x6b, 0x2e, 0x51, 0x2b, 0xc8, 0xfa, 0x6c, 0x70, 0x47, 0x7e, 0xce, 0x05, 0x0c, 0x71, 0xf3, 0xb4, 0x56, 0xa6, 0xdc, 0xcc, 0x78, 0x07, 0x75, 0xd0, 0xdd, 0xb2, 0x6a}}}, {{{0xc6, 0xef, 0xb9, 0xc0, 0x2b, 0x22, 0x08, 0x1e, 0x71, 0x70, 0xb3, 0x35, 0x9c, 0x7a, 0x01, 0x92, 0x44, 0x9a, 0xf6, 0xb0, 0x58, 0x95, 0xc1, 0x9b, 0x02, 0xed, 0x2d, 0x7c, 0x34, 0x29, 0x49, 0x44}} , {{0x45, 0x62, 0x1d, 0x2e, 0xff, 0x2a, 0x1c, 0x21, 0xa4, 0x25, 0x7b, 0x0d, 0x8c, 0x15, 0x39, 0xfc, 0x8f, 0x7c, 0xa5, 0x7d, 0x1e, 0x25, 0xa3, 0x45, 0xd6, 0xab, 0xbd, 0xcb, 0xc5, 0x5e, 0x78, 0x77}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0xd3, 0x42, 0xed, 0x1d, 0x00, 0x3c, 0x15, 0x2c, 0x9c, 0x77, 0x81, 0xd2, 0x73, 0xd1, 0x06, 0xd5, 0xc4, 0x7f, 0x94, 0xbb, 0x92, 0x2d, 0x2c, 0x4b, 0x45, 0x4b, 0xe9, 0x2a, 0x89, 0x6b, 0x2b}} , {{0xd2, 0x0c, 0x88, 0xc5, 0x48, 0x4d, 0xea, 0x0d, 0x4a, 0xc9, 0x52, 0x6a, 0x61, 0x79, 0xe9, 0x76, 0xf3, 0x85, 0x52, 0x5c, 0x1b, 0x2c, 0xe1, 0xd6, 0xc4, 0x0f, 0x18, 0x0e, 0x4e, 0xf6, 0x1c, 0x7f}}}, {{{0xb4, 0x04, 0x2e, 0x42, 0xcb, 0x1f, 0x2b, 0x11, 0x51, 0x7b, 0x08, 0xac, 0xaa, 0x3e, 0x9e, 0x52, 0x60, 0xb7, 0xc2, 0x61, 0x57, 0x8c, 0x84, 0xd5, 0x18, 0xa6, 0x19, 0xfc, 0xb7, 0x75, 0x91, 0x1b}} , {{0xe8, 0x68, 0xca, 0x44, 0xc8, 0x38, 0x38, 0xcc, 0x53, 0x0a, 0x32, 0x35, 0xcc, 0x52, 0xcb, 0x0e, 0xf7, 0xc5, 0xe7, 0xec, 0x3d, 0x85, 0xcc, 0x58, 0xe2, 0x17, 0x47, 0xff, 0x9f, 0xa5, 0x30, 0x17}}}, {{{0xe3, 0xae, 0xc8, 0xc1, 0x71, 0x75, 0x31, 0x00, 0x37, 0x41, 0x5c, 0x0e, 0x39, 0xda, 0x73, 0xa0, 0xc7, 0x97, 0x36, 0x6c, 0x5b, 0xf2, 0xee, 0x64, 0x0a, 0x3d, 0x89, 0x1e, 0x1d, 0x49, 0x8c, 0x37}} , {{0x4c, 0xe6, 0xb0, 0xc1, 0xa5, 0x2a, 0x82, 0x09, 0x08, 0xad, 0x79, 0x9c, 0x56, 0xf6, 0xf9, 0xc1, 0xd7, 0x7c, 0x39, 0x7f, 0x93, 0xca, 0x11, 0x55, 0xbf, 0x07, 0x1b, 0x82, 0x29, 0x69, 0x95, 0x5c}}}, {{{0x87, 0xee, 0xa6, 0x56, 0x9e, 0xc2, 0x9a, 0x56, 0x24, 0x42, 0x85, 0x4d, 0x98, 0x31, 0x1e, 0x60, 0x4d, 0x87, 0x85, 0x04, 0xae, 0x46, 0x12, 0xf9, 0x8e, 0x7f, 0xe4, 0x7f, 0xf6, 0x1c, 0x37, 0x01}} , {{0x73, 0x4c, 0xb6, 0xc5, 0xc4, 0xe9, 0x6c, 0x85, 0x48, 0x4a, 0x5a, 0xac, 0xd9, 0x1f, 0x43, 0xf8, 0x62, 0x5b, 0xee, 0x98, 0x2a, 0x33, 0x8e, 0x79, 0xce, 0x61, 0x06, 0x35, 0xd8, 0xd7, 0xca, 0x71}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x72, 0xd3, 0xae, 0xa6, 0xca, 0x8f, 0xcd, 0xcc, 0x78, 0x8e, 0x19, 0x4d, 0xa7, 0xd2, 0x27, 0xe9, 0xa4, 0x3c, 0x16, 0x5b, 0x84, 0x80, 0xf9, 0xd0, 0xcc, 0x6a, 0x1e, 0xca, 0x1e, 0x67, 0xbd, 0x63}} , {{0x7b, 0x6e, 0x2a, 0xd2, 0x87, 0x48, 0xff, 0xa1, 0xca, 0xe9, 0x15, 0x85, 0xdc, 0xdb, 0x2c, 0x39, 0x12, 0x91, 0xa9, 0x20, 0xaa, 0x4f, 0x29, 0xf4, 0x15, 0x7a, 0xd2, 0xf5, 0x32, 0xcc, 0x60, 0x04}}}, {{{0xe5, 0x10, 0x47, 0x3b, 0xfa, 0x90, 0xfc, 0x30, 0xb5, 0xea, 0x6f, 0x56, 0x8f, 0xfb, 0x0e, 0xa7, 0x3b, 0xc8, 0xb2, 0xff, 0x02, 0x7a, 0x33, 0x94, 0x93, 0x2a, 0x03, 0xe0, 0x96, 0x3a, 0x6c, 0x0f}} , {{0x5a, 0x63, 0x67, 0xe1, 0x9b, 0x47, 0x78, 0x9f, 0x38, 0x79, 0xac, 0x97, 0x66, 0x1d, 0x5e, 0x51, 0xee, 0x24, 0x42, 0xe8, 0x58, 0x4b, 0x8a, 0x03, 0x75, 0x86, 0x37, 0x86, 0xe2, 0x97, 0x4e, 0x3d}}}, {{{0x3f, 0x75, 0x8e, 0xb4, 0xff, 0xd8, 0xdd, 0xd6, 0x37, 0x57, 0x9d, 0x6d, 0x3b, 0xbd, 0xd5, 0x60, 0x88, 0x65, 0x9a, 0xb9, 0x4a, 0x68, 0x84, 0xa2, 0x67, 0xdd, 0x17, 0x25, 0x97, 0x04, 0x8b, 0x5e}} , {{0xbb, 0x40, 0x5e, 0xbc, 0x16, 0x92, 0x05, 0xc4, 0xc0, 0x4e, 0x72, 0x90, 0x0e, 0xab, 0xcf, 0x8a, 0xed, 0xef, 0xb9, 0x2d, 0x3b, 0xf8, 0x43, 0x5b, 0xba, 0x2d, 0xeb, 0x2f, 0x52, 0xd2, 0xd1, 0x5a}}}, {{{0x40, 0xb4, 0xab, 0xe6, 0xad, 0x9f, 0x46, 0x69, 0x4a, 0xb3, 0x8e, 0xaa, 0xea, 0x9c, 0x8a, 0x20, 0x16, 0x5d, 0x8c, 0x13, 0xbd, 0xf6, 0x1d, 0xc5, 0x24, 0xbd, 0x90, 0x2a, 0x1c, 0xc7, 0x13, 0x3b}} , {{0x54, 0xdc, 0x16, 0x0d, 0x18, 0xbe, 0x35, 0x64, 0x61, 0x52, 0x02, 0x80, 0xaf, 0x05, 0xf7, 0xa6, 0x42, 0xd3, 0x8f, 0x2e, 0x79, 0x26, 0xa8, 0xbb, 0xb2, 0x17, 0x48, 0xb2, 0x7a, 0x0a, 0x89, 0x14}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x20, 0xa8, 0x88, 0xe3, 0x91, 0xc0, 0x6e, 0xbb, 0x8a, 0x27, 0x82, 0x51, 0x83, 0xb2, 0x28, 0xa9, 0x83, 0xeb, 0xa6, 0xa9, 0x4d, 0x17, 0x59, 0x22, 0x54, 0x00, 0x50, 0x45, 0xcb, 0x48, 0x4b, 0x18}} , {{0x33, 0x7c, 0xe7, 0x26, 0xba, 0x4d, 0x32, 0xfe, 0x53, 0xf4, 0xfa, 0x83, 0xe3, 0xa5, 0x79, 0x66, 0x73, 0xef, 0x80, 0x23, 0x68, 0xc2, 0x60, 0xdd, 0xa9, 0x33, 0xdc, 0x03, 0x7a, 0xe0, 0xe0, 0x3e}}}, {{{0x34, 0x5c, 0x13, 0xfb, 0xc0, 0xe3, 0x78, 0x2b, 0x54, 0x58, 0x22, 0x9b, 0x76, 0x81, 0x7f, 0x93, 0x9c, 0x25, 0x3c, 0xd2, 0xe9, 0x96, 0x21, 0x26, 0x08, 0xf5, 0xed, 0x95, 0x11, 0xae, 0x04, 0x5a}} , {{0xb9, 0xe8, 0xc5, 0x12, 0x97, 0x1f, 0x83, 0xfe, 0x3e, 0x94, 0x99, 0xd4, 0x2d, 0xf9, 0x52, 0x59, 0x5c, 0x82, 0xa6, 0xf0, 0x75, 0x7e, 0xe8, 0xec, 0xcc, 0xac, 0x18, 0x21, 0x09, 0x67, 0x66, 0x67}}}, {{{0xb3, 0x40, 0x29, 0xd1, 0xcb, 0x1b, 0x08, 0x9e, 0x9c, 0xb7, 0x53, 0xb9, 0x3b, 0x71, 0x08, 0x95, 0x12, 0x1a, 0x58, 0xaf, 0x7e, 0x82, 0x52, 0x43, 0x4f, 0x11, 0x39, 0xf4, 0x93, 0x1a, 0x26, 0x05}} , {{0x6e, 0x44, 0xa3, 0xf9, 0x64, 0xaf, 0xe7, 0x6d, 0x7d, 0xdf, 0x1e, 0xac, 0x04, 0xea, 0x3b, 0x5f, 0x9b, 0xe8, 0x24, 0x9d, 0x0e, 0xe5, 0x2e, 0x3e, 0xdf, 0xa9, 0xf7, 0xd4, 0x50, 0x71, 0xf0, 0x78}}}, {{{0x3e, 0xa8, 0x38, 0xc2, 0x57, 0x56, 0x42, 0x9a, 0xb1, 0xe2, 0xf8, 0x45, 0xaa, 0x11, 0x48, 0x5f, 0x17, 0xc4, 0x54, 0x27, 0xdc, 0x5d, 0xaa, 0xdd, 0x41, 0xbc, 0xdf, 0x81, 0xb9, 0x53, 0xee, 0x52}} , {{0xc3, 0xf1, 0xa7, 0x6d, 0xb3, 0x5f, 0x92, 0x6f, 0xcc, 0x91, 0xb8, 0x95, 0x05, 0xdf, 0x3c, 0x64, 0x57, 0x39, 0x61, 0x51, 0xad, 0x8c, 0x38, 0x7b, 0xc8, 0xde, 0x00, 0x34, 0xbe, 0xa1, 0xb0, 0x7e}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0x24, 0x1d, 0x8a, 0x67, 0x20, 0xee, 0x42, 0xeb, 0x38, 0xed, 0x0b, 0x8b, 0xcd, 0x46, 0x9d, 0x5e, 0x6b, 0x1e, 0x24, 0x9d, 0x12, 0x05, 0x1a, 0xcc, 0x05, 0x4e, 0x92, 0x38, 0xe1, 0x1f, 0x50}} , {{0x4e, 0xee, 0x1c, 0x91, 0xe6, 0x11, 0xbd, 0x8e, 0x55, 0x1a, 0x18, 0x75, 0x66, 0xaf, 0x4d, 0x7b, 0x0f, 0xae, 0x6d, 0x85, 0xca, 0x82, 0x58, 0x21, 0x9c, 0x18, 0xe0, 0xed, 0xec, 0x22, 0x80, 0x2f}}}, {{{0x68, 0x3b, 0x0a, 0x39, 0x1d, 0x6a, 0x15, 0x57, 0xfc, 0xf0, 0x63, 0x54, 0xdb, 0x39, 0xdb, 0xe8, 0x5c, 0x64, 0xff, 0xa0, 0x09, 0x4f, 0x3b, 0xb7, 0x32, 0x60, 0x99, 0x94, 0xfd, 0x94, 0x82, 0x2d}} , {{0x24, 0xf6, 0x5a, 0x44, 0xf1, 0x55, 0x2c, 0xdb, 0xea, 0x7c, 0x84, 0x7c, 0x01, 0xac, 0xe3, 0xfd, 0xc9, 0x27, 0xc1, 0x5a, 0xb9, 0xde, 0x4f, 0x5a, 0x90, 0xdd, 0xc6, 0x67, 0xaa, 0x6f, 0x8a, 0x3a}}}, {{{0x78, 0x52, 0x87, 0xc9, 0x97, 0x63, 0xb1, 0xdd, 0x54, 0x5f, 0xc1, 0xf8, 0xf1, 0x06, 0xa6, 0xa8, 0xa3, 0x88, 0x82, 0xd4, 0xcb, 0xa6, 0x19, 0xdd, 0xd1, 0x11, 0x87, 0x08, 0x17, 0x4c, 0x37, 0x2a}} , {{0xa1, 0x0c, 0xf3, 0x08, 0x43, 0xd9, 0x24, 0x1e, 0x83, 0xa7, 0xdf, 0x91, 0xca, 0xbd, 0x69, 0x47, 0x8d, 0x1b, 0xe2, 0xb9, 0x4e, 0xb5, 0xe1, 0x76, 0xb3, 0x1c, 0x93, 0x03, 0xce, 0x5f, 0xb3, 0x5a}}}, {{{0x1d, 0xda, 0xe4, 0x61, 0x03, 0x50, 0xa9, 0x8b, 0x68, 0x18, 0xef, 0xb2, 0x1c, 0x84, 0x3b, 0xa2, 0x44, 0x95, 0xa3, 0x04, 0x3b, 0xd6, 0x99, 0x00, 0xaf, 0x76, 0x42, 0x67, 0x02, 0x7d, 0x85, 0x56}} , {{0xce, 0x72, 0x0e, 0x29, 0x84, 0xb2, 0x7d, 0xd2, 0x45, 0xbe, 0x57, 0x06, 0xed, 0x7f, 0xcf, 0xed, 0xcd, 0xef, 0x19, 0xd6, 0xbc, 0x15, 0x79, 0x64, 0xd2, 0x18, 0xe3, 0x20, 0x67, 0x3a, 0x54, 0x0b}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x52, 0xfd, 0x04, 0xc5, 0xfb, 0x99, 0xe7, 0xe8, 0xfb, 0x8c, 0xe1, 0x42, 0x03, 0xef, 0x9d, 0xd9, 0x9e, 0x4d, 0xf7, 0x80, 0xcf, 0x2e, 0xcc, 0x9b, 0x45, 0xc9, 0x7b, 0x7a, 0xbc, 0x37, 0xa8, 0x52}} , {{0x96, 0x11, 0x41, 0x8a, 0x47, 0x91, 0xfe, 0xb6, 0xda, 0x7a, 0x54, 0x63, 0xd1, 0x14, 0x35, 0x05, 0x86, 0x8c, 0xa9, 0x36, 0x3f, 0xf2, 0x85, 0x54, 0x4e, 0x92, 0xd8, 0x85, 0x01, 0x46, 0xd6, 0x50}}}, {{{0x53, 0xcd, 0xf3, 0x86, 0x40, 0xe6, 0x39, 0x42, 0x95, 0xd6, 0xcb, 0x45, 0x1a, 0x20, 0xc8, 0x45, 0x4b, 0x32, 0x69, 0x04, 0xb1, 0xaf, 0x20, 0x46, 0xc7, 0x6b, 0x23, 0x5b, 0x69, 0xee, 0x30, 0x3f}} , {{0x70, 0x83, 0x47, 0xc0, 0xdb, 0x55, 0x08, 0xa8, 0x7b, 0x18, 0x6d, 0xf5, 0x04, 0x5a, 0x20, 0x0c, 0x4a, 0x8c, 0x60, 0xae, 0xae, 0x0f, 0x64, 0x55, 0x55, 0x2e, 0xd5, 0x1d, 0x53, 0x31, 0x42, 0x41}}}, {{{0xca, 0xfc, 0x88, 0x6b, 0x96, 0x78, 0x0a, 0x8b, 0x83, 0xdc, 0xbc, 0xaf, 0x40, 0xb6, 0x8d, 0x7f, 0xef, 0xb4, 0xd1, 0x3f, 0xcc, 0xa2, 0x74, 0xc9, 0xc2, 0x92, 0x55, 0x00, 0xab, 0xdb, 0xbf, 0x4f}} , {{0x93, 0x1c, 0x06, 0x2d, 0x66, 0x65, 0x02, 0xa4, 0x97, 0x18, 0xfd, 0x00, 0xe7, 0xab, 0x03, 0xec, 0xce, 0xc1, 0xbf, 0x37, 0xf8, 0x13, 0x53, 0xa5, 0xe5, 0x0c, 0x3a, 0xa8, 0x55, 0xb9, 0xff, 0x68}}}, {{{0xe4, 0xe6, 0x6d, 0x30, 0x7d, 0x30, 0x35, 0xc2, 0x78, 0x87, 0xf9, 0xfc, 0x6b, 0x5a, 0xc3, 0xb7, 0x65, 0xd8, 0x2e, 0xc7, 0xa5, 0x0c, 0xc6, 0xdc, 0x12, 0xaa, 0xd6, 0x4f, 0xc5, 0x38, 0xbc, 0x0e}} , {{0xe2, 0x3c, 0x76, 0x86, 0x38, 0xf2, 0x7b, 0x2c, 0x16, 0x78, 0x8d, 0xf5, 0xa4, 0x15, 0xda, 0xdb, 0x26, 0x85, 0xa0, 0x56, 0xdd, 0x1d, 0xe3, 0xb3, 0xfd, 0x40, 0xef, 0xf2, 0xd9, 0xa1, 0xb3, 0x04}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xdb, 0x49, 0x0e, 0xe6, 0x58, 0x10, 0x7a, 0x52, 0xda, 0xb5, 0x7d, 0x37, 0x6a, 0x3e, 0xa1, 0x78, 0xce, 0xc7, 0x1c, 0x24, 0x23, 0xdb, 0x7d, 0xfb, 0x8c, 0x8d, 0xdc, 0x30, 0x67, 0x69, 0x75, 0x3b}} , {{0xa9, 0xea, 0x6d, 0x16, 0x16, 0x60, 0xf4, 0x60, 0x87, 0x19, 0x44, 0x8c, 0x4a, 0x8b, 0x3e, 0xfb, 0x16, 0x00, 0x00, 0x54, 0xa6, 0x9e, 0x9f, 0xef, 0xcf, 0xd9, 0xd2, 0x4c, 0x74, 0x31, 0xd0, 0x34}}}, {{{0xa4, 0xeb, 0x04, 0xa4, 0x8c, 0x8f, 0x71, 0x27, 0x95, 0x85, 0x5d, 0x55, 0x4b, 0xb1, 0x26, 0x26, 0xc8, 0xae, 0x6a, 0x7d, 0xa2, 0x21, 0xca, 0xce, 0x38, 0xab, 0x0f, 0xd0, 0xd5, 0x2b, 0x6b, 0x00}} , {{0xe5, 0x67, 0x0c, 0xf1, 0x3a, 0x9a, 0xea, 0x09, 0x39, 0xef, 0xd1, 0x30, 0xbc, 0x33, 0xba, 0xb1, 0x6a, 0xc5, 0x27, 0x08, 0x7f, 0x54, 0x80, 0x3d, 0xab, 0xf6, 0x15, 0x7a, 0xc2, 0x40, 0x73, 0x72}}}, {{{0x84, 0x56, 0x82, 0xb6, 0x12, 0x70, 0x7f, 0xf7, 0xf0, 0xbd, 0x5b, 0xa9, 0xd5, 0xc5, 0x5f, 0x59, 0xbf, 0x7f, 0xb3, 0x55, 0x22, 0x02, 0xc9, 0x44, 0x55, 0x87, 0x8f, 0x96, 0x98, 0x64, 0x6d, 0x15}} , {{0xb0, 0x8b, 0xaa, 0x1e, 0xec, 0xc7, 0xa5, 0x8f, 0x1f, 0x92, 0x04, 0xc6, 0x05, 0xf6, 0xdf, 0xa1, 0xcc, 0x1f, 0x81, 0xf5, 0x0e, 0x9c, 0x57, 0xdc, 0xe3, 0xbb, 0x06, 0x87, 0x1e, 0xfe, 0x23, 0x6c}}}, {{{0xd8, 0x2b, 0x5b, 0x16, 0xea, 0x20, 0xf1, 0xd3, 0x68, 0x8f, 0xae, 0x5b, 0xd0, 0xa9, 0x1a, 0x19, 0xa8, 0x36, 0xfb, 0x2b, 0x57, 0x88, 0x7d, 0x90, 0xd5, 0xa6, 0xf3, 0xdc, 0x38, 0x89, 0x4e, 0x1f}} , {{0xcc, 0x19, 0xda, 0x9b, 0x3b, 0x43, 0x48, 0x21, 0x2e, 0x23, 0x4d, 0x3d, 0xae, 0xf8, 0x8c, 0xfc, 0xdd, 0xa6, 0x74, 0x37, 0x65, 0xca, 0xee, 0x1a, 0x19, 0x8e, 0x9f, 0x64, 0x6f, 0x0c, 0x8b, 0x5a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0xb9, 0xc2, 0xf0, 0x72, 0xb8, 0x15, 0x16, 0xcc, 0x8d, 0x3c, 0x6f, 0x25, 0xed, 0xf4, 0x46, 0x2e, 0x0c, 0x60, 0x0f, 0xe2, 0x84, 0x34, 0x55, 0x89, 0x59, 0x34, 0x1b, 0xf5, 0x8d, 0xfe, 0x08}} , {{0xf8, 0xab, 0x93, 0xbc, 0x44, 0xba, 0x1b, 0x75, 0x4b, 0x49, 0x6f, 0xd0, 0x54, 0x2e, 0x63, 0xba, 0xb5, 0xea, 0xed, 0x32, 0x14, 0xc9, 0x94, 0xd8, 0xc5, 0xce, 0xf4, 0x10, 0x68, 0xe0, 0x38, 0x27}}}, {{{0x74, 0x1c, 0x14, 0x9b, 0xd4, 0x64, 0x61, 0x71, 0x5a, 0xb6, 0x21, 0x33, 0x4f, 0xf7, 0x8e, 0xba, 0xa5, 0x48, 0x9a, 0xc7, 0xfa, 0x9a, 0xf0, 0xb4, 0x62, 0xad, 0xf2, 0x5e, 0xcc, 0x03, 0x24, 0x1a}} , {{0xf5, 0x76, 0xfd, 0xe4, 0xaf, 0xb9, 0x03, 0x59, 0xce, 0x63, 0xd2, 0x3b, 0x1f, 0xcd, 0x21, 0x0c, 0xad, 0x44, 0xa5, 0x97, 0xac, 0x80, 0x11, 0x02, 0x9b, 0x0c, 0xe5, 0x8b, 0xcd, 0xfb, 0x79, 0x77}}}, {{{0x15, 0xbe, 0x9a, 0x0d, 0xba, 0x38, 0x72, 0x20, 0x8a, 0xf5, 0xbe, 0x59, 0x93, 0x79, 0xb7, 0xf6, 0x6a, 0x0c, 0x38, 0x27, 0x1a, 0x60, 0xf4, 0x86, 0x3b, 0xab, 0x5a, 0x00, 0xa0, 0xce, 0x21, 0x7d}} , {{0x6c, 0xba, 0x14, 0xc5, 0xea, 0x12, 0x9e, 0x2e, 0x82, 0x63, 0xce, 0x9b, 0x4a, 0xe7, 0x1d, 0xec, 0xf1, 0x2e, 0x51, 0x1c, 0xf4, 0xd0, 0x69, 0x15, 0x42, 0x9d, 0xa3, 0x3f, 0x0e, 0xbf, 0xe9, 0x5c}}}, {{{0xe4, 0x0d, 0xf4, 0xbd, 0xee, 0x31, 0x10, 0xed, 0xcb, 0x12, 0x86, 0xad, 0xd4, 0x2f, 0x90, 0x37, 0x32, 0xc3, 0x0b, 0x73, 0xec, 0x97, 0x85, 0xa4, 0x01, 0x1c, 0x76, 0x35, 0xfe, 0x75, 0xdd, 0x71}} , {{0x11, 0xa4, 0x88, 0x9f, 0x3e, 0x53, 0x69, 0x3b, 0x1b, 0xe0, 0xf7, 0xba, 0x9b, 0xad, 0x4e, 0x81, 0x5f, 0xb5, 0x5c, 0xae, 0xbe, 0x67, 0x86, 0x37, 0x34, 0x8e, 0x07, 0x32, 0x45, 0x4a, 0x67, 0x39}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x90, 0x70, 0x58, 0x20, 0x03, 0x1e, 0x67, 0xb2, 0xc8, 0x9b, 0x58, 0xc5, 0xb1, 0xeb, 0x2d, 0x4a, 0xde, 0x82, 0x8c, 0xf2, 0xd2, 0x14, 0xb8, 0x70, 0x61, 0x4e, 0x73, 0xd6, 0x0b, 0x6b, 0x0d, 0x30}} , {{0x81, 0xfc, 0x55, 0x5c, 0xbf, 0xa7, 0xc4, 0xbd, 0xe2, 0xf0, 0x4b, 0x8f, 0xe9, 0x7d, 0x99, 0xfa, 0xd3, 0xab, 0xbc, 0xc7, 0x83, 0x2b, 0x04, 0x7f, 0x0c, 0x19, 0x43, 0x03, 0x3d, 0x07, 0xca, 0x40}}}, {{{0xf9, 0xc8, 0xbe, 0x8c, 0x16, 0x81, 0x39, 0x96, 0xf6, 0x17, 0x58, 0xc8, 0x30, 0x58, 0xfb, 0xc2, 0x03, 0x45, 0xd2, 0x52, 0x76, 0xe0, 0x6a, 0x26, 0x28, 0x5c, 0x88, 0x59, 0x6a, 0x5a, 0x54, 0x42}} , {{0x07, 0xb5, 0x2e, 0x2c, 0x67, 0x15, 0x9b, 0xfb, 0x83, 0x69, 0x1e, 0x0f, 0xda, 0xd6, 0x29, 0xb1, 0x60, 0xe0, 0xb2, 0xba, 0x69, 0xa2, 0x9e, 0xbd, 0xbd, 0xe0, 0x1c, 0xbd, 0xcd, 0x06, 0x64, 0x70}}}, {{{0x41, 0xfa, 0x8c, 0xe1, 0x89, 0x8f, 0x27, 0xc8, 0x25, 0x8f, 0x6f, 0x5f, 0x55, 0xf8, 0xde, 0x95, 0x6d, 0x2f, 0x75, 0x16, 0x2b, 0x4e, 0x44, 0xfd, 0x86, 0x6e, 0xe9, 0x70, 0x39, 0x76, 0x97, 0x7e}} , {{0x17, 0x62, 0x6b, 0x14, 0xa1, 0x7c, 0xd0, 0x79, 0x6e, 0xd8, 0x8a, 0xa5, 0x6d, 0x8c, 0x93, 0xd2, 0x3f, 0xec, 0x44, 0x8d, 0x6e, 0x91, 0x01, 0x8c, 0x8f, 0xee, 0x01, 0x8f, 0xc0, 0xb4, 0x85, 0x0e}}}, {{{0x02, 0x3a, 0x70, 0x41, 0xe4, 0x11, 0x57, 0x23, 0xac, 0xe6, 0xfc, 0x54, 0x7e, 0xcd, 0xd7, 0x22, 0xcb, 0x76, 0x9f, 0x20, 0xce, 0xa0, 0x73, 0x76, 0x51, 0x3b, 0xa4, 0xf8, 0xe3, 0x62, 0x12, 0x6c}} , {{0x7f, 0x00, 0x9c, 0x26, 0x0d, 0x6f, 0x48, 0x7f, 0x3a, 0x01, 0xed, 0xc5, 0x96, 0xb0, 0x1f, 0x4f, 0xa8, 0x02, 0x62, 0x27, 0x8a, 0x50, 0x8d, 0x9a, 0x8b, 0x52, 0x0f, 0x1e, 0xcf, 0x41, 0x38, 0x19}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf5, 0x6c, 0xd4, 0x2f, 0x0f, 0x69, 0x0f, 0x87, 0x3f, 0x61, 0x65, 0x1e, 0x35, 0x34, 0x85, 0xba, 0x02, 0x30, 0xac, 0x25, 0x3d, 0xe2, 0x62, 0xf1, 0xcc, 0xe9, 0x1b, 0xc2, 0xef, 0x6a, 0x42, 0x57}} , {{0x34, 0x1f, 0x2e, 0xac, 0xd1, 0xc7, 0x04, 0x52, 0x32, 0x66, 0xb2, 0x33, 0x73, 0x21, 0x34, 0x54, 0xf7, 0x71, 0xed, 0x06, 0xb0, 0xff, 0xa6, 0x59, 0x6f, 0x8a, 0x4e, 0xfb, 0x02, 0xb0, 0x45, 0x6b}}}, {{{0xf5, 0x48, 0x0b, 0x03, 0xc5, 0x22, 0x7d, 0x80, 0x08, 0x53, 0xfe, 0x32, 0xb1, 0xa1, 0x8a, 0x74, 0x6f, 0xbd, 0x3f, 0x85, 0xf4, 0xcf, 0xf5, 0x60, 0xaf, 0x41, 0x7e, 0x3e, 0x46, 0xa3, 0x5a, 0x20}} , {{0xaa, 0x35, 0x87, 0x44, 0x63, 0x66, 0x97, 0xf8, 0x6e, 0x55, 0x0c, 0x04, 0x3e, 0x35, 0x50, 0xbf, 0x93, 0x69, 0xd2, 0x8b, 0x05, 0x55, 0x99, 0xbe, 0xe2, 0x53, 0x61, 0xec, 0xe8, 0x08, 0x0b, 0x32}}}, {{{0xb3, 0x10, 0x45, 0x02, 0x69, 0x59, 0x2e, 0x97, 0xd9, 0x64, 0xf8, 0xdb, 0x25, 0x80, 0xdc, 0xc4, 0xd5, 0x62, 0x3c, 0xed, 0x65, 0x91, 0xad, 0xd1, 0x57, 0x81, 0x94, 0xaa, 0xa1, 0x29, 0xfc, 0x68}} , {{0xdd, 0xb5, 0x7d, 0xab, 0x5a, 0x21, 0x41, 0x53, 0xbb, 0x17, 0x79, 0x0d, 0xd1, 0xa8, 0x0c, 0x0c, 0x20, 0x88, 0x09, 0xe9, 0x84, 0xe8, 0x25, 0x11, 0x67, 0x7a, 0x8b, 0x1a, 0xe4, 0x5d, 0xe1, 0x5d}}}, {{{0x37, 0xea, 0xfe, 0x65, 0x3b, 0x25, 0xe8, 0xe1, 0xc2, 0xc5, 0x02, 0xa4, 0xbe, 0x98, 0x0a, 0x2b, 0x61, 0xc1, 0x9b, 0xe2, 0xd5, 0x92, 0xe6, 0x9e, 0x7d, 0x1f, 0xca, 0x43, 0x88, 0x8b, 0x2c, 0x59}} , {{0xe0, 0xb5, 0x00, 0x1d, 0x2a, 0x6f, 0xaf, 0x79, 0x86, 0x2f, 0xa6, 0x5a, 0x93, 0xd1, 0xfe, 0xae, 0x3a, 0xee, 0xdb, 0x7c, 0x61, 0xbe, 0x7c, 0x01, 0xf9, 0xfe, 0x52, 0xdc, 0xd8, 0x52, 0xa3, 0x42}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x22, 0xaf, 0x13, 0x37, 0xbd, 0x37, 0x71, 0xac, 0x04, 0x46, 0x63, 0xac, 0xa4, 0x77, 0xed, 0x25, 0x38, 0xe0, 0x15, 0xa8, 0x64, 0x00, 0x0d, 0xce, 0x51, 0x01, 0xa9, 0xbc, 0x0f, 0x03, 0x1c, 0x04}} , {{0x89, 0xf9, 0x80, 0x07, 0xcf, 0x3f, 0xb3, 0xe9, 0xe7, 0x45, 0x44, 0x3d, 0x2a, 0x7c, 0xe9, 0xe4, 0x16, 0x5c, 0x5e, 0x65, 0x1c, 0xc7, 0x7d, 0xc6, 0x7a, 0xfb, 0x43, 0xee, 0x25, 0x76, 0x46, 0x72}}}, {{{0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e, 0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4, 0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62}} , {{0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba, 0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd, 0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03}}}, {{{0x51, 0x16, 0x50, 0x7c, 0xd5, 0x5d, 0xf6, 0x99, 0xe8, 0x77, 0x72, 0x4e, 0xfa, 0x62, 0xcb, 0x76, 0x75, 0x0c, 0xe2, 0x71, 0x98, 0x92, 0xd5, 0xfa, 0x45, 0xdf, 0x5c, 0x6f, 0x1e, 0x9e, 0x28, 0x69}} , {{0x0d, 0xac, 0x66, 0x6d, 0xc3, 0x8b, 0xba, 0x16, 0xb5, 0xe2, 0xa0, 0x0d, 0x0c, 0xbd, 0xa4, 0x8e, 0x18, 0x6c, 0xf2, 0xdc, 0xf9, 0xdc, 0x4a, 0x86, 0x25, 0x95, 0x14, 0xcb, 0xd8, 0x1a, 0x04, 0x0f}}}, {{{0x97, 0xa5, 0xdb, 0x8b, 0x2d, 0xaa, 0x42, 0x11, 0x09, 0xf2, 0x93, 0xbb, 0xd9, 0x06, 0x84, 0x4e, 0x11, 0xa8, 0xa0, 0x25, 0x2b, 0xa6, 0x5f, 0xae, 0xc4, 0xb4, 0x4c, 0xc8, 0xab, 0xc7, 0x3b, 0x02}} , {{0xee, 0xc9, 0x29, 0x0f, 0xdf, 0x11, 0x85, 0xed, 0xce, 0x0d, 0x62, 0x2c, 0x8f, 0x4b, 0xf9, 0x04, 0xe9, 0x06, 0x72, 0x1d, 0x37, 0x20, 0x50, 0xc9, 0x14, 0xeb, 0xec, 0x39, 0xa7, 0x97, 0x2b, 0x4d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x69, 0xd1, 0x39, 0xbd, 0xfb, 0x33, 0xbe, 0xc4, 0xf0, 0x5c, 0xef, 0xf0, 0x56, 0x68, 0xfc, 0x97, 0x47, 0xc8, 0x72, 0xb6, 0x53, 0xa4, 0x0a, 0x98, 0xa5, 0xb4, 0x37, 0x71, 0xcf, 0x66, 0x50, 0x6d}} , {{0x17, 0xa4, 0x19, 0x52, 0x11, 0x47, 0xb3, 0x5c, 0x5b, 0xa9, 0x2e, 0x22, 0xb4, 0x00, 0x52, 0xf9, 0x57, 0x18, 0xb8, 0xbe, 0x5a, 0xe3, 0xab, 0x83, 0xc8, 0x87, 0x0a, 0x2a, 0xd8, 0x8c, 0xbb, 0x54}}}, {{{0xa9, 0x62, 0x93, 0x85, 0xbe, 0xe8, 0x73, 0x4a, 0x0e, 0xb0, 0xb5, 0x2d, 0x94, 0x50, 0xaa, 0xd3, 0xb2, 0xea, 0x9d, 0x62, 0x76, 0x3b, 0x07, 0x34, 0x4e, 0x2d, 0x70, 0xc8, 0x9a, 0x15, 0x66, 0x6b}} , {{0xc5, 0x96, 0xca, 0xc8, 0x22, 0x1a, 0xee, 0x5f, 0xe7, 0x31, 0x60, 0x22, 0x83, 0x08, 0x63, 0xce, 0xb9, 0x32, 0x44, 0x58, 0x5d, 0x3a, 0x9b, 0xe4, 0x04, 0xd5, 0xef, 0x38, 0xef, 0x4b, 0xdd, 0x19}}}, {{{0x4d, 0xc2, 0x17, 0x75, 0xa1, 0x68, 0xcd, 0xc3, 0xc6, 0x03, 0x44, 0xe3, 0x78, 0x09, 0x91, 0x47, 0x3f, 0x0f, 0xe4, 0x92, 0x58, 0xfa, 0x7d, 0x1f, 0x20, 0x94, 0x58, 0x5e, 0xbc, 0x19, 0x02, 0x6f}} , {{0x20, 0xd6, 0xd8, 0x91, 0x54, 0xa7, 0xf3, 0x20, 0x4b, 0x34, 0x06, 0xfa, 0x30, 0xc8, 0x6f, 0x14, 0x10, 0x65, 0x74, 0x13, 0x4e, 0xf0, 0x69, 0x26, 0xce, 0xcf, 0x90, 0xf4, 0xd0, 0xc5, 0xc8, 0x64}}}, {{{0x26, 0xa2, 0x50, 0x02, 0x24, 0x72, 0xf1, 0xf0, 0x4e, 0x2d, 0x93, 0xd5, 0x08, 0xe7, 0xae, 0x38, 0xf7, 0x18, 0xa5, 0x32, 0x34, 0xc2, 0xf0, 0xa6, 0xec, 0xb9, 0x61, 0x7b, 0x64, 0x99, 0xac, 0x71}} , {{0x25, 0xcf, 0x74, 0x55, 0x1b, 0xaa, 0xa9, 0x38, 0x41, 0x40, 0xd5, 0x95, 0x95, 0xab, 0x1c, 0x5e, 0xbc, 0x41, 0x7e, 0x14, 0x30, 0xbe, 0x13, 0x89, 0xf4, 0xe5, 0xeb, 0x28, 0xc0, 0xc2, 0x96, 0x3a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2b, 0x77, 0x45, 0xec, 0x67, 0x76, 0x32, 0x4c, 0xb9, 0xdf, 0x25, 0x32, 0x6b, 0xcb, 0xe7, 0x14, 0x61, 0x43, 0xee, 0xba, 0x9b, 0x71, 0xef, 0xd2, 0x48, 0x65, 0xbb, 0x1b, 0x8a, 0x13, 0x1b, 0x22}} , {{0x84, 0xad, 0x0c, 0x18, 0x38, 0x5a, 0xba, 0xd0, 0x98, 0x59, 0xbf, 0x37, 0xb0, 0x4f, 0x97, 0x60, 0x20, 0xb3, 0x9b, 0x97, 0xf6, 0x08, 0x6c, 0xa4, 0xff, 0xfb, 0xb7, 0xfa, 0x95, 0xb2, 0x51, 0x79}}}, {{{0x28, 0x5c, 0x3f, 0xdb, 0x6b, 0x18, 0x3b, 0x5c, 0xd1, 0x04, 0x28, 0xde, 0x85, 0x52, 0x31, 0xb5, 0xbb, 0xf6, 0xa9, 0xed, 0xbe, 0x28, 0x4f, 0xb3, 0x7e, 0x05, 0x6a, 0xdb, 0x95, 0x0d, 0x1b, 0x1c}} , {{0xd5, 0xc5, 0xc3, 0x9a, 0x0a, 0xd0, 0x31, 0x3e, 0x07, 0x36, 0x8e, 0xc0, 0x8a, 0x62, 0xb1, 0xca, 0xd6, 0x0e, 0x1e, 0x9d, 0xef, 0xab, 0x98, 0x4d, 0xbb, 0x6c, 0x05, 0xe0, 0xe4, 0x5d, 0xbd, 0x57}}}, {{{0xcc, 0x21, 0x27, 0xce, 0xfd, 0xa9, 0x94, 0x8e, 0xe1, 0xab, 0x49, 0xe0, 0x46, 0x26, 0xa1, 0xa8, 0x8c, 0xa1, 0x99, 0x1d, 0xb4, 0x27, 0x6d, 0x2d, 0xc8, 0x39, 0x30, 0x5e, 0x37, 0x52, 0xc4, 0x6e}} , {{0xa9, 0x85, 0xf4, 0xe7, 0xb0, 0x15, 0x33, 0x84, 0x1b, 0x14, 0x1a, 0x02, 0xd9, 0x3b, 0xad, 0x0f, 0x43, 0x6c, 0xea, 0x3e, 0x0f, 0x7e, 0xda, 0xdd, 0x6b, 0x4c, 0x7f, 0x6e, 0xd4, 0x6b, 0xbf, 0x0f}}}, {{{0x47, 0x9f, 0x7c, 0x56, 0x7c, 0x43, 0x91, 0x1c, 0xbb, 0x4e, 0x72, 0x3e, 0x64, 0xab, 0xa0, 0xa0, 0xdf, 0xb4, 0xd8, 0x87, 0x3a, 0xbd, 0xa8, 0x48, 0xc9, 0xb8, 0xef, 0x2e, 0xad, 0x6f, 0x84, 0x4f}} , {{0x2d, 0x2d, 0xf0, 0x1b, 0x7e, 0x2a, 0x6c, 0xf8, 0xa9, 0x6a, 0xe1, 0xf0, 0x99, 0xa1, 0x67, 0x9a, 0xd4, 0x13, 0xca, 0xca, 0xba, 0x27, 0x92, 0xaa, 0xa1, 0x5d, 0x50, 0xde, 0xcc, 0x40, 0x26, 0x0a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9f, 0x3e, 0xf2, 0xb2, 0x90, 0xce, 0xdb, 0x64, 0x3e, 0x03, 0xdd, 0x37, 0x36, 0x54, 0x70, 0x76, 0x24, 0xb5, 0x69, 0x03, 0xfc, 0xa0, 0x2b, 0x74, 0xb2, 0x05, 0x0e, 0xcc, 0xd8, 0x1f, 0x6a, 0x1f}} , {{0x19, 0x5e, 0x60, 0x69, 0x58, 0x86, 0xa0, 0x31, 0xbd, 0x32, 0xe9, 0x2c, 0x5c, 0xd2, 0x85, 0xba, 0x40, 0x64, 0xa8, 0x74, 0xf8, 0x0e, 0x1c, 0xb3, 0xa9, 0x69, 0xe8, 0x1e, 0x40, 0x64, 0x99, 0x77}}}, {{{0x6c, 0x32, 0x4f, 0xfd, 0xbb, 0x5c, 0xbb, 0x8d, 0x64, 0x66, 0x4a, 0x71, 0x1f, 0x79, 0xa3, 0xad, 0x8d, 0xf9, 0xd4, 0xec, 0xcf, 0x67, 0x70, 0xfa, 0x05, 0x4a, 0x0f, 0x6e, 0xaf, 0x87, 0x0a, 0x6f}} , {{0xc6, 0x36, 0x6e, 0x6c, 0x8c, 0x24, 0x09, 0x60, 0xbe, 0x26, 0xd2, 0x4c, 0x5e, 0x17, 0xca, 0x5f, 0x1d, 0xcc, 0x87, 0xe8, 0x42, 0x6a, 0xcb, 0xcb, 0x7d, 0x92, 0x05, 0x35, 0x81, 0x13, 0x60, 0x6b}}}, {{{0xf4, 0x15, 0xcd, 0x0f, 0x0a, 0xaf, 0x4e, 0x6b, 0x51, 0xfd, 0x14, 0xc4, 0x2e, 0x13, 0x86, 0x74, 0x44, 0xcb, 0x66, 0x6b, 0xb6, 0x9d, 0x74, 0x56, 0x32, 0xac, 0x8d, 0x8e, 0x8c, 0x8c, 0x8c, 0x39}} , {{0xca, 0x59, 0x74, 0x1a, 0x11, 0xef, 0x6d, 0xf7, 0x39, 0x5c, 0x3b, 0x1f, 0xfa, 0xe3, 0x40, 0x41, 0x23, 0x9e, 0xf6, 0xd1, 0x21, 0xa2, 0xbf, 0xad, 0x65, 0x42, 0x6b, 0x59, 0x8a, 0xe8, 0xc5, 0x7f}}}, {{{0x64, 0x05, 0x7a, 0x84, 0x4a, 0x13, 0xc3, 0xf6, 0xb0, 0x6e, 0x9a, 0x6b, 0x53, 0x6b, 0x32, 0xda, 0xd9, 0x74, 0x75, 0xc4, 0xba, 0x64, 0x3d, 0x3b, 0x08, 0xdd, 0x10, 0x46, 0xef, 0xc7, 0x90, 0x1f}} , {{0x7b, 0x2f, 0x3a, 0xce, 0xc8, 0xa1, 0x79, 0x3c, 0x30, 0x12, 0x44, 0x28, 0xf6, 0xbc, 0xff, 0xfd, 0xf4, 0xc0, 0x97, 0xb0, 0xcc, 0xc3, 0x13, 0x7a, 0xb9, 0x9a, 0x16, 0xe4, 0xcb, 0x4c, 0x34, 0x63}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x07, 0x4e, 0xd3, 0x2d, 0x09, 0x33, 0x0e, 0xd2, 0x0d, 0xbe, 0x3e, 0xe7, 0xe4, 0xaa, 0xb7, 0x00, 0x8b, 0xe8, 0xad, 0xaa, 0x7a, 0x8d, 0x34, 0x28, 0xa9, 0x81, 0x94, 0xc5, 0xe7, 0x42, 0xac, 0x47}} , {{0x24, 0x89, 0x7a, 0x8f, 0xb5, 0x9b, 0xf0, 0xc2, 0x03, 0x64, 0xd0, 0x1e, 0xf5, 0xa4, 0xb2, 0xf3, 0x74, 0xe9, 0x1a, 0x16, 0xfd, 0xcb, 0x15, 0xea, 0xeb, 0x10, 0x6c, 0x35, 0xd1, 0xc1, 0xa6, 0x28}}}, {{{0xcc, 0xd5, 0x39, 0xfc, 0xa5, 0xa4, 0xad, 0x32, 0x15, 0xce, 0x19, 0xe8, 0x34, 0x2b, 0x1c, 0x60, 0x91, 0xfc, 0x05, 0xa9, 0xb3, 0xdc, 0x80, 0x29, 0xc4, 0x20, 0x79, 0x06, 0x39, 0xc0, 0xe2, 0x22}} , {{0xbb, 0xa8, 0xe1, 0x89, 0x70, 0x57, 0x18, 0x54, 0x3c, 0xf6, 0x0d, 0x82, 0x12, 0x05, 0x87, 0x96, 0x06, 0x39, 0xe3, 0xf8, 0xb3, 0x95, 0xe5, 0xd7, 0x26, 0xbf, 0x09, 0x5a, 0x94, 0xf9, 0x1c, 0x63}}}, {{{0x2b, 0x8c, 0x2d, 0x9a, 0x8b, 0x84, 0xf2, 0x56, 0xfb, 0xad, 0x2e, 0x7f, 0xb7, 0xfc, 0x30, 0xe1, 0x35, 0x89, 0xba, 0x4d, 0xa8, 0x6d, 0xce, 0x8c, 0x8b, 0x30, 0xe0, 0xda, 0x29, 0x18, 0x11, 0x17}} , {{0x19, 0xa6, 0x5a, 0x65, 0x93, 0xc3, 0xb5, 0x31, 0x22, 0x4f, 0xf3, 0xf6, 0x0f, 0xeb, 0x28, 0xc3, 0x7c, 0xeb, 0xce, 0x86, 0xec, 0x67, 0x76, 0x6e, 0x35, 0x45, 0x7b, 0xd8, 0x6b, 0x92, 0x01, 0x65}}}, {{{0x3d, 0xd5, 0x9a, 0x64, 0x73, 0x36, 0xb1, 0xd6, 0x86, 0x98, 0x42, 0x3f, 0x8a, 0xf1, 0xc7, 0xf5, 0x42, 0xa8, 0x9c, 0x52, 0xa8, 0xdc, 0xf9, 0x24, 0x3f, 0x4a, 0xa1, 0xa4, 0x5b, 0xe8, 0x62, 0x1a}} , {{0xc5, 0xbd, 0xc8, 0x14, 0xd5, 0x0d, 0xeb, 0xe1, 0xa5, 0xe6, 0x83, 0x11, 0x09, 0x00, 0x1d, 0x55, 0x83, 0x51, 0x7e, 0x75, 0x00, 0x81, 0xb9, 0xcb, 0xd8, 0xc5, 0xe5, 0xa1, 0xd9, 0x17, 0x6d, 0x1f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xea, 0xf9, 0xe4, 0xe9, 0xe1, 0x52, 0x3f, 0x51, 0x19, 0x0d, 0xdd, 0xd9, 0x9d, 0x93, 0x31, 0x87, 0x23, 0x09, 0xd5, 0x83, 0xeb, 0x92, 0x09, 0x76, 0x6e, 0xe3, 0xf8, 0xc0, 0xa2, 0x66, 0xb5, 0x36}} , {{0x3a, 0xbb, 0x39, 0xed, 0x32, 0x02, 0xe7, 0x43, 0x7a, 0x38, 0x14, 0x84, 0xe3, 0x44, 0xd2, 0x5e, 0x94, 0xdd, 0x78, 0x89, 0x55, 0x4c, 0x73, 0x9e, 0xe1, 0xe4, 0x3e, 0x43, 0xd0, 0x4a, 0xde, 0x1b}}}, {{{0xb2, 0xe7, 0x8f, 0xe3, 0xa3, 0xc5, 0xcb, 0x72, 0xee, 0x79, 0x41, 0xf8, 0xdf, 0xee, 0x65, 0xc5, 0x45, 0x77, 0x27, 0x3c, 0xbd, 0x58, 0xd3, 0x75, 0xe2, 0x04, 0x4b, 0xbb, 0x65, 0xf3, 0xc8, 0x0f}} , {{0x24, 0x7b, 0x93, 0x34, 0xb5, 0xe2, 0x74, 0x48, 0xcd, 0xa0, 0x0b, 0x92, 0x97, 0x66, 0x39, 0xf4, 0xb0, 0xe2, 0x5d, 0x39, 0x6a, 0x5b, 0x45, 0x17, 0x78, 0x1e, 0xdb, 0x91, 0x81, 0x1c, 0xf9, 0x16}}}, {{{0x16, 0xdf, 0xd1, 0x5a, 0xd5, 0xe9, 0x4e, 0x58, 0x95, 0x93, 0x5f, 0x51, 0x09, 0xc3, 0x2a, 0xc9, 0xd4, 0x55, 0x48, 0x79, 0xa4, 0xa3, 0xb2, 0xc3, 0x62, 0xaa, 0x8c, 0xe8, 0xad, 0x47, 0x39, 0x1b}} , {{0x46, 0xda, 0x9e, 0x51, 0x3a, 0xe6, 0xd1, 0xa6, 0xbb, 0x4d, 0x7b, 0x08, 0xbe, 0x8c, 0xd5, 0xf3, 0x3f, 0xfd, 0xf7, 0x44, 0x80, 0x2d, 0x53, 0x4b, 0xd0, 0x87, 0x68, 0xc1, 0xb5, 0xd8, 0xf7, 0x07}}}, {{{0xf4, 0x10, 0x46, 0xbe, 0xb7, 0xd2, 0xd1, 0xce, 0x5e, 0x76, 0xa2, 0xd7, 0x03, 0xdc, 0xe4, 0x81, 0x5a, 0xf6, 0x3c, 0xde, 0xae, 0x7a, 0x9d, 0x21, 0x34, 0xa5, 0xf6, 0xa9, 0x73, 0xe2, 0x8d, 0x60}} , {{0xfa, 0x44, 0x71, 0xf6, 0x41, 0xd8, 0xc6, 0x58, 0x13, 0x37, 0xeb, 0x84, 0x0f, 0x96, 0xc7, 0xdc, 0xc8, 0xa9, 0x7a, 0x83, 0xb2, 0x2f, 0x31, 0xb1, 0x1a, 0xd8, 0x98, 0x3f, 0x11, 0xd0, 0x31, 0x3b}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x81, 0xd5, 0x34, 0x16, 0x01, 0xa3, 0x93, 0xea, 0x52, 0x94, 0xec, 0x93, 0xb7, 0x81, 0x11, 0x2d, 0x58, 0xf9, 0xb5, 0x0a, 0xaa, 0x4f, 0xf6, 0x2e, 0x3f, 0x36, 0xbf, 0x33, 0x5a, 0xe7, 0xd1, 0x08}} , {{0x1a, 0xcf, 0x42, 0xae, 0xcc, 0xb5, 0x77, 0x39, 0xc4, 0x5b, 0x5b, 0xd0, 0x26, 0x59, 0x27, 0xd0, 0x55, 0x71, 0x12, 0x9d, 0x88, 0x3d, 0x9c, 0xea, 0x41, 0x6a, 0xf0, 0x50, 0x93, 0x93, 0xdd, 0x47}}}, {{{0x6f, 0xc9, 0x51, 0x6d, 0x1c, 0xaa, 0xf5, 0xa5, 0x90, 0x3f, 0x14, 0xe2, 0x6e, 0x8e, 0x64, 0xfd, 0xac, 0xe0, 0x4e, 0x22, 0xe5, 0xc1, 0xbc, 0x29, 0x0a, 0x6a, 0x9e, 0xa1, 0x60, 0xcb, 0x2f, 0x0b}} , {{0xdc, 0x39, 0x32, 0xf3, 0xa1, 0x44, 0xe9, 0xc5, 0xc3, 0x78, 0xfb, 0x95, 0x47, 0x34, 0x35, 0x34, 0xe8, 0x25, 0xde, 0x93, 0xc6, 0xb4, 0x76, 0x6d, 0x86, 0x13, 0xc6, 0xe9, 0x68, 0xb5, 0x01, 0x63}}}, {{{0x1f, 0x9a, 0x52, 0x64, 0x97, 0xd9, 0x1c, 0x08, 0x51, 0x6f, 0x26, 0x9d, 0xaa, 0x93, 0x33, 0x43, 0xfa, 0x77, 0xe9, 0x62, 0x9b, 0x5d, 0x18, 0x75, 0xeb, 0x78, 0xf7, 0x87, 0x8f, 0x41, 0xb4, 0x4d}} , {{0x13, 0xa8, 0x82, 0x3e, 0xe9, 0x13, 0xad, 0xeb, 0x01, 0xca, 0xcf, 0xda, 0xcd, 0xf7, 0x6c, 0xc7, 0x7a, 0xdc, 0x1e, 0x6e, 0xc8, 0x4e, 0x55, 0x62, 0x80, 0xea, 0x78, 0x0c, 0x86, 0xb9, 0x40, 0x51}}}, {{{0x27, 0xae, 0xd3, 0x0d, 0x4c, 0x8f, 0x34, 0xea, 0x7d, 0x3c, 0xe5, 0x8a, 0xcf, 0x5b, 0x92, 0xd8, 0x30, 0x16, 0xb4, 0xa3, 0x75, 0xff, 0xeb, 0x27, 0xc8, 0x5c, 0x6c, 0xc2, 0xee, 0x6c, 0x21, 0x0b}} , {{0xc3, 0xba, 0x12, 0x53, 0x2a, 0xaa, 0x77, 0xad, 0x19, 0x78, 0x55, 0x8a, 0x2e, 0x60, 0x87, 0xc2, 0x6e, 0x91, 0x38, 0x91, 0x3f, 0x7a, 0xc5, 0x24, 0x8f, 0x51, 0xc5, 0xde, 0xb0, 0x53, 0x30, 0x56}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x02, 0xfe, 0x54, 0x12, 0x18, 0xca, 0x7d, 0xa5, 0x68, 0x43, 0xa3, 0x6d, 0x14, 0x2a, 0x6a, 0xa5, 0x8e, 0x32, 0xe7, 0x63, 0x4f, 0xe3, 0xc6, 0x44, 0x3e, 0xab, 0x63, 0xca, 0x17, 0x86, 0x74, 0x3f}} , {{0x1e, 0x64, 0xc1, 0x7d, 0x52, 0xdc, 0x13, 0x5a, 0xa1, 0x9c, 0x4e, 0xee, 0x99, 0x28, 0xbb, 0x4c, 0xee, 0xac, 0xa9, 0x1b, 0x89, 0xa2, 0x38, 0x39, 0x7b, 0xc4, 0x0f, 0x42, 0xe6, 0x89, 0xed, 0x0f}}}, {{{0xf3, 0x3c, 0x8c, 0x80, 0x83, 0x10, 0x8a, 0x37, 0x50, 0x9c, 0xb4, 0xdf, 0x3f, 0x8c, 0xf7, 0x23, 0x07, 0xd6, 0xff, 0xa0, 0x82, 0x6c, 0x75, 0x3b, 0xe4, 0xb5, 0xbb, 0xe4, 0xe6, 0x50, 0xf0, 0x08}} , {{0x62, 0xee, 0x75, 0x48, 0x92, 0x33, 0xf2, 0xf4, 0xad, 0x15, 0x7a, 0xa1, 0x01, 0x46, 0xa9, 0x32, 0x06, 0x88, 0xb6, 0x36, 0x47, 0x35, 0xb9, 0xb4, 0x42, 0x85, 0x76, 0xf0, 0x48, 0x00, 0x90, 0x38}}}, {{{0x51, 0x15, 0x9d, 0xc3, 0x95, 0xd1, 0x39, 0xbb, 0x64, 0x9d, 0x15, 0x81, 0xc1, 0x68, 0xd0, 0xb6, 0xa4, 0x2c, 0x7d, 0x5e, 0x02, 0x39, 0x00, 0xe0, 0x3b, 0xa4, 0xcc, 0xca, 0x1d, 0x81, 0x24, 0x10}} , {{0xe7, 0x29, 0xf9, 0x37, 0xd9, 0x46, 0x5a, 0xcd, 0x70, 0xfe, 0x4d, 0x5b, 0xbf, 0xa5, 0xcf, 0x91, 0xf4, 0xef, 0xee, 0x8a, 0x29, 0xd0, 0xe7, 0xc4, 0x25, 0x92, 0x8a, 0xff, 0x36, 0xfc, 0xe4, 0x49}}}, {{{0xbd, 0x00, 0xb9, 0x04, 0x7d, 0x35, 0xfc, 0xeb, 0xd0, 0x0b, 0x05, 0x32, 0x52, 0x7a, 0x89, 0x24, 0x75, 0x50, 0xe1, 0x63, 0x02, 0x82, 0x8e, 0xe7, 0x85, 0x0c, 0xf2, 0x56, 0x44, 0x37, 0x83, 0x25}} , {{0x8f, 0xa1, 0xce, 0xcb, 0x60, 0xda, 0x12, 0x02, 0x1e, 0x29, 0x39, 0x2a, 0x03, 0xb7, 0xeb, 0x77, 0x40, 0xea, 0xc9, 0x2b, 0x2c, 0xd5, 0x7d, 0x7e, 0x2c, 0xc7, 0x5a, 0xfd, 0xff, 0xc4, 0xd1, 0x62}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x1d, 0x88, 0x98, 0x5b, 0x4e, 0xfc, 0x41, 0x24, 0x05, 0xe6, 0x50, 0x2b, 0xae, 0x96, 0x51, 0xd9, 0x6b, 0x72, 0xb2, 0x33, 0x42, 0x98, 0x68, 0xbb, 0x10, 0x5a, 0x7a, 0x8c, 0x9d, 0x07, 0xb4, 0x05}} , {{0x2f, 0x61, 0x9f, 0xd7, 0xa8, 0x3f, 0x83, 0x8c, 0x10, 0x69, 0x90, 0xe6, 0xcf, 0xd2, 0x63, 0xa3, 0xe4, 0x54, 0x7e, 0xe5, 0x69, 0x13, 0x1c, 0x90, 0x57, 0xaa, 0xe9, 0x53, 0x22, 0x43, 0x29, 0x23}}}, {{{0xe5, 0x1c, 0xf8, 0x0a, 0xfd, 0x2d, 0x7e, 0xf5, 0xf5, 0x70, 0x7d, 0x41, 0x6b, 0x11, 0xfe, 0xbe, 0x99, 0xd1, 0x55, 0x29, 0x31, 0xbf, 0xc0, 0x97, 0x6c, 0xd5, 0x35, 0xcc, 0x5e, 0x8b, 0xd9, 0x69}} , {{0x8e, 0x4e, 0x9f, 0x25, 0xf8, 0x81, 0x54, 0x2d, 0x0e, 0xd5, 0x54, 0x81, 0x9b, 0xa6, 0x92, 0xce, 0x4b, 0xe9, 0x8f, 0x24, 0x3b, 0xca, 0xe0, 0x44, 0xab, 0x36, 0xfe, 0xfb, 0x87, 0xd4, 0x26, 0x3e}}}, {{{0x0f, 0x93, 0x9c, 0x11, 0xe7, 0xdb, 0xf1, 0xf0, 0x85, 0x43, 0x28, 0x15, 0x37, 0xdd, 0xde, 0x27, 0xdf, 0xad, 0x3e, 0x49, 0x4f, 0xe0, 0x5b, 0xf6, 0x80, 0x59, 0x15, 0x3c, 0x85, 0xb7, 0x3e, 0x12}} , {{0xf5, 0xff, 0xcc, 0xf0, 0xb4, 0x12, 0x03, 0x5f, 0xc9, 0x84, 0xcb, 0x1d, 0x17, 0xe0, 0xbc, 0xcc, 0x03, 0x62, 0xa9, 0x8b, 0x94, 0xa6, 0xaa, 0x18, 0xcb, 0x27, 0x8d, 0x49, 0xa6, 0x17, 0x15, 0x07}}}, {{{0xd9, 0xb6, 0xd4, 0x9d, 0xd4, 0x6a, 0xaf, 0x70, 0x07, 0x2c, 0x10, 0x9e, 0xbd, 0x11, 0xad, 0xe4, 0x26, 0x33, 0x70, 0x92, 0x78, 0x1c, 0x74, 0x9f, 0x75, 0x60, 0x56, 0xf4, 0x39, 0xa8, 0xa8, 0x62}} , {{0x3b, 0xbf, 0x55, 0x35, 0x61, 0x8b, 0x44, 0x97, 0xe8, 0x3a, 0x55, 0xc1, 0xc8, 0x3b, 0xfd, 0x95, 0x29, 0x11, 0x60, 0x96, 0x1e, 0xcb, 0x11, 0x9d, 0xc2, 0x03, 0x8a, 0x1b, 0xc6, 0xd6, 0x45, 0x3d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x7e, 0x0e, 0x50, 0xb2, 0xcc, 0x0d, 0x6b, 0xa6, 0x71, 0x5b, 0x42, 0xed, 0xbd, 0xaf, 0xac, 0xf0, 0xfc, 0x12, 0xa2, 0x3f, 0x4e, 0xda, 0xe8, 0x11, 0xf3, 0x23, 0xe1, 0x04, 0x62, 0x03, 0x1c, 0x4e}} , {{0xc8, 0xb1, 0x1b, 0x6f, 0x73, 0x61, 0x3d, 0x27, 0x0d, 0x7d, 0x7a, 0x25, 0x5f, 0x73, 0x0e, 0x2f, 0x93, 0xf6, 0x24, 0xd8, 0x4f, 0x90, 0xac, 0xa2, 0x62, 0x0a, 0xf0, 0x61, 0xd9, 0x08, 0x59, 0x6a}}}, {{{0x6f, 0x2d, 0x55, 0xf8, 0x2f, 0x8e, 0xf0, 0x18, 0x3b, 0xea, 0xdd, 0x26, 0x72, 0xd1, 0xf5, 0xfe, 0xe5, 0xb8, 0xe6, 0xd3, 0x10, 0x48, 0x46, 0x49, 0x3a, 0x9f, 0x5e, 0x45, 0x6b, 0x90, 0xe8, 0x7f}} , {{0xd3, 0x76, 0x69, 0x33, 0x7b, 0xb9, 0x40, 0x70, 0xee, 0xa6, 0x29, 0x6b, 0xdd, 0xd0, 0x5d, 0x8d, 0xc1, 0x3e, 0x4a, 0xea, 0x37, 0xb1, 0x03, 0x02, 0x03, 0x35, 0xf1, 0x28, 0x9d, 0xff, 0x00, 0x13}}}, {{{0x7a, 0xdb, 0x12, 0xd2, 0x8a, 0x82, 0x03, 0x1b, 0x1e, 0xaf, 0xf9, 0x4b, 0x9c, 0xbe, 0xae, 0x7c, 0xe4, 0x94, 0x2a, 0x23, 0xb3, 0x62, 0x86, 0xe7, 0xfd, 0x23, 0xaa, 0x99, 0xbd, 0x2b, 0x11, 0x6c}} , {{0x8d, 0xa6, 0xd5, 0xac, 0x9d, 0xcc, 0x68, 0x75, 0x7f, 0xc3, 0x4d, 0x4b, 0xdd, 0x6c, 0xbb, 0x11, 0x5a, 0x60, 0xe5, 0xbd, 0x7d, 0x27, 0x8b, 0xda, 0xb4, 0x95, 0xf6, 0x03, 0x27, 0xa4, 0x92, 0x3f}}}, {{{0x22, 0xd6, 0xb5, 0x17, 0x84, 0xbf, 0x12, 0xcc, 0x23, 0x14, 0x4a, 0xdf, 0x14, 0x31, 0xbc, 0xa1, 0xac, 0x6e, 0xab, 0xfa, 0x57, 0x11, 0x53, 0xb3, 0x27, 0xe6, 0xf9, 0x47, 0x33, 0x44, 0x34, 0x1e}} , {{0x79, 0xfc, 0xa6, 0xb4, 0x0b, 0x35, 0x20, 0xc9, 0x4d, 0x22, 0x84, 0xc4, 0xa9, 0x20, 0xec, 0x89, 0x94, 0xba, 0x66, 0x56, 0x48, 0xb9, 0x87, 0x7f, 0xca, 0x1e, 0x06, 0xed, 0xa5, 0x55, 0x59, 0x29}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x56, 0xe1, 0xf5, 0xf1, 0xd5, 0xab, 0xa8, 0x2b, 0xae, 0x89, 0xf3, 0xcf, 0x56, 0x9f, 0xf2, 0x4b, 0x31, 0xbc, 0x18, 0xa9, 0x06, 0x5b, 0xbe, 0xb4, 0x61, 0xf8, 0xb2, 0x06, 0x9c, 0x81, 0xab, 0x4c}} , {{0x1f, 0x68, 0x76, 0x01, 0x16, 0x38, 0x2b, 0x0f, 0x77, 0x97, 0x92, 0x67, 0x4e, 0x86, 0x6a, 0x8b, 0xe5, 0xe8, 0x0c, 0xf7, 0x36, 0x39, 0xb5, 0x33, 0xe6, 0xcf, 0x5e, 0xbd, 0x18, 0xfb, 0x10, 0x1f}}}, {{{0x83, 0xf0, 0x0d, 0x63, 0xef, 0x53, 0x6b, 0xb5, 0x6b, 0xf9, 0x83, 0xcf, 0xde, 0x04, 0x22, 0x9b, 0x2c, 0x0a, 0xe0, 0xa5, 0xd8, 0xc7, 0x9c, 0xa5, 0xa3, 0xf6, 0x6f, 0xcf, 0x90, 0x6b, 0x68, 0x7c}} , {{0x33, 0x15, 0xd7, 0x7f, 0x1a, 0xd5, 0x21, 0x58, 0xc4, 0x18, 0xa5, 0xf0, 0xcc, 0x73, 0xa8, 0xfd, 0xfa, 0x18, 0xd1, 0x03, 0x91, 0x8d, 0x52, 0xd2, 0xa3, 0xa4, 0xd3, 0xb1, 0xea, 0x1d, 0x0f, 0x00}}}, {{{0xcc, 0x48, 0x83, 0x90, 0xe5, 0xfd, 0x3f, 0x84, 0xaa, 0xf9, 0x8b, 0x82, 0x59, 0x24, 0x34, 0x68, 0x4f, 0x1c, 0x23, 0xd9, 0xcc, 0x71, 0xe1, 0x7f, 0x8c, 0xaf, 0xf1, 0xee, 0x00, 0xb6, 0xa0, 0x77}} , {{0xf5, 0x1a, 0x61, 0xf7, 0x37, 0x9d, 0x00, 0xf4, 0xf2, 0x69, 0x6f, 0x4b, 0x01, 0x85, 0x19, 0x45, 0x4d, 0x7f, 0x02, 0x7c, 0x6a, 0x05, 0x47, 0x6c, 0x1f, 0x81, 0x20, 0xd4, 0xe8, 0x50, 0x27, 0x72}}}, {{{0x2c, 0x3a, 0xe5, 0xad, 0xf4, 0xdd, 0x2d, 0xf7, 0x5c, 0x44, 0xb5, 0x5b, 0x21, 0xa3, 0x89, 0x5f, 0x96, 0x45, 0xca, 0x4d, 0xa4, 0x21, 0x99, 0x70, 0xda, 0xc4, 0xc4, 0xa0, 0xe5, 0xf4, 0xec, 0x0a}} , {{0x07, 0x68, 0x21, 0x65, 0xe9, 0x08, 0xa0, 0x0b, 0x6a, 0x4a, 0xba, 0xb5, 0x80, 0xaf, 0xd0, 0x1b, 0xc5, 0xf5, 0x4b, 0x73, 0x50, 0x60, 0x2d, 0x71, 0x69, 0x61, 0x0e, 0xc0, 0x20, 0x40, 0x30, 0x19}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0x75, 0x57, 0x3b, 0xeb, 0x5c, 0x14, 0x56, 0x50, 0xc9, 0x4f, 0xb8, 0xb8, 0x1e, 0xa3, 0xf4, 0xab, 0xf5, 0xa9, 0x20, 0x15, 0x94, 0x82, 0xda, 0x96, 0x1c, 0x9b, 0x59, 0x8c, 0xff, 0xf4, 0x51}} , {{0xc1, 0x3a, 0x86, 0xd7, 0xb0, 0x06, 0x84, 0x7f, 0x1b, 0xbd, 0xd4, 0x07, 0x78, 0x80, 0x2e, 0xb1, 0xb4, 0xee, 0x52, 0x38, 0xee, 0x9a, 0xf9, 0xf6, 0xf3, 0x41, 0x6e, 0xd4, 0x88, 0x95, 0xac, 0x35}}}, {{{0x41, 0x97, 0xbf, 0x71, 0x6a, 0x9b, 0x72, 0xec, 0xf3, 0xf8, 0x6b, 0xe6, 0x0e, 0x6c, 0x69, 0xa5, 0x2f, 0x68, 0x52, 0xd8, 0x61, 0x81, 0xc0, 0x63, 0x3f, 0xa6, 0x3c, 0x13, 0x90, 0xe6, 0x8d, 0x56}} , {{0xe8, 0x39, 0x30, 0x77, 0x23, 0xb1, 0xfd, 0x1b, 0x3d, 0x3e, 0x74, 0x4d, 0x7f, 0xae, 0x5b, 0x3a, 0xb4, 0x65, 0x0e, 0x3a, 0x43, 0xdc, 0xdc, 0x41, 0x47, 0xe6, 0xe8, 0x92, 0x09, 0x22, 0x48, 0x4c}}}, {{{0x85, 0x57, 0x9f, 0xb5, 0xc8, 0x06, 0xb2, 0x9f, 0x47, 0x3f, 0xf0, 0xfa, 0xe6, 0xa9, 0xb1, 0x9b, 0x6f, 0x96, 0x7d, 0xf9, 0xa4, 0x65, 0x09, 0x75, 0x32, 0xa6, 0x6c, 0x7f, 0x47, 0x4b, 0x2f, 0x4f}} , {{0x34, 0xe9, 0x59, 0x93, 0x9d, 0x26, 0x80, 0x54, 0xf2, 0xcc, 0x3c, 0xc2, 0x25, 0x85, 0xe3, 0x6a, 0xc1, 0x62, 0x04, 0xa7, 0x08, 0x32, 0x6d, 0xa1, 0x39, 0x84, 0x8a, 0x3b, 0x87, 0x5f, 0x11, 0x13}}}, {{{0xda, 0x03, 0x34, 0x66, 0xc4, 0x0c, 0x73, 0x6e, 0xbc, 0x24, 0xb5, 0xf9, 0x70, 0x81, 0x52, 0xe9, 0xf4, 0x7c, 0x23, 0xdd, 0x9f, 0xb8, 0x46, 0xef, 0x1d, 0x22, 0x55, 0x7d, 0x71, 0xc4, 0x42, 0x33}} , {{0xc5, 0x37, 0x69, 0x5b, 0xa8, 0xc6, 0x9d, 0xa4, 0xfc, 0x61, 0x6e, 0x68, 0x46, 0xea, 0xd7, 0x1c, 0x67, 0xd2, 0x7d, 0xfa, 0xf1, 0xcc, 0x54, 0x8d, 0x36, 0x35, 0xc9, 0x00, 0xdf, 0x6c, 0x67, 0x50}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9a, 0x4d, 0x42, 0x29, 0x5d, 0xa4, 0x6b, 0x6f, 0xa8, 0x8a, 0x4d, 0x91, 0x7b, 0xd2, 0xdf, 0x36, 0xef, 0x01, 0x22, 0xc5, 0xcc, 0x8d, 0xeb, 0x58, 0x3d, 0xb3, 0x50, 0xfc, 0x8b, 0x97, 0x96, 0x33}} , {{0x93, 0x33, 0x07, 0xc8, 0x4a, 0xca, 0xd0, 0xb1, 0xab, 0xbd, 0xdd, 0xa7, 0x7c, 0xac, 0x3e, 0x45, 0xcb, 0xcc, 0x07, 0x91, 0xbf, 0x35, 0x9d, 0xcb, 0x7d, 0x12, 0x3c, 0x11, 0x59, 0x13, 0xcf, 0x5c}}}, {{{0x45, 0xb8, 0x41, 0xd7, 0xab, 0x07, 0x15, 0x00, 0x8e, 0xce, 0xdf, 0xb2, 0x43, 0x5c, 0x01, 0xdc, 0xf4, 0x01, 0x51, 0x95, 0x10, 0x5a, 0xf6, 0x24, 0x24, 0xa0, 0x19, 0x3a, 0x09, 0x2a, 0xaa, 0x3f}} , {{0xdc, 0x8e, 0xeb, 0xc6, 0xbf, 0xdd, 0x11, 0x7b, 0xe7, 0x47, 0xe6, 0xce, 0xe7, 0xb6, 0xc5, 0xe8, 0x8a, 0xdc, 0x4b, 0x57, 0x15, 0x3b, 0x66, 0xca, 0x89, 0xa3, 0xfd, 0xac, 0x0d, 0xe1, 0x1d, 0x7a}}}, {{{0x89, 0xef, 0xbf, 0x03, 0x75, 0xd0, 0x29, 0x50, 0xcb, 0x7d, 0xd6, 0xbe, 0xad, 0x5f, 0x7b, 0x00, 0x32, 0xaa, 0x98, 0xed, 0x3f, 0x8f, 0x92, 0xcb, 0x81, 0x56, 0x01, 0x63, 0x64, 0xa3, 0x38, 0x39}} , {{0x8b, 0xa4, 0xd6, 0x50, 0xb4, 0xaa, 0x5d, 0x64, 0x64, 0x76, 0x2e, 0xa1, 0xa6, 0xb3, 0xb8, 0x7c, 0x7a, 0x56, 0xf5, 0x5c, 0x4e, 0x84, 0x5c, 0xfb, 0xdd, 0xca, 0x48, 0x8b, 0x48, 0xb9, 0xba, 0x34}}}, {{{0xc5, 0xe3, 0xe8, 0xae, 0x17, 0x27, 0xe3, 0x64, 0x60, 0x71, 0x47, 0x29, 0x02, 0x0f, 0x92, 0x5d, 0x10, 0x93, 0xc8, 0x0e, 0xa1, 0xed, 0xba, 0xa9, 0x96, 0x1c, 0xc5, 0x76, 0x30, 0xcd, 0xf9, 0x30}} , {{0x95, 0xb0, 0xbd, 0x8c, 0xbc, 0xa7, 0x4f, 0x7e, 0xfd, 0x4e, 0x3a, 0xbf, 0x5f, 0x04, 0x79, 0x80, 0x2b, 0x5a, 0x9f, 0x4f, 0x68, 0x21, 0x19, 0x71, 0xc6, 0x20, 0x01, 0x42, 0xaa, 0xdf, 0xae, 0x2c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x90, 0x6e, 0x7e, 0x4b, 0x71, 0x93, 0xc0, 0x72, 0xed, 0xeb, 0x71, 0x24, 0x97, 0x26, 0x9c, 0xfe, 0xcb, 0x3e, 0x59, 0x19, 0xa8, 0x0f, 0x75, 0x7d, 0xbe, 0x18, 0xe6, 0x96, 0x1e, 0x95, 0x70, 0x60}} , {{0x89, 0x66, 0x3e, 0x1d, 0x4c, 0x5f, 0xfe, 0xc0, 0x04, 0x43, 0xd6, 0x44, 0x19, 0xb5, 0xad, 0xc7, 0x22, 0xdc, 0x71, 0x28, 0x64, 0xde, 0x41, 0x38, 0x27, 0x8f, 0x2c, 0x6b, 0x08, 0xb8, 0xb8, 0x7b}}}, {{{0x3d, 0x70, 0x27, 0x9d, 0xd9, 0xaf, 0xb1, 0x27, 0xaf, 0xe3, 0x5d, 0x1e, 0x3a, 0x30, 0x54, 0x61, 0x60, 0xe8, 0xc3, 0x26, 0x3a, 0xbc, 0x7e, 0xf5, 0x81, 0xdd, 0x64, 0x01, 0x04, 0xeb, 0xc0, 0x1e}} , {{0xda, 0x2c, 0xa4, 0xd1, 0xa1, 0xc3, 0x5c, 0x6e, 0x32, 0x07, 0x1f, 0xb8, 0x0e, 0x19, 0x9e, 0x99, 0x29, 0x33, 0x9a, 0xae, 0x7a, 0xed, 0x68, 0x42, 0x69, 0x7c, 0x07, 0xb3, 0x38, 0x2c, 0xf6, 0x3d}}}, {{{0x64, 0xaa, 0xb5, 0x88, 0x79, 0x65, 0x38, 0x8c, 0x94, 0xd6, 0x62, 0x37, 0x7d, 0x64, 0xcd, 0x3a, 0xeb, 0xff, 0xe8, 0x81, 0x09, 0xc7, 0x6a, 0x50, 0x09, 0x0d, 0x28, 0x03, 0x0d, 0x9a, 0x93, 0x0a}} , {{0x42, 0xa3, 0xf1, 0xc5, 0xb4, 0x0f, 0xd8, 0xc8, 0x8d, 0x15, 0x31, 0xbd, 0xf8, 0x07, 0x8b, 0xcd, 0x08, 0x8a, 0xfb, 0x18, 0x07, 0xfe, 0x8e, 0x52, 0x86, 0xef, 0xbe, 0xec, 0x49, 0x52, 0x99, 0x08}}}, {{{0x0f, 0xa9, 0xd5, 0x01, 0xaa, 0x48, 0x4f, 0x28, 0x66, 0x32, 0x1a, 0xba, 0x7c, 0xea, 0x11, 0x80, 0x17, 0x18, 0x9b, 0x56, 0x88, 0x25, 0x06, 0x69, 0x12, 0x2c, 0xea, 0x56, 0x69, 0x41, 0x24, 0x19}} , {{0xde, 0x21, 0xf0, 0xda, 0x8a, 0xfb, 0xb1, 0xb8, 0xcd, 0xc8, 0x6a, 0x82, 0x19, 0x73, 0xdb, 0xc7, 0xcf, 0x88, 0xeb, 0x96, 0xee, 0x6f, 0xfb, 0x06, 0xd2, 0xcd, 0x7d, 0x7b, 0x12, 0x28, 0x8e, 0x0c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x93, 0x44, 0x97, 0xce, 0x28, 0xff, 0x3a, 0x40, 0xc4, 0xf5, 0xf6, 0x9b, 0xf4, 0x6b, 0x07, 0x84, 0xfb, 0x98, 0xd8, 0xec, 0x8c, 0x03, 0x57, 0xec, 0x49, 0xed, 0x63, 0xb6, 0xaa, 0xff, 0x98, 0x28}} , {{0x3d, 0x16, 0x35, 0xf3, 0x46, 0xbc, 0xb3, 0xf4, 0xc6, 0xb6, 0x4f, 0xfa, 0xf4, 0xa0, 0x13, 0xe6, 0x57, 0x45, 0x93, 0xb9, 0xbc, 0xd6, 0x59, 0xe7, 0x77, 0x94, 0x6c, 0xab, 0x96, 0x3b, 0x4f, 0x09}}}, {{{0x5a, 0xf7, 0x6b, 0x01, 0x12, 0x4f, 0x51, 0xc1, 0x70, 0x84, 0x94, 0x47, 0xb2, 0x01, 0x6c, 0x71, 0xd7, 0xcc, 0x17, 0x66, 0x0f, 0x59, 0x5d, 0x5d, 0x10, 0x01, 0x57, 0x11, 0xf5, 0xdd, 0xe2, 0x34}} , {{0x26, 0xd9, 0x1f, 0x5c, 0x58, 0xac, 0x8b, 0x03, 0xd2, 0xc3, 0x85, 0x0f, 0x3a, 0xc3, 0x7f, 0x6d, 0x8e, 0x86, 0xcd, 0x52, 0x74, 0x8f, 0x55, 0x77, 0x17, 0xb7, 0x8e, 0xb7, 0x88, 0xea, 0xda, 0x1b}}}, {{{0xb6, 0xea, 0x0e, 0x40, 0x93, 0x20, 0x79, 0x35, 0x6a, 0x61, 0x84, 0x5a, 0x07, 0x6d, 0xf9, 0x77, 0x6f, 0xed, 0x69, 0x1c, 0x0d, 0x25, 0x76, 0xcc, 0xf0, 0xdb, 0xbb, 0xc5, 0xad, 0xe2, 0x26, 0x57}} , {{0xcf, 0xe8, 0x0e, 0x6b, 0x96, 0x7d, 0xed, 0x27, 0xd1, 0x3c, 0xa9, 0xd9, 0x50, 0xa9, 0x98, 0x84, 0x5e, 0x86, 0xef, 0xd6, 0xf0, 0xf8, 0x0e, 0x89, 0x05, 0x2f, 0xd9, 0x5f, 0x15, 0x5f, 0x73, 0x79}}}, {{{0xc8, 0x5c, 0x16, 0xfe, 0xed, 0x9f, 0x26, 0x56, 0xf6, 0x4b, 0x9f, 0xa7, 0x0a, 0x85, 0xfe, 0xa5, 0x8c, 0x87, 0xdd, 0x98, 0xce, 0x4e, 0xc3, 0x58, 0x55, 0xb2, 0x7b, 0x3d, 0xd8, 0x6b, 0xb5, 0x4c}} , {{0x65, 0x38, 0xa0, 0x15, 0xfa, 0xa7, 0xb4, 0x8f, 0xeb, 0xc4, 0x86, 0x9b, 0x30, 0xa5, 0x5e, 0x4d, 0xea, 0x8a, 0x9a, 0x9f, 0x1a, 0xd8, 0x5b, 0x53, 0x14, 0x19, 0x25, 0x63, 0xb4, 0x6f, 0x1f, 0x5d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xac, 0x8f, 0xbc, 0x1e, 0x7d, 0x8b, 0x5a, 0x0b, 0x8d, 0xaf, 0x76, 0x2e, 0x71, 0xe3, 0x3b, 0x6f, 0x53, 0x2f, 0x3e, 0x90, 0x95, 0xd4, 0x35, 0x14, 0x4f, 0x8c, 0x3c, 0xce, 0x57, 0x1c, 0x76, 0x49}} , {{0xa8, 0x50, 0xe1, 0x61, 0x6b, 0x57, 0x35, 0xeb, 0x44, 0x0b, 0x0c, 0x6e, 0xf9, 0x25, 0x80, 0x74, 0xf2, 0x8f, 0x6f, 0x7a, 0x3e, 0x7f, 0x2d, 0xf3, 0x4e, 0x09, 0x65, 0x10, 0x5e, 0x03, 0x25, 0x32}}}, {{{0xa9, 0x60, 0xdc, 0x0f, 0x64, 0xe5, 0x1d, 0xe2, 0x8d, 0x4f, 0x79, 0x2f, 0x0e, 0x24, 0x02, 0x00, 0x05, 0x77, 0x43, 0x25, 0x3d, 0x6a, 0xc7, 0xb7, 0xbf, 0x04, 0x08, 0x65, 0xf4, 0x39, 0x4b, 0x65}} , {{0x96, 0x19, 0x12, 0x6b, 0x6a, 0xb7, 0xe3, 0xdc, 0x45, 0x9b, 0xdb, 0xb4, 0xa8, 0xae, 0xdc, 0xa8, 0x14, 0x44, 0x65, 0x62, 0xce, 0x34, 0x9a, 0x84, 0x18, 0x12, 0x01, 0xf1, 0xe2, 0x7b, 0xce, 0x50}}}, {{{0x41, 0x21, 0x30, 0x53, 0x1b, 0x47, 0x01, 0xb7, 0x18, 0xd8, 0x82, 0x57, 0xbd, 0xa3, 0x60, 0xf0, 0x32, 0xf6, 0x5b, 0xf0, 0x30, 0x88, 0x91, 0x59, 0xfd, 0x90, 0xa2, 0xb9, 0x55, 0x93, 0x21, 0x34}} , {{0x97, 0x67, 0x9e, 0xeb, 0x6a, 0xf9, 0x6e, 0xd6, 0x73, 0xe8, 0x6b, 0x29, 0xec, 0x63, 0x82, 0x00, 0xa8, 0x99, 0x1c, 0x1d, 0x30, 0xc8, 0x90, 0x52, 0x90, 0xb6, 0x6a, 0x80, 0x4e, 0xff, 0x4b, 0x51}}}, {{{0x0f, 0x7d, 0x63, 0x8c, 0x6e, 0x5c, 0xde, 0x30, 0xdf, 0x65, 0xfa, 0x2e, 0xb0, 0xa3, 0x25, 0x05, 0x54, 0xbd, 0x25, 0xba, 0x06, 0xae, 0xdf, 0x8b, 0xd9, 0x1b, 0xea, 0x38, 0xb3, 0x05, 0x16, 0x09}} , {{0xc7, 0x8c, 0xbf, 0x64, 0x28, 0xad, 0xf8, 0xa5, 0x5a, 0x6f, 0xc9, 0xba, 0xd5, 0x7f, 0xd5, 0xd6, 0xbd, 0x66, 0x2f, 0x3d, 0xaa, 0x54, 0xf6, 0xba, 0x32, 0x22, 0x9a, 0x1e, 0x52, 0x05, 0xf4, 0x1d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xaa, 0x1f, 0xbb, 0xeb, 0xfe, 0xe4, 0x87, 0xfc, 0xb1, 0x2c, 0xb7, 0x88, 0xf4, 0xc6, 0xb9, 0xf5, 0x24, 0x46, 0xf2, 0xa5, 0x9f, 0x8f, 0x8a, 0x93, 0x70, 0x69, 0xd4, 0x56, 0xec, 0xfd, 0x06, 0x46}} , {{0x4e, 0x66, 0xcf, 0x4e, 0x34, 0xce, 0x0c, 0xd9, 0xa6, 0x50, 0xd6, 0x5e, 0x95, 0xaf, 0xe9, 0x58, 0xfa, 0xee, 0x9b, 0xb8, 0xa5, 0x0f, 0x35, 0xe0, 0x43, 0x82, 0x6d, 0x65, 0xe6, 0xd9, 0x00, 0x0f}}}, {{{0x7b, 0x75, 0x3a, 0xfc, 0x64, 0xd3, 0x29, 0x7e, 0xdd, 0x49, 0x9a, 0x59, 0x53, 0xbf, 0xb4, 0xa7, 0x52, 0xb3, 0x05, 0xab, 0xc3, 0xaf, 0x16, 0x1a, 0x85, 0x42, 0x32, 0xa2, 0x86, 0xfa, 0x39, 0x43}} , {{0x0e, 0x4b, 0xa3, 0x63, 0x8a, 0xfe, 0xa5, 0x58, 0xf1, 0x13, 0xbd, 0x9d, 0xaa, 0x7f, 0x76, 0x40, 0x70, 0x81, 0x10, 0x75, 0x99, 0xbb, 0xbe, 0x0b, 0x16, 0xe9, 0xba, 0x62, 0x34, 0xcc, 0x07, 0x6d}}}, {{{0xc3, 0xf1, 0xc6, 0x93, 0x65, 0xee, 0x0b, 0xbc, 0xea, 0x14, 0xf0, 0xc1, 0xf8, 0x84, 0x89, 0xc2, 0xc9, 0xd7, 0xea, 0x34, 0xca, 0xa7, 0xc4, 0x99, 0xd5, 0x50, 0x69, 0xcb, 0xd6, 0x21, 0x63, 0x7c}} , {{0x99, 0xeb, 0x7c, 0x31, 0x73, 0x64, 0x67, 0x7f, 0x0c, 0x66, 0xaa, 0x8c, 0x69, 0x91, 0xe2, 0x26, 0xd3, 0x23, 0xe2, 0x76, 0x5d, 0x32, 0x52, 0xdf, 0x5d, 0xc5, 0x8f, 0xb7, 0x7c, 0x84, 0xb3, 0x70}}}, {{{0xeb, 0x01, 0xc7, 0x36, 0x97, 0x4e, 0xb6, 0xab, 0x5f, 0x0d, 0x2c, 0xba, 0x67, 0x64, 0x55, 0xde, 0xbc, 0xff, 0xa6, 0xec, 0x04, 0xd3, 0x8d, 0x39, 0x56, 0x5e, 0xee, 0xf8, 0xe4, 0x2e, 0x33, 0x62}} , {{0x65, 0xef, 0xb8, 0x9f, 0xc8, 0x4b, 0xa7, 0xfd, 0x21, 0x49, 0x9b, 0x92, 0x35, 0x82, 0xd6, 0x0a, 0x9b, 0xf2, 0x79, 0xf1, 0x47, 0x2f, 0x6a, 0x7e, 0x9f, 0xcf, 0x18, 0x02, 0x3c, 0xfb, 0x1b, 0x3e}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2f, 0x8b, 0xc8, 0x40, 0x51, 0xd1, 0xac, 0x1a, 0x0b, 0xe4, 0xa9, 0xa2, 0x42, 0x21, 0x19, 0x2f, 0x7b, 0x97, 0xbf, 0xf7, 0x57, 0x6d, 0x3f, 0x3d, 0x4f, 0x0f, 0xe2, 0xb2, 0x81, 0x00, 0x9e, 0x7b}} , {{0x8c, 0x85, 0x2b, 0xc4, 0xfc, 0xf1, 0xab, 0xe8, 0x79, 0x22, 0xc4, 0x84, 0x17, 0x3a, 0xfa, 0x86, 0xa6, 0x7d, 0xf9, 0xf3, 0x6f, 0x03, 0x57, 0x20, 0x4d, 0x79, 0xf9, 0x6e, 0x71, 0x54, 0x38, 0x09}}}, {{{0x40, 0x29, 0x74, 0xa8, 0x2f, 0x5e, 0xf9, 0x79, 0xa4, 0xf3, 0x3e, 0xb9, 0xfd, 0x33, 0x31, 0xac, 0x9a, 0x69, 0x88, 0x1e, 0x77, 0x21, 0x2d, 0xf3, 0x91, 0x52, 0x26, 0x15, 0xb2, 0xa6, 0xcf, 0x7e}} , {{0xc6, 0x20, 0x47, 0x6c, 0xa4, 0x7d, 0xcb, 0x63, 0xea, 0x5b, 0x03, 0xdf, 0x3e, 0x88, 0x81, 0x6d, 0xce, 0x07, 0x42, 0x18, 0x60, 0x7e, 0x7b, 0x55, 0xfe, 0x6a, 0xf3, 0xda, 0x5c, 0x8b, 0x95, 0x10}}}, {{{0x62, 0xe4, 0x0d, 0x03, 0xb4, 0xd7, 0xcd, 0xfa, 0xbd, 0x46, 0xdf, 0x93, 0x71, 0x10, 0x2c, 0xa8, 0x3b, 0xb6, 0x09, 0x05, 0x70, 0x84, 0x43, 0x29, 0xa8, 0x59, 0xf5, 0x8e, 0x10, 0xe4, 0xd7, 0x20}} , {{0x57, 0x82, 0x1c, 0xab, 0xbf, 0x62, 0x70, 0xe8, 0xc4, 0xcf, 0xf0, 0x28, 0x6e, 0x16, 0x3c, 0x08, 0x78, 0x89, 0x85, 0x46, 0x0f, 0xf6, 0x7f, 0xcf, 0xcb, 0x7e, 0xb8, 0x25, 0xe9, 0x5a, 0xfa, 0x03}}}, {{{0xfb, 0x95, 0x92, 0x63, 0x50, 0xfc, 0x62, 0xf0, 0xa4, 0x5e, 0x8c, 0x18, 0xc2, 0x17, 0x24, 0xb7, 0x78, 0xc2, 0xa9, 0xe7, 0x6a, 0x32, 0xd6, 0x29, 0x85, 0xaf, 0xcb, 0x8d, 0x91, 0x13, 0xda, 0x6b}} , {{0x36, 0x0a, 0xc2, 0xb6, 0x4b, 0xa5, 0x5d, 0x07, 0x17, 0x41, 0x31, 0x5f, 0x62, 0x46, 0xf8, 0x92, 0xf9, 0x66, 0x48, 0x73, 0xa6, 0x97, 0x0d, 0x7d, 0x88, 0xee, 0x62, 0xb1, 0x03, 0xa8, 0x3f, 0x2c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x4a, 0xb1, 0x70, 0x8a, 0xa9, 0xe8, 0x63, 0x79, 0x00, 0xe2, 0x25, 0x16, 0xca, 0x4b, 0x0f, 0xa4, 0x66, 0xad, 0x19, 0x9f, 0x88, 0x67, 0x0c, 0x8b, 0xc2, 0x4a, 0x5b, 0x2b, 0x6d, 0x95, 0xaf, 0x19}} , {{0x8b, 0x9d, 0xb6, 0xcc, 0x60, 0xb4, 0x72, 0x4f, 0x17, 0x69, 0x5a, 0x4a, 0x68, 0x34, 0xab, 0xa1, 0x45, 0x32, 0x3c, 0x83, 0x87, 0x72, 0x30, 0x54, 0x77, 0x68, 0xae, 0xfb, 0xb5, 0x8b, 0x22, 0x5e}}}, {{{0xf1, 0xb9, 0x87, 0x35, 0xc5, 0xbb, 0xb9, 0xcf, 0xf5, 0xd6, 0xcd, 0xd5, 0x0c, 0x7c, 0x0e, 0xe6, 0x90, 0x34, 0xfb, 0x51, 0x42, 0x1e, 0x6d, 0xac, 0x9a, 0x46, 0xc4, 0x97, 0x29, 0x32, 0xbf, 0x45}} , {{0x66, 0x9e, 0xc6, 0x24, 0xc0, 0xed, 0xa5, 0x5d, 0x88, 0xd4, 0xf0, 0x73, 0x97, 0x7b, 0xea, 0x7f, 0x42, 0xff, 0x21, 0xa0, 0x9b, 0x2f, 0x9a, 0xfd, 0x53, 0x57, 0x07, 0x84, 0x48, 0x88, 0x9d, 0x52}}}, {{{0xc6, 0x96, 0x48, 0x34, 0x2a, 0x06, 0xaf, 0x94, 0x3d, 0xf4, 0x1a, 0xcf, 0xf2, 0xc0, 0x21, 0xc2, 0x42, 0x5e, 0xc8, 0x2f, 0x35, 0xa2, 0x3e, 0x29, 0xfa, 0x0c, 0x84, 0xe5, 0x89, 0x72, 0x7c, 0x06}} , {{0x32, 0x65, 0x03, 0xe5, 0x89, 0xa6, 0x6e, 0xb3, 0x5b, 0x8e, 0xca, 0xeb, 0xfe, 0x22, 0x56, 0x8b, 0x5d, 0x14, 0x4b, 0x4d, 0xf9, 0xbe, 0xb5, 0xf5, 0xe6, 0x5c, 0x7b, 0x8b, 0xf4, 0x13, 0x11, 0x34}}}, {{{0x07, 0xc6, 0x22, 0x15, 0xe2, 0x9c, 0x60, 0xa2, 0x19, 0xd9, 0x27, 0xae, 0x37, 0x4e, 0xa6, 0xc9, 0x80, 0xa6, 0x91, 0x8f, 0x12, 0x49, 0xe5, 0x00, 0x18, 0x47, 0xd1, 0xd7, 0x28, 0x22, 0x63, 0x39}} , {{0xe8, 0xe2, 0x00, 0x7e, 0xf2, 0x9e, 0x1e, 0x99, 0x39, 0x95, 0x04, 0xbd, 0x1e, 0x67, 0x7b, 0xb2, 0x26, 0xac, 0xe6, 0xaa, 0xe2, 0x46, 0xd5, 0xe4, 0xe8, 0x86, 0xbd, 0xab, 0x7c, 0x55, 0x59, 0x6f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x24, 0x64, 0x6e, 0x9b, 0x35, 0x71, 0x78, 0xce, 0x33, 0x03, 0x21, 0x33, 0x36, 0xf1, 0x73, 0x9b, 0xb9, 0x15, 0x8b, 0x2c, 0x69, 0xcf, 0x4d, 0xed, 0x4f, 0x4d, 0x57, 0x14, 0x13, 0x82, 0xa4, 0x4d}} , {{0x65, 0x6e, 0x0a, 0xa4, 0x59, 0x07, 0x17, 0xf2, 0x6b, 0x4a, 0x1f, 0x6e, 0xf6, 0xb5, 0xbc, 0x62, 0xe4, 0xb6, 0xda, 0xa2, 0x93, 0xbc, 0x29, 0x05, 0xd2, 0xd2, 0x73, 0x46, 0x03, 0x16, 0x40, 0x31}}}, {{{0x4c, 0x73, 0x6d, 0x15, 0xbd, 0xa1, 0x4d, 0x5c, 0x13, 0x0b, 0x24, 0x06, 0x98, 0x78, 0x1c, 0x5b, 0xeb, 0x1f, 0x18, 0x54, 0x43, 0xd9, 0x55, 0x66, 0xda, 0x29, 0x21, 0xe8, 0xb8, 0x3c, 0x42, 0x22}} , {{0xb4, 0xcd, 0x08, 0x6f, 0x15, 0x23, 0x1a, 0x0b, 0x22, 0xed, 0xd1, 0xf1, 0xa7, 0xc7, 0x73, 0x45, 0xf3, 0x9e, 0xce, 0x76, 0xb7, 0xf6, 0x39, 0xb6, 0x8e, 0x79, 0xbe, 0xe9, 0x9b, 0xcf, 0x7d, 0x62}}}, {{{0x92, 0x5b, 0xfc, 0x72, 0xfd, 0xba, 0xf1, 0xfd, 0xa6, 0x7c, 0x95, 0xe3, 0x61, 0x3f, 0xe9, 0x03, 0xd4, 0x2b, 0xd4, 0x20, 0xd9, 0xdb, 0x4d, 0x32, 0x3e, 0xf5, 0x11, 0x64, 0xe3, 0xb4, 0xbe, 0x32}} , {{0x86, 0x17, 0x90, 0xe7, 0xc9, 0x1f, 0x10, 0xa5, 0x6a, 0x2d, 0x39, 0xd0, 0x3b, 0xc4, 0xa6, 0xe9, 0x59, 0x13, 0xda, 0x1a, 0xe6, 0xa0, 0xb9, 0x3c, 0x50, 0xb8, 0x40, 0x7c, 0x15, 0x36, 0x5a, 0x42}}}, {{{0xb4, 0x0b, 0x32, 0xab, 0xdc, 0x04, 0x51, 0x55, 0x21, 0x1e, 0x0b, 0x75, 0x99, 0x89, 0x73, 0x35, 0x3a, 0x91, 0x2b, 0xfe, 0xe7, 0x49, 0xea, 0x76, 0xc1, 0xf9, 0x46, 0xb9, 0x53, 0x02, 0x23, 0x04}} , {{0xfc, 0x5a, 0x1e, 0x1d, 0x74, 0x58, 0x95, 0xa6, 0x8f, 0x7b, 0x97, 0x3e, 0x17, 0x3b, 0x79, 0x2d, 0xa6, 0x57, 0xef, 0x45, 0x02, 0x0b, 0x4d, 0x6e, 0x9e, 0x93, 0x8d, 0x2f, 0xd9, 0x9d, 0xdb, 0x04}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc0, 0xd7, 0x56, 0x97, 0x58, 0x91, 0xde, 0x09, 0x4f, 0x9f, 0xbe, 0x63, 0xb0, 0x83, 0x86, 0x43, 0x5d, 0xbc, 0xe0, 0xf3, 0xc0, 0x75, 0xbf, 0x8b, 0x8e, 0xaa, 0xf7, 0x8b, 0x64, 0x6e, 0xb0, 0x63}} , {{0x16, 0xae, 0x8b, 0xe0, 0x9b, 0x24, 0x68, 0x5c, 0x44, 0xc2, 0xd0, 0x08, 0xb7, 0x7b, 0x62, 0xfd, 0x7f, 0xd8, 0xd4, 0xb7, 0x50, 0xfd, 0x2c, 0x1b, 0xbf, 0x41, 0x95, 0xd9, 0x8e, 0xd8, 0x17, 0x1b}}}, {{{0x86, 0x55, 0x37, 0x8e, 0xc3, 0x38, 0x48, 0x14, 0xb5, 0x97, 0xd2, 0xa7, 0x54, 0x45, 0xf1, 0x35, 0x44, 0x38, 0x9e, 0xf1, 0x1b, 0xb6, 0x34, 0x00, 0x3c, 0x96, 0xee, 0x29, 0x00, 0xea, 0x2c, 0x0b}} , {{0xea, 0xda, 0x99, 0x9e, 0x19, 0x83, 0x66, 0x6d, 0xe9, 0x76, 0x87, 0x50, 0xd1, 0xfd, 0x3c, 0x60, 0x87, 0xc6, 0x41, 0xd9, 0x8e, 0xdb, 0x5e, 0xde, 0xaa, 0x9a, 0xd3, 0x28, 0xda, 0x95, 0xea, 0x47}}}, {{{0xd0, 0x80, 0xba, 0x19, 0xae, 0x1d, 0xa9, 0x79, 0xf6, 0x3f, 0xac, 0x5d, 0x6f, 0x96, 0x1f, 0x2a, 0xce, 0x29, 0xb2, 0xff, 0x37, 0xf1, 0x94, 0x8f, 0x0c, 0xb5, 0x28, 0xba, 0x9a, 0x21, 0xf6, 0x66}} , {{0x02, 0xfb, 0x54, 0xb8, 0x05, 0xf3, 0x81, 0x52, 0x69, 0x34, 0x46, 0x9d, 0x86, 0x76, 0x8f, 0xd7, 0xf8, 0x6a, 0x66, 0xff, 0xe6, 0xa7, 0x90, 0xf7, 0x5e, 0xcd, 0x6a, 0x9b, 0x55, 0xfc, 0x9d, 0x48}}}, {{{0xbd, 0xaa, 0x13, 0xe6, 0xcd, 0x45, 0x4a, 0xa4, 0x59, 0x0a, 0x64, 0xb1, 0x98, 0xd6, 0x34, 0x13, 0x04, 0xe6, 0x97, 0x94, 0x06, 0xcb, 0xd4, 0x4e, 0xbb, 0x96, 0xcd, 0xd1, 0x57, 0xd1, 0xe3, 0x06}} , {{0x7a, 0x6c, 0x45, 0x27, 0xc4, 0x93, 0x7f, 0x7d, 0x7c, 0x62, 0x50, 0x38, 0x3a, 0x6b, 0xb5, 0x88, 0xc6, 0xd9, 0xf1, 0x78, 0x19, 0xb9, 0x39, 0x93, 0x3d, 0xc9, 0xe0, 0x9c, 0x3c, 0xce, 0xf5, 0x72}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x24, 0xea, 0x23, 0x7d, 0x56, 0x2c, 0xe2, 0x59, 0x0e, 0x85, 0x60, 0x04, 0x88, 0x5a, 0x74, 0x1e, 0x4b, 0xef, 0x13, 0xda, 0x4c, 0xff, 0x83, 0x45, 0x85, 0x3f, 0x08, 0x95, 0x2c, 0x20, 0x13, 0x1f}} , {{0x48, 0x5f, 0x27, 0x90, 0x5c, 0x02, 0x42, 0xad, 0x78, 0x47, 0x5c, 0xb5, 0x7e, 0x08, 0x85, 0x00, 0xfa, 0x7f, 0xfd, 0xfd, 0xe7, 0x09, 0x11, 0xf2, 0x7e, 0x1b, 0x38, 0x6c, 0x35, 0x6d, 0x33, 0x66}}}, {{{0x93, 0x03, 0x36, 0x81, 0xac, 0xe4, 0x20, 0x09, 0x35, 0x4c, 0x45, 0xb2, 0x1e, 0x4c, 0x14, 0x21, 0xe6, 0xe9, 0x8a, 0x7b, 0x8d, 0xfe, 0x1e, 0xc6, 0x3e, 0xc1, 0x35, 0xfa, 0xe7, 0x70, 0x4e, 0x1d}} , {{0x61, 0x2e, 0xc2, 0xdd, 0x95, 0x57, 0xd1, 0xab, 0x80, 0xe8, 0x63, 0x17, 0xb5, 0x48, 0xe4, 0x8a, 0x11, 0x9e, 0x72, 0xbe, 0x85, 0x8d, 0x51, 0x0a, 0xf2, 0x9f, 0xe0, 0x1c, 0xa9, 0x07, 0x28, 0x7b}}}, {{{0xbb, 0x71, 0x14, 0x5e, 0x26, 0x8c, 0x3d, 0xc8, 0xe9, 0x7c, 0xd3, 0xd6, 0xd1, 0x2f, 0x07, 0x6d, 0xe6, 0xdf, 0xfb, 0x79, 0xd6, 0x99, 0x59, 0x96, 0x48, 0x40, 0x0f, 0x3a, 0x7b, 0xb2, 0xa0, 0x72}} , {{0x4e, 0x3b, 0x69, 0xc8, 0x43, 0x75, 0x51, 0x6c, 0x79, 0x56, 0xe4, 0xcb, 0xf7, 0xa6, 0x51, 0xc2, 0x2c, 0x42, 0x0b, 0xd4, 0x82, 0x20, 0x1c, 0x01, 0x08, 0x66, 0xd7, 0xbf, 0x04, 0x56, 0xfc, 0x02}}}, {{{0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2, 0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95, 0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c}} , {{0x6b, 0xa6, 0xf5, 0x4b, 0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90, 0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52, 0xe6, 0x99, 0x2c, 0x5f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x85, 0xe0, 0x24, 0x32, 0xb4, 0xd1, 0xef, 0xfc, 0x69, 0xa2, 0xbf, 0x8f, 0x72, 0x2c, 0x95, 0xf6, 0xe4, 0x6e, 0x7d, 0x90, 0xf7, 0x57, 0x81, 0xa0, 0xf7, 0xda, 0xef, 0x33, 0x07, 0xe3, 0x6b, 0x78}} , {{0x36, 0x27, 0x3e, 0xc6, 0x12, 0x07, 0xab, 0x4e, 0xbe, 0x69, 0x9d, 0xb3, 0xbe, 0x08, 0x7c, 0x2a, 0x47, 0x08, 0xfd, 0xd4, 0xcd, 0x0e, 0x27, 0x34, 0x5b, 0x98, 0x34, 0x2f, 0x77, 0x5f, 0x3a, 0x65}}}, {{{0x13, 0xaa, 0x2e, 0x4c, 0xf0, 0x22, 0xb8, 0x6c, 0xb3, 0x19, 0x4d, 0xeb, 0x6b, 0xd0, 0xa4, 0xc6, 0x9c, 0xdd, 0xc8, 0x5b, 0x81, 0x57, 0x89, 0xdf, 0x33, 0xa9, 0x68, 0x49, 0x80, 0xe4, 0xfe, 0x21}} , {{0x00, 0x17, 0x90, 0x30, 0xe9, 0xd3, 0x60, 0x30, 0x31, 0xc2, 0x72, 0x89, 0x7a, 0x36, 0xa5, 0xbd, 0x39, 0x83, 0x85, 0x50, 0xa1, 0x5d, 0x6c, 0x41, 0x1d, 0xb5, 0x2c, 0x07, 0x40, 0x77, 0x0b, 0x50}}}, {{{0x64, 0x34, 0xec, 0xc0, 0x9e, 0x44, 0x41, 0xaf, 0xa0, 0x36, 0x05, 0x6d, 0xea, 0x30, 0x25, 0x46, 0x35, 0x24, 0x9d, 0x86, 0xbd, 0x95, 0xf1, 0x6a, 0x46, 0xd7, 0x94, 0x54, 0xf9, 0x3b, 0xbd, 0x5d}} , {{0x77, 0x5b, 0xe2, 0x37, 0xc7, 0xe1, 0x7c, 0x13, 0x8c, 0x9f, 0x7b, 0x7b, 0x2a, 0xce, 0x42, 0xa3, 0xb9, 0x2a, 0x99, 0xa8, 0xc0, 0xd8, 0x3c, 0x86, 0xb0, 0xfb, 0xe9, 0x76, 0x77, 0xf7, 0xf5, 0x56}}}, {{{0xdf, 0xb3, 0x46, 0x11, 0x6e, 0x13, 0xb7, 0x28, 0x4e, 0x56, 0xdd, 0xf1, 0xac, 0xad, 0x58, 0xc3, 0xf8, 0x88, 0x94, 0x5e, 0x06, 0x98, 0xa1, 0xe4, 0x6a, 0xfb, 0x0a, 0x49, 0x5d, 0x8a, 0xfe, 0x77}} , {{0x46, 0x02, 0xf5, 0xa5, 0xaf, 0xc5, 0x75, 0x6d, 0xba, 0x45, 0x35, 0x0a, 0xfe, 0xc9, 0xac, 0x22, 0x91, 0x8d, 0x21, 0x95, 0x33, 0x03, 0xc0, 0x8a, 0x16, 0xf3, 0x39, 0xe0, 0x01, 0x0f, 0x53, 0x3c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x34, 0x75, 0x37, 0x1f, 0x34, 0x4e, 0xa9, 0x1d, 0x68, 0x67, 0xf8, 0x49, 0x98, 0x96, 0xfc, 0x4c, 0x65, 0x97, 0xf7, 0x02, 0x4a, 0x52, 0x6c, 0x01, 0xbd, 0x48, 0xbb, 0x1b, 0xed, 0xa4, 0xe2, 0x53}} , {{0x59, 0xd5, 0x9b, 0x5a, 0xa2, 0x90, 0xd3, 0xb8, 0x37, 0x4c, 0x55, 0x82, 0x28, 0x08, 0x0f, 0x7f, 0xaa, 0x81, 0x65, 0xe0, 0x0c, 0x52, 0xc9, 0xa3, 0x32, 0x27, 0x64, 0xda, 0xfd, 0x34, 0x23, 0x5a}}}, {{{0xb5, 0xb0, 0x0c, 0x4d, 0xb3, 0x7b, 0x23, 0xc8, 0x1f, 0x8a, 0x39, 0x66, 0xe6, 0xba, 0x4c, 0x10, 0x37, 0xca, 0x9c, 0x7c, 0x05, 0x9e, 0xff, 0xc0, 0xf8, 0x8e, 0xb1, 0x8f, 0x6f, 0x67, 0x18, 0x26}} , {{0x4b, 0x41, 0x13, 0x54, 0x23, 0x1a, 0xa4, 0x4e, 0xa9, 0x8b, 0x1e, 0x4b, 0xfc, 0x15, 0x24, 0xbb, 0x7e, 0xcb, 0xb6, 0x1e, 0x1b, 0xf5, 0xf2, 0xc8, 0x56, 0xec, 0x32, 0xa2, 0x60, 0x5b, 0xa0, 0x2a}}}, {{{0xa4, 0x29, 0x47, 0x86, 0x2e, 0x92, 0x4f, 0x11, 0x4f, 0xf3, 0xb2, 0x5c, 0xd5, 0x3e, 0xa6, 0xb9, 0xc8, 0xe2, 0x33, 0x11, 0x1f, 0x01, 0x8f, 0xb0, 0x9b, 0xc7, 0xa5, 0xff, 0x83, 0x0f, 0x1e, 0x28}} , {{0x1d, 0x29, 0x7a, 0xa1, 0xec, 0x8e, 0xb5, 0xad, 0xea, 0x02, 0x68, 0x60, 0x74, 0x29, 0x1c, 0xa5, 0xcf, 0xc8, 0x3b, 0x7d, 0x8b, 0x2b, 0x7c, 0xad, 0xa4, 0x40, 0x17, 0x51, 0x59, 0x7c, 0x2e, 0x5d}}}, {{{0x0a, 0x6c, 0x4f, 0xbc, 0x3e, 0x32, 0xe7, 0x4a, 0x1a, 0x13, 0xc1, 0x49, 0x38, 0xbf, 0xf7, 0xc2, 0xd3, 0x8f, 0x6b, 0xad, 0x52, 0xf7, 0xcf, 0xbc, 0x27, 0xcb, 0x40, 0x67, 0x76, 0xcd, 0x6d, 0x56}} , {{0xe5, 0xb0, 0x27, 0xad, 0xbe, 0x9b, 0xf2, 0xb5, 0x63, 0xde, 0x3a, 0x23, 0x95, 0xb7, 0x0a, 0x7e, 0xf3, 0x9e, 0x45, 0x6f, 0x19, 0x39, 0x75, 0x8f, 0x39, 0x3d, 0x0f, 0xc0, 0x9f, 0xf1, 0xe9, 0x51}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x88, 0xaa, 0x14, 0x24, 0x86, 0x94, 0x11, 0x12, 0x3e, 0x1a, 0xb5, 0xcc, 0xbb, 0xe0, 0x9c, 0xd5, 0x9c, 0x6d, 0xba, 0x58, 0x72, 0x8d, 0xfb, 0x22, 0x7b, 0x9f, 0x7c, 0x94, 0x30, 0xb3, 0x51, 0x21}} , {{0xf6, 0x74, 0x3d, 0xf2, 0xaf, 0xd0, 0x1e, 0x03, 0x7c, 0x23, 0x6b, 0xc9, 0xfc, 0x25, 0x70, 0x90, 0xdc, 0x9a, 0xa4, 0xfb, 0x49, 0xfc, 0x3d, 0x0a, 0x35, 0x38, 0x6f, 0xe4, 0x7e, 0x50, 0x01, 0x2a}}}, {{{0xd6, 0xe3, 0x96, 0x61, 0x3a, 0xfd, 0xef, 0x9b, 0x1f, 0x90, 0xa4, 0x24, 0x14, 0x5b, 0xc8, 0xde, 0x50, 0xb1, 0x1d, 0xaf, 0xe8, 0x55, 0x8a, 0x87, 0x0d, 0xfe, 0xaa, 0x3b, 0x82, 0x2c, 0x8d, 0x7b}} , {{0x85, 0x0c, 0xaf, 0xf8, 0x83, 0x44, 0x49, 0xd9, 0x45, 0xcf, 0xf7, 0x48, 0xd9, 0x53, 0xb4, 0xf1, 0x65, 0xa0, 0xe1, 0xc3, 0xb3, 0x15, 0xed, 0x89, 0x9b, 0x4f, 0x62, 0xb3, 0x57, 0xa5, 0x45, 0x1c}}}, {{{0x8f, 0x12, 0xea, 0xaf, 0xd1, 0x1f, 0x79, 0x10, 0x0b, 0xf6, 0xa3, 0x7b, 0xea, 0xac, 0x8b, 0x57, 0x32, 0x62, 0xe7, 0x06, 0x12, 0x51, 0xa0, 0x3b, 0x43, 0x5e, 0xa4, 0x20, 0x78, 0x31, 0xce, 0x0d}} , {{0x84, 0x7c, 0xc2, 0xa6, 0x91, 0x23, 0xce, 0xbd, 0xdc, 0xf9, 0xce, 0xd5, 0x75, 0x30, 0x22, 0xe6, 0xf9, 0x43, 0x62, 0x0d, 0xf7, 0x75, 0x9d, 0x7f, 0x8c, 0xff, 0x7d, 0xe4, 0x72, 0xac, 0x9f, 0x1c}}}, {{{0x88, 0xc1, 0x99, 0xd0, 0x3c, 0x1c, 0x5d, 0xb4, 0xef, 0x13, 0x0f, 0x90, 0xb9, 0x36, 0x2f, 0x95, 0x95, 0xc6, 0xdc, 0xde, 0x0a, 0x51, 0xe2, 0x8d, 0xf3, 0xbc, 0x51, 0xec, 0xdf, 0xb1, 0xa2, 0x5f}} , {{0x2e, 0x68, 0xa1, 0x23, 0x7d, 0x9b, 0x40, 0x69, 0x85, 0x7b, 0x42, 0xbf, 0x90, 0x4b, 0xd6, 0x40, 0x2f, 0xd7, 0x52, 0x52, 0xb2, 0x21, 0xde, 0x64, 0xbd, 0x88, 0xc3, 0x6d, 0xa5, 0xfa, 0x81, 0x3f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xfb, 0xfd, 0x47, 0x7b, 0x8a, 0x66, 0x9e, 0x79, 0x2e, 0x64, 0x82, 0xef, 0xf7, 0x21, 0xec, 0xf6, 0xd8, 0x86, 0x09, 0x31, 0x7c, 0xdd, 0x03, 0x6a, 0x58, 0xa0, 0x77, 0xb7, 0x9b, 0x8c, 0x87, 0x1f}} , {{0x55, 0x47, 0xe4, 0xa8, 0x3d, 0x55, 0x21, 0x34, 0xab, 0x1d, 0xae, 0xe0, 0xf4, 0xea, 0xdb, 0xc5, 0xb9, 0x58, 0xbf, 0xc4, 0x2a, 0x89, 0x31, 0x1a, 0xf4, 0x2d, 0xe1, 0xca, 0x37, 0x99, 0x47, 0x59}}}, {{{0xc7, 0xca, 0x63, 0xc1, 0x49, 0xa9, 0x35, 0x45, 0x55, 0x7e, 0xda, 0x64, 0x32, 0x07, 0x50, 0xf7, 0x32, 0xac, 0xde, 0x75, 0x58, 0x9b, 0x11, 0xb2, 0x3a, 0x1f, 0xf5, 0xf7, 0x79, 0x04, 0xe6, 0x08}} , {{0x46, 0xfa, 0x22, 0x4b, 0xfa, 0xe1, 0xfe, 0x96, 0xfc, 0x67, 0xba, 0x67, 0x97, 0xc4, 0xe7, 0x1b, 0x86, 0x90, 0x5f, 0xee, 0xf4, 0x5b, 0x11, 0xb2, 0xcd, 0xad, 0xee, 0xc2, 0x48, 0x6c, 0x2b, 0x1b}}}, {{{0xe3, 0x39, 0x62, 0xb4, 0x4f, 0x31, 0x04, 0xc9, 0xda, 0xd5, 0x73, 0x51, 0x57, 0xc5, 0xb8, 0xf3, 0xa3, 0x43, 0x70, 0xe4, 0x61, 0x81, 0x84, 0xe2, 0xbb, 0xbf, 0x4f, 0x9e, 0xa4, 0x5e, 0x74, 0x06}} , {{0x29, 0xac, 0xff, 0x27, 0xe0, 0x59, 0xbe, 0x39, 0x9c, 0x0d, 0x83, 0xd7, 0x10, 0x0b, 0x15, 0xb7, 0xe1, 0xc2, 0x2c, 0x30, 0x73, 0x80, 0x3a, 0x7d, 0x5d, 0xab, 0x58, 0x6b, 0xc1, 0xf0, 0xf4, 0x22}}}, {{{0xfe, 0x7f, 0xfb, 0x35, 0x7d, 0xc6, 0x01, 0x23, 0x28, 0xc4, 0x02, 0xac, 0x1f, 0x42, 0xb4, 0x9d, 0xfc, 0x00, 0x94, 0xa5, 0xee, 0xca, 0xda, 0x97, 0x09, 0x41, 0x77, 0x87, 0x5d, 0x7b, 0x87, 0x78}} , {{0xf5, 0xfb, 0x90, 0x2d, 0x81, 0x19, 0x9e, 0x2f, 0x6d, 0x85, 0x88, 0x8c, 0x40, 0x5c, 0x77, 0x41, 0x4d, 0x01, 0x19, 0x76, 0x60, 0xe8, 0x4c, 0x48, 0xe4, 0x33, 0x83, 0x32, 0x6c, 0xb4, 0x41, 0x03}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xff, 0x10, 0xc2, 0x09, 0x4f, 0x6e, 0xf4, 0xd2, 0xdf, 0x7e, 0xca, 0x7b, 0x1c, 0x1d, 0xba, 0xa3, 0xb6, 0xda, 0x67, 0x33, 0xd4, 0x87, 0x36, 0x4b, 0x11, 0x20, 0x05, 0xa6, 0x29, 0xc1, 0x87, 0x17}} , {{0xf6, 0x96, 0xca, 0x2f, 0xda, 0x38, 0xa7, 0x1b, 0xfc, 0xca, 0x7d, 0xfe, 0x08, 0x89, 0xe2, 0x47, 0x2b, 0x6a, 0x5d, 0x4b, 0xfa, 0xa1, 0xb4, 0xde, 0xb6, 0xc2, 0x31, 0x51, 0xf5, 0xe0, 0xa4, 0x0b}}}, {{{0x5c, 0xe5, 0xc6, 0x04, 0x8e, 0x2b, 0x57, 0xbe, 0x38, 0x85, 0x23, 0xcb, 0xb7, 0xbe, 0x4f, 0xa9, 0xd3, 0x6e, 0x12, 0xaa, 0xd5, 0xb2, 0x2e, 0x93, 0x29, 0x9a, 0x4a, 0x88, 0x18, 0x43, 0xf5, 0x01}} , {{0x50, 0xfc, 0xdb, 0xa2, 0x59, 0x21, 0x8d, 0xbd, 0x7e, 0x33, 0xae, 0x2f, 0x87, 0x1a, 0xd0, 0x97, 0xc7, 0x0d, 0x4d, 0x63, 0x01, 0xef, 0x05, 0x84, 0xec, 0x40, 0xdd, 0xa8, 0x0a, 0x4f, 0x70, 0x0b}}}, {{{0x41, 0x69, 0x01, 0x67, 0x5c, 0xd3, 0x8a, 0xc5, 0xcf, 0x3f, 0xd1, 0x57, 0xd1, 0x67, 0x3e, 0x01, 0x39, 0xb5, 0xcb, 0x81, 0x56, 0x96, 0x26, 0xb6, 0xc2, 0xe7, 0x5c, 0xfb, 0x63, 0x97, 0x58, 0x06}} , {{0x0c, 0x0e, 0xf3, 0xba, 0xf0, 0xe5, 0xba, 0xb2, 0x57, 0x77, 0xc6, 0x20, 0x9b, 0x89, 0x24, 0xbe, 0xf2, 0x9c, 0x8a, 0xba, 0x69, 0xc1, 0xf1, 0xb0, 0x4f, 0x2a, 0x05, 0x9a, 0xee, 0x10, 0x7e, 0x36}}}, {{{0x3f, 0x26, 0xe9, 0x40, 0xe9, 0x03, 0xad, 0x06, 0x69, 0x91, 0xe0, 0xd1, 0x89, 0x60, 0x84, 0x79, 0xde, 0x27, 0x6d, 0xe6, 0x76, 0xbd, 0xea, 0xe6, 0xae, 0x48, 0xc3, 0x67, 0xc0, 0x57, 0xcd, 0x2f}} , {{0x7f, 0xc1, 0xdc, 0xb9, 0xc7, 0xbc, 0x86, 0x3d, 0x55, 0x4b, 0x28, 0x7a, 0xfb, 0x4d, 0xc7, 0xf8, 0xbc, 0x67, 0x2a, 0x60, 0x4d, 0x8f, 0x07, 0x0b, 0x1a, 0x17, 0xbf, 0xfa, 0xac, 0xa7, 0x3d, 0x1a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x91, 0x3f, 0xed, 0x5e, 0x18, 0x78, 0x3f, 0x23, 0x2c, 0x0d, 0x8c, 0x44, 0x00, 0xe8, 0xfb, 0xe9, 0x8e, 0xd6, 0xd1, 0x36, 0x58, 0x57, 0x9e, 0xae, 0x4b, 0x5c, 0x0b, 0x07, 0xbc, 0x6b, 0x55, 0x2b}} , {{0x6f, 0x4d, 0x17, 0xd7, 0xe1, 0x84, 0xd9, 0x78, 0xb1, 0x90, 0xfd, 0x2e, 0xb3, 0xb5, 0x19, 0x3f, 0x1b, 0xfa, 0xc0, 0x68, 0xb3, 0xdd, 0x00, 0x2e, 0x89, 0xbd, 0x7e, 0x80, 0x32, 0x13, 0xa0, 0x7b}}}, {{{0x1a, 0x6f, 0x40, 0xaf, 0x44, 0x44, 0xb0, 0x43, 0x8f, 0x0d, 0xd0, 0x1e, 0xc4, 0x0b, 0x19, 0x5d, 0x8e, 0xfe, 0xc1, 0xf3, 0xc5, 0x5c, 0x91, 0xf8, 0x04, 0x4e, 0xbe, 0x90, 0xb4, 0x47, 0x5c, 0x3f}} , {{0xb0, 0x3b, 0x2c, 0xf3, 0xfe, 0x32, 0x71, 0x07, 0x3f, 0xaa, 0xba, 0x45, 0x60, 0xa8, 0x8d, 0xea, 0x54, 0xcb, 0x39, 0x10, 0xb4, 0xf2, 0x8b, 0xd2, 0x14, 0x82, 0x42, 0x07, 0x8e, 0xe9, 0x7c, 0x53}}}, {{{0xb0, 0xae, 0xc1, 0x8d, 0xc9, 0x8f, 0xb9, 0x7a, 0x77, 0xef, 0xba, 0x79, 0xa0, 0x3c, 0xa8, 0xf5, 0x6a, 0xe2, 0x3f, 0x5d, 0x00, 0xe3, 0x4b, 0x45, 0x24, 0x7b, 0x43, 0x78, 0x55, 0x1d, 0x2b, 0x1e}} , {{0x01, 0xb8, 0xd6, 0x16, 0x67, 0xa0, 0x15, 0xb9, 0xe1, 0x58, 0xa4, 0xa7, 0x31, 0x37, 0x77, 0x2f, 0x8b, 0x12, 0x9f, 0xf4, 0x3f, 0xc7, 0x36, 0x66, 0xd2, 0xa8, 0x56, 0xf7, 0x7f, 0x74, 0xc6, 0x41}}}, {{{0x5d, 0xf8, 0xb4, 0xa8, 0x30, 0xdd, 0xcc, 0x38, 0xa5, 0xd3, 0xca, 0xd8, 0xd1, 0xf8, 0xb2, 0x31, 0x91, 0xd4, 0x72, 0x05, 0x57, 0x4a, 0x3b, 0x82, 0x4a, 0xc6, 0x68, 0x20, 0xe2, 0x18, 0x41, 0x61}} , {{0x19, 0xd4, 0x8d, 0x47, 0x29, 0x12, 0x65, 0xb0, 0x11, 0x78, 0x47, 0xb5, 0xcb, 0xa3, 0xa5, 0xfa, 0x05, 0x85, 0x54, 0xa9, 0x33, 0x97, 0x8d, 0x2b, 0xc2, 0xfe, 0x99, 0x35, 0x28, 0xe5, 0xeb, 0x63}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xb1, 0x3f, 0x3f, 0xef, 0xd8, 0xf4, 0xfc, 0xb3, 0xa0, 0x60, 0x50, 0x06, 0x2b, 0x29, 0x52, 0x70, 0x15, 0x0b, 0x24, 0x24, 0xf8, 0x5f, 0x79, 0x18, 0xcc, 0xff, 0x89, 0x99, 0x84, 0xa1, 0xae, 0x13}} , {{0x44, 0x1f, 0xb8, 0xc2, 0x01, 0xc1, 0x30, 0x19, 0x55, 0x05, 0x60, 0x10, 0xa4, 0x6c, 0x2d, 0x67, 0x70, 0xe5, 0x25, 0x1b, 0xf2, 0xbf, 0xdd, 0xfb, 0x70, 0x2b, 0xa1, 0x8c, 0x9c, 0x94, 0x84, 0x08}}}, {{{0xe7, 0xc4, 0x43, 0x4d, 0xc9, 0x2b, 0x69, 0x5d, 0x1d, 0x3c, 0xaf, 0xbb, 0x43, 0x38, 0x4e, 0x98, 0x3d, 0xed, 0x0d, 0x21, 0x03, 0xfd, 0xf0, 0x99, 0x47, 0x04, 0xb0, 0x98, 0x69, 0x55, 0x72, 0x0f}} , {{0x5e, 0xdf, 0x15, 0x53, 0x3b, 0x86, 0x80, 0xb0, 0xf1, 0x70, 0x68, 0x8f, 0x66, 0x7c, 0x0e, 0x49, 0x1a, 0xd8, 0x6b, 0xfe, 0x4e, 0xef, 0xca, 0x47, 0xd4, 0x03, 0xc1, 0x37, 0x50, 0x9c, 0xc1, 0x16}}}, {{{0xcd, 0x24, 0xc6, 0x3e, 0x0c, 0x82, 0x9b, 0x91, 0x2b, 0x61, 0x4a, 0xb2, 0x0f, 0x88, 0x55, 0x5f, 0x5a, 0x57, 0xff, 0xe5, 0x74, 0x0b, 0x13, 0x43, 0x00, 0xd8, 0x6b, 0xcf, 0xd2, 0x15, 0x03, 0x2c}} , {{0xdc, 0xff, 0x15, 0x61, 0x2f, 0x4a, 0x2f, 0x62, 0xf2, 0x04, 0x2f, 0xb5, 0x0c, 0xb7, 0x1e, 0x3f, 0x74, 0x1a, 0x0f, 0xd7, 0xea, 0xcd, 0xd9, 0x7d, 0xf6, 0x12, 0x0e, 0x2f, 0xdb, 0x5a, 0x3b, 0x16}}}, {{{0x1b, 0x37, 0x47, 0xe3, 0xf5, 0x9e, 0xea, 0x2c, 0x2a, 0xe7, 0x82, 0x36, 0xf4, 0x1f, 0x81, 0x47, 0x92, 0x4b, 0x69, 0x0e, 0x11, 0x8c, 0x5d, 0x53, 0x5b, 0x81, 0x27, 0x08, 0xbc, 0xa0, 0xae, 0x25}} , {{0x69, 0x32, 0xa1, 0x05, 0x11, 0x42, 0x00, 0xd2, 0x59, 0xac, 0x4d, 0x62, 0x8b, 0x13, 0xe2, 0x50, 0x5d, 0xa0, 0x9d, 0x9b, 0xfd, 0xbb, 0x12, 0x41, 0x75, 0x41, 0x9e, 0xcc, 0xdc, 0xc7, 0xdc, 0x5d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd9, 0xe3, 0x38, 0x06, 0x46, 0x70, 0x82, 0x5e, 0x28, 0x49, 0x79, 0xff, 0x25, 0xd2, 0x4e, 0x29, 0x8d, 0x06, 0xb0, 0x23, 0xae, 0x9b, 0x66, 0xe4, 0x7d, 0xc0, 0x70, 0x91, 0xa3, 0xfc, 0xec, 0x4e}} , {{0x62, 0x12, 0x37, 0x6a, 0x30, 0xf6, 0x1e, 0xfb, 0x14, 0x5c, 0x0d, 0x0e, 0xb7, 0x81, 0x6a, 0xe7, 0x08, 0x05, 0xac, 0xaa, 0x38, 0x46, 0xe2, 0x73, 0xea, 0x4b, 0x07, 0x81, 0x43, 0x7c, 0x9e, 0x5e}}}, {{{0xfc, 0xf9, 0x21, 0x4f, 0x2e, 0x76, 0x9b, 0x1f, 0x28, 0x60, 0x77, 0x43, 0x32, 0x9d, 0xbe, 0x17, 0x30, 0x2a, 0xc6, 0x18, 0x92, 0x66, 0x62, 0x30, 0x98, 0x40, 0x11, 0xa6, 0x7f, 0x18, 0x84, 0x28}} , {{0x3f, 0xab, 0xd3, 0xf4, 0x8a, 0x76, 0xa1, 0x3c, 0xca, 0x2d, 0x49, 0xc3, 0xea, 0x08, 0x0b, 0x85, 0x17, 0x2a, 0xc3, 0x6c, 0x08, 0xfd, 0x57, 0x9f, 0x3d, 0x5f, 0xdf, 0x67, 0x68, 0x42, 0x00, 0x32}}}, {{{0x51, 0x60, 0x1b, 0x06, 0x4f, 0x8a, 0x21, 0xba, 0x38, 0xa8, 0xba, 0xd6, 0x40, 0xf6, 0xe9, 0x9b, 0x76, 0x4d, 0x56, 0x21, 0x5b, 0x0a, 0x9b, 0x2e, 0x4f, 0x3d, 0x81, 0x32, 0x08, 0x9f, 0x97, 0x5b}} , {{0xe5, 0x44, 0xec, 0x06, 0x9d, 0x90, 0x79, 0x9f, 0xd3, 0xe0, 0x79, 0xaf, 0x8f, 0x10, 0xfd, 0xdd, 0x04, 0xae, 0x27, 0x97, 0x46, 0x33, 0x79, 0xea, 0xb8, 0x4e, 0xca, 0x5a, 0x59, 0x57, 0xe1, 0x0e}}}, {{{0x1a, 0xda, 0xf3, 0xa5, 0x41, 0x43, 0x28, 0xfc, 0x7e, 0xe7, 0x71, 0xea, 0xc6, 0x3b, 0x59, 0xcc, 0x2e, 0xd3, 0x40, 0xec, 0xb3, 0x13, 0x6f, 0x44, 0xcd, 0x13, 0xb2, 0x37, 0xf2, 0x6e, 0xd9, 0x1c}} , {{0xe3, 0xdb, 0x60, 0xcd, 0x5c, 0x4a, 0x18, 0x0f, 0xef, 0x73, 0x36, 0x71, 0x8c, 0xf6, 0x11, 0xb4, 0xd8, 0xce, 0x17, 0x5e, 0x4f, 0x26, 0x77, 0x97, 0x5f, 0xcb, 0xef, 0x91, 0xeb, 0x6a, 0x62, 0x7a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x18, 0x4a, 0xa2, 0x97, 0x08, 0x81, 0x2d, 0x83, 0xc4, 0xcc, 0xf0, 0x83, 0x7e, 0xec, 0x0d, 0x95, 0x4c, 0x5b, 0xfb, 0xfa, 0x98, 0x80, 0x4a, 0x66, 0x56, 0x0c, 0x51, 0xb3, 0xf2, 0x04, 0x5d, 0x27}} , {{0x3b, 0xb9, 0xb8, 0x06, 0x5a, 0x2e, 0xfe, 0xc3, 0x82, 0x37, 0x9c, 0xa3, 0x11, 0x1f, 0x9c, 0xa6, 0xda, 0x63, 0x48, 0x9b, 0xad, 0xde, 0x2d, 0xa6, 0xbc, 0x6e, 0x32, 0xda, 0x27, 0x65, 0xdd, 0x57}}}, {{{0x84, 0x4f, 0x37, 0x31, 0x7d, 0x2e, 0xbc, 0xad, 0x87, 0x07, 0x2a, 0x6b, 0x37, 0xfc, 0x5f, 0xeb, 0x4e, 0x75, 0x35, 0xa6, 0xde, 0xab, 0x0a, 0x19, 0x3a, 0xb7, 0xb1, 0xef, 0x92, 0x6a, 0x3b, 0x3c}} , {{0x3b, 0xb2, 0x94, 0x6d, 0x39, 0x60, 0xac, 0xee, 0xe7, 0x81, 0x1a, 0x3b, 0x76, 0x87, 0x5c, 0x05, 0x94, 0x2a, 0x45, 0xb9, 0x80, 0xe9, 0x22, 0xb1, 0x07, 0xcb, 0x40, 0x9e, 0x70, 0x49, 0x6d, 0x12}}}, {{{0xfd, 0x18, 0x78, 0x84, 0xa8, 0x4c, 0x7d, 0x6e, 0x59, 0xa6, 0xe5, 0x74, 0xf1, 0x19, 0xa6, 0x84, 0x2e, 0x51, 0xc1, 0x29, 0x13, 0xf2, 0x14, 0x6b, 0x5d, 0x53, 0x51, 0xf7, 0xef, 0xbf, 0x01, 0x22}} , {{0xa4, 0x4b, 0x62, 0x4c, 0xe6, 0xfd, 0x72, 0x07, 0xf2, 0x81, 0xfc, 0xf2, 0xbd, 0x12, 0x7c, 0x68, 0x76, 0x2a, 0xba, 0xf5, 0x65, 0xb1, 0x1f, 0x17, 0x0a, 0x38, 0xb0, 0xbf, 0xc0, 0xf8, 0xf4, 0x2a}}}, {{{0x55, 0x60, 0x55, 0x5b, 0xe4, 0x1d, 0x71, 0x4c, 0x9d, 0x5b, 0x9f, 0x70, 0xa6, 0x85, 0x9a, 0x2c, 0xa0, 0xe2, 0x32, 0x48, 0xce, 0x9e, 0x2a, 0xa5, 0x07, 0x3b, 0xc7, 0x6c, 0x86, 0x77, 0xde, 0x3c}} , {{0xf7, 0x18, 0x7a, 0x96, 0x7e, 0x43, 0x57, 0xa9, 0x55, 0xfc, 0x4e, 0xb6, 0x72, 0x00, 0xf2, 0xe4, 0xd7, 0x52, 0xd3, 0xd3, 0xb6, 0x85, 0xf6, 0x71, 0xc7, 0x44, 0x3f, 0x7f, 0xd7, 0xb3, 0xf2, 0x79}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x46, 0xca, 0xa7, 0x55, 0x7b, 0x79, 0xf3, 0xca, 0x5a, 0x65, 0xf6, 0xed, 0x50, 0x14, 0x7b, 0xe4, 0xc4, 0x2a, 0x65, 0x9e, 0xe2, 0xf9, 0xca, 0xa7, 0x22, 0x26, 0x53, 0xcb, 0x21, 0x5b, 0xa7, 0x31}} , {{0x90, 0xd7, 0xc5, 0x26, 0x08, 0xbd, 0xb0, 0x53, 0x63, 0x58, 0xc3, 0x31, 0x5e, 0x75, 0x46, 0x15, 0x91, 0xa6, 0xf8, 0x2f, 0x1a, 0x08, 0x65, 0x88, 0x2f, 0x98, 0x04, 0xf1, 0x7c, 0x6e, 0x00, 0x77}}}, {{{0x81, 0x21, 0x61, 0x09, 0xf6, 0x4e, 0xf1, 0x92, 0xee, 0x63, 0x61, 0x73, 0x87, 0xc7, 0x54, 0x0e, 0x42, 0x4b, 0xc9, 0x47, 0xd1, 0xb8, 0x7e, 0x91, 0x75, 0x37, 0x99, 0x28, 0xb8, 0xdd, 0x7f, 0x50}} , {{0x89, 0x8f, 0xc0, 0xbe, 0x5d, 0xd6, 0x9f, 0xa0, 0xf0, 0x9d, 0x81, 0xce, 0x3a, 0x7b, 0x98, 0x58, 0xbb, 0xd7, 0x78, 0xc8, 0x3f, 0x13, 0xf1, 0x74, 0x19, 0xdf, 0xf8, 0x98, 0x89, 0x5d, 0xfa, 0x5f}}}, {{{0x9e, 0x35, 0x85, 0x94, 0x47, 0x1f, 0x90, 0x15, 0x26, 0xd0, 0x84, 0xed, 0x8a, 0x80, 0xf7, 0x63, 0x42, 0x86, 0x27, 0xd7, 0xf4, 0x75, 0x58, 0xdc, 0x9c, 0xc0, 0x22, 0x7e, 0x20, 0x35, 0xfd, 0x1f}} , {{0x68, 0x0e, 0x6f, 0x97, 0xba, 0x70, 0xbb, 0xa3, 0x0e, 0xe5, 0x0b, 0x12, 0xf4, 0xa2, 0xdc, 0x47, 0xf8, 0xe6, 0xd0, 0x23, 0x6c, 0x33, 0xa8, 0x99, 0x46, 0x6e, 0x0f, 0x44, 0xba, 0x76, 0x48, 0x0f}}}, {{{0xa3, 0x2a, 0x61, 0x37, 0xe2, 0x59, 0x12, 0x0e, 0x27, 0xba, 0x64, 0x43, 0xae, 0xc0, 0x42, 0x69, 0x79, 0xa4, 0x1e, 0x29, 0x8b, 0x15, 0xeb, 0xf8, 0xaf, 0xd4, 0xa2, 0x68, 0x33, 0xb5, 0x7a, 0x24}} , {{0x2c, 0x19, 0x33, 0xdd, 0x1b, 0xab, 0xec, 0x01, 0xb0, 0x23, 0xf8, 0x42, 0x2b, 0x06, 0x88, 0xea, 0x3d, 0x2d, 0x00, 0x2a, 0x78, 0x45, 0x4d, 0x38, 0xed, 0x2e, 0x2e, 0x44, 0x49, 0xed, 0xcb, 0x33}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xa0, 0x68, 0xe8, 0x41, 0x8f, 0x91, 0xf8, 0x11, 0x13, 0x90, 0x2e, 0xa7, 0xab, 0x30, 0xef, 0xad, 0xa0, 0x61, 0x00, 0x88, 0xef, 0xdb, 0xce, 0x5b, 0x5c, 0xbb, 0x62, 0xc8, 0x56, 0xf9, 0x00, 0x73}} , {{0x3f, 0x60, 0xc1, 0x82, 0x2d, 0xa3, 0x28, 0x58, 0x24, 0x9e, 0x9f, 0xe3, 0x70, 0xcc, 0x09, 0x4e, 0x1a, 0x3f, 0x11, 0x11, 0x15, 0x07, 0x3c, 0xa4, 0x41, 0xe0, 0x65, 0xa3, 0x0a, 0x41, 0x6d, 0x11}}}, {{{0x31, 0x40, 0x01, 0x52, 0x56, 0x94, 0x5b, 0x28, 0x8a, 0xaa, 0x52, 0xee, 0xd8, 0x0a, 0x05, 0x8d, 0xcd, 0xb5, 0xaa, 0x2e, 0x38, 0xaa, 0xb7, 0x87, 0xf7, 0x2b, 0xfb, 0x04, 0xcb, 0x84, 0x3d, 0x54}} , {{0x20, 0xef, 0x59, 0xde, 0xa4, 0x2b, 0x93, 0x6e, 0x2e, 0xec, 0x42, 0x9a, 0xd4, 0x2d, 0xf4, 0x46, 0x58, 0x27, 0x2b, 0x18, 0x8f, 0x83, 0x3d, 0x69, 0x9e, 0xd4, 0x3e, 0xb6, 0xc5, 0xfd, 0x58, 0x03}}}, {{{0x33, 0x89, 0xc9, 0x63, 0x62, 0x1c, 0x17, 0xb4, 0x60, 0xc4, 0x26, 0x68, 0x09, 0xc3, 0x2e, 0x37, 0x0f, 0x7b, 0xb4, 0x9c, 0xb6, 0xf9, 0xfb, 0xd4, 0x51, 0x78, 0xc8, 0x63, 0xea, 0x77, 0x47, 0x07}} , {{0x32, 0xb4, 0x18, 0x47, 0x79, 0xcb, 0xd4, 0x5a, 0x07, 0x14, 0x0f, 0xa0, 0xd5, 0xac, 0xd0, 0x41, 0x40, 0xab, 0x61, 0x23, 0xe5, 0x2a, 0x2a, 0x6f, 0xf7, 0xa8, 0xd4, 0x76, 0xef, 0xe7, 0x45, 0x6c}}}, {{{0xa1, 0x5e, 0x60, 0x4f, 0xfb, 0xe1, 0x70, 0x6a, 0x1f, 0x55, 0x4f, 0x09, 0xb4, 0x95, 0x33, 0x36, 0xc6, 0x81, 0x01, 0x18, 0x06, 0x25, 0x27, 0xa4, 0xb4, 0x24, 0xa4, 0x86, 0x03, 0x4c, 0xac, 0x02}} , {{0x77, 0x38, 0xde, 0xd7, 0x60, 0x48, 0x07, 0xf0, 0x74, 0xa8, 0xff, 0x54, 0xe5, 0x30, 0x43, 0xff, 0x77, 0xfb, 0x21, 0x07, 0xff, 0xb2, 0x07, 0x6b, 0xe4, 0xe5, 0x30, 0xfc, 0x19, 0x6c, 0xa3, 0x01}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x13, 0xc5, 0x2c, 0xac, 0xd3, 0x83, 0x82, 0x7c, 0x29, 0xf7, 0x05, 0xa5, 0x00, 0xb6, 0x1f, 0x86, 0x55, 0xf4, 0xd6, 0x2f, 0x0c, 0x99, 0xd0, 0x65, 0x9b, 0x6b, 0x46, 0x0d, 0x43, 0xf8, 0x16, 0x28}} , {{0x1e, 0x7f, 0xb4, 0x74, 0x7e, 0xb1, 0x89, 0x4f, 0x18, 0x5a, 0xab, 0x64, 0x06, 0xdf, 0x45, 0x87, 0xe0, 0x6a, 0xc6, 0xf0, 0x0e, 0xc9, 0x24, 0x35, 0x38, 0xea, 0x30, 0x54, 0xb4, 0xc4, 0x52, 0x54}}}, {{{0xe9, 0x9f, 0xdc, 0x3f, 0xc1, 0x89, 0x44, 0x74, 0x27, 0xe4, 0xc1, 0x90, 0xff, 0x4a, 0xa7, 0x3c, 0xee, 0xcd, 0xf4, 0x1d, 0x25, 0x94, 0x7f, 0x63, 0x16, 0x48, 0xbc, 0x64, 0xfe, 0x95, 0xc4, 0x0c}} , {{0x8b, 0x19, 0x75, 0x6e, 0x03, 0x06, 0x5e, 0x6a, 0x6f, 0x1a, 0x8c, 0xe3, 0xd3, 0x28, 0xf2, 0xe0, 0xb9, 0x7a, 0x43, 0x69, 0xe6, 0xd3, 0xc0, 0xfe, 0x7e, 0x97, 0xab, 0x6c, 0x7b, 0x8e, 0x13, 0x42}}}, {{{0xd4, 0xca, 0x70, 0x3d, 0xab, 0xfb, 0x5f, 0x5e, 0x00, 0x0c, 0xcc, 0x77, 0x22, 0xf8, 0x78, 0x55, 0xae, 0x62, 0x35, 0xfb, 0x9a, 0xc6, 0x03, 0xe4, 0x0c, 0xee, 0xab, 0xc7, 0xc0, 0x89, 0x87, 0x54}} , {{0x32, 0xad, 0xae, 0x85, 0x58, 0x43, 0xb8, 0xb1, 0xe6, 0x3e, 0x00, 0x9c, 0x78, 0x88, 0x56, 0xdb, 0x9c, 0xfc, 0x79, 0xf6, 0xf9, 0x41, 0x5f, 0xb7, 0xbc, 0x11, 0xf9, 0x20, 0x36, 0x1c, 0x53, 0x2b}}}, {{{0x5a, 0x20, 0x5b, 0xa1, 0xa5, 0x44, 0x91, 0x24, 0x02, 0x63, 0x12, 0x64, 0xb8, 0x55, 0xf6, 0xde, 0x2c, 0xdb, 0x47, 0xb8, 0xc6, 0x0a, 0xc3, 0x00, 0x78, 0x93, 0xd8, 0xf5, 0xf5, 0x18, 0x28, 0x0a}} , {{0xd6, 0x1b, 0x9a, 0x6c, 0xe5, 0x46, 0xea, 0x70, 0x96, 0x8d, 0x4e, 0x2a, 0x52, 0x21, 0x26, 0x4b, 0xb1, 0xbb, 0x0f, 0x7c, 0xa9, 0x9b, 0x04, 0xbb, 0x51, 0x08, 0xf1, 0x9a, 0xa4, 0x76, 0x7c, 0x18}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xfa, 0x94, 0xf7, 0x40, 0xd0, 0xd7, 0xeb, 0xa9, 0x82, 0x36, 0xd5, 0x15, 0xb9, 0x33, 0x7a, 0xbf, 0x8a, 0xf2, 0x63, 0xaa, 0x37, 0xf5, 0x59, 0xac, 0xbd, 0xbb, 0x32, 0x36, 0xbe, 0x73, 0x99, 0x38}} , {{0x2c, 0xb3, 0xda, 0x7a, 0xd8, 0x3d, 0x99, 0xca, 0xd2, 0xf4, 0xda, 0x99, 0x8e, 0x4f, 0x98, 0xb7, 0xf4, 0xae, 0x3e, 0x9f, 0x8e, 0x35, 0x60, 0xa4, 0x33, 0x75, 0xa4, 0x04, 0x93, 0xb1, 0x6b, 0x4d}}}, {{{0x97, 0x9d, 0xa8, 0xcd, 0x97, 0x7b, 0x9d, 0xb9, 0xe7, 0xa5, 0xef, 0xfd, 0xa8, 0x42, 0x6b, 0xc3, 0x62, 0x64, 0x7d, 0xa5, 0x1b, 0xc9, 0x9e, 0xd2, 0x45, 0xb9, 0xee, 0x03, 0xb0, 0xbf, 0xc0, 0x68}} , {{0xed, 0xb7, 0x84, 0x2c, 0xf6, 0xd3, 0xa1, 0x6b, 0x24, 0x6d, 0x87, 0x56, 0x97, 0x59, 0x79, 0x62, 0x9f, 0xac, 0xed, 0xf3, 0xc9, 0x89, 0x21, 0x2e, 0x04, 0xb3, 0xcc, 0x2f, 0xbe, 0xd6, 0x0a, 0x4b}}}, {{{0x39, 0x61, 0x05, 0xed, 0x25, 0x89, 0x8b, 0x5d, 0x1b, 0xcb, 0x0c, 0x55, 0xf4, 0x6a, 0x00, 0x8a, 0x46, 0xe8, 0x1e, 0xc6, 0x83, 0xc8, 0x5a, 0x76, 0xdb, 0xcc, 0x19, 0x7a, 0xcc, 0x67, 0x46, 0x0b}} , {{0x53, 0xcf, 0xc2, 0xa1, 0xad, 0x6a, 0xf3, 0xcd, 0x8f, 0xc9, 0xde, 0x1c, 0xf8, 0x6c, 0x8f, 0xf8, 0x76, 0x42, 0xe7, 0xfe, 0xb2, 0x72, 0x21, 0x0a, 0x66, 0x74, 0x8f, 0xb7, 0xeb, 0xe4, 0x6f, 0x01}}}, {{{0x22, 0x8c, 0x6b, 0xbe, 0xfc, 0x4d, 0x70, 0x62, 0x6e, 0x52, 0x77, 0x99, 0x88, 0x7e, 0x7b, 0x57, 0x7a, 0x0d, 0xfe, 0xdc, 0x72, 0x92, 0xf1, 0x68, 0x1d, 0x97, 0xd7, 0x7c, 0x8d, 0x53, 0x10, 0x37}} , {{0x53, 0x88, 0x77, 0x02, 0xca, 0x27, 0xa8, 0xe5, 0x45, 0xe2, 0xa8, 0x48, 0x2a, 0xab, 0x18, 0xca, 0xea, 0x2d, 0x2a, 0x54, 0x17, 0x37, 0x32, 0x09, 0xdc, 0xe0, 0x4a, 0xb7, 0x7d, 0x82, 0x10, 0x7d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x8a, 0x64, 0x1e, 0x14, 0x0a, 0x57, 0xd4, 0xda, 0x5c, 0x96, 0x9b, 0x01, 0x4c, 0x67, 0xbf, 0x8b, 0x30, 0xfe, 0x08, 0xdb, 0x0d, 0xd5, 0xa8, 0xd7, 0x09, 0x11, 0x85, 0xa2, 0xd3, 0x45, 0xfb, 0x7e}} , {{0xda, 0x8c, 0xc2, 0xd0, 0xac, 0x18, 0xe8, 0x52, 0x36, 0xd4, 0x21, 0xa3, 0xdd, 0x57, 0x22, 0x79, 0xb7, 0xf8, 0x71, 0x9d, 0xc6, 0x91, 0x70, 0x86, 0x56, 0xbf, 0xa1, 0x11, 0x8b, 0x19, 0xe1, 0x0f}}}, {{{0x18, 0x32, 0x98, 0x2c, 0x8f, 0x91, 0xae, 0x12, 0xf0, 0x8c, 0xea, 0xf3, 0x3c, 0xb9, 0x5d, 0xe4, 0x69, 0xed, 0xb2, 0x47, 0x18, 0xbd, 0xce, 0x16, 0x52, 0x5c, 0x23, 0xe2, 0xa5, 0x25, 0x52, 0x5d}} , {{0xb9, 0xb1, 0xe7, 0x5d, 0x4e, 0xbc, 0xee, 0xbb, 0x40, 0x81, 0x77, 0x82, 0x19, 0xab, 0xb5, 0xc6, 0xee, 0xab, 0x5b, 0x6b, 0x63, 0x92, 0x8a, 0x34, 0x8d, 0xcd, 0xee, 0x4f, 0x49, 0xe5, 0xc9, 0x7e}}}, {{{0x21, 0xac, 0x8b, 0x22, 0xcd, 0xc3, 0x9a, 0xe9, 0x5e, 0x78, 0xbd, 0xde, 0xba, 0xad, 0xab, 0xbf, 0x75, 0x41, 0x09, 0xc5, 0x58, 0xa4, 0x7d, 0x92, 0xb0, 0x7f, 0xf2, 0xa1, 0xd1, 0xc0, 0xb3, 0x6d}} , {{0x62, 0x4f, 0xd0, 0x75, 0x77, 0xba, 0x76, 0x77, 0xd7, 0xb8, 0xd8, 0x92, 0x6f, 0x98, 0x34, 0x3d, 0xd6, 0x4e, 0x1c, 0x0f, 0xf0, 0x8f, 0x2e, 0xf1, 0xb3, 0xbd, 0xb1, 0xb9, 0xec, 0x99, 0xb4, 0x07}}}, {{{0x60, 0x57, 0x2e, 0x9a, 0x72, 0x1d, 0x6b, 0x6e, 0x58, 0x33, 0x24, 0x8c, 0x48, 0x39, 0x46, 0x8e, 0x89, 0x6a, 0x88, 0x51, 0x23, 0x62, 0xb5, 0x32, 0x09, 0x36, 0xe3, 0x57, 0xf5, 0x98, 0xde, 0x6f}} , {{0x8b, 0x2c, 0x00, 0x48, 0x4a, 0xf9, 0x5b, 0x87, 0x69, 0x52, 0xe5, 0x5b, 0xd1, 0xb1, 0xe5, 0x25, 0x25, 0xe0, 0x9c, 0xc2, 0x13, 0x44, 0xe8, 0xb9, 0x0a, 0x70, 0xad, 0xbd, 0x0f, 0x51, 0x94, 0x69}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xa2, 0xdc, 0xab, 0xa9, 0x25, 0x2d, 0xac, 0x5f, 0x03, 0x33, 0x08, 0xe7, 0x7e, 0xfe, 0x95, 0x36, 0x3c, 0x5b, 0x3a, 0xd3, 0x05, 0x82, 0x1c, 0x95, 0x2d, 0xd8, 0x77, 0x7e, 0x02, 0xd9, 0x5b, 0x70}} , {{0xc2, 0xfe, 0x1b, 0x0c, 0x67, 0xcd, 0xd6, 0xe0, 0x51, 0x8e, 0x2c, 0xe0, 0x79, 0x88, 0xf0, 0xcf, 0x41, 0x4a, 0xad, 0x23, 0xd4, 0x46, 0xca, 0x94, 0xa1, 0xc3, 0xeb, 0x28, 0x06, 0xfa, 0x17, 0x14}}}, {{{0x7b, 0xaa, 0x70, 0x0a, 0x4b, 0xfb, 0xf5, 0xbf, 0x80, 0xc5, 0xcf, 0x08, 0x7a, 0xdd, 0xa1, 0xf4, 0x9d, 0x54, 0x50, 0x53, 0x23, 0x77, 0x23, 0xf5, 0x34, 0xa5, 0x22, 0xd1, 0x0d, 0x96, 0x2e, 0x47}} , {{0xcc, 0xb7, 0x32, 0x89, 0x57, 0xd0, 0x98, 0x75, 0xe4, 0x37, 0x99, 0xa9, 0xe8, 0xba, 0xed, 0xba, 0xeb, 0xc7, 0x4f, 0x15, 0x76, 0x07, 0x0c, 0x4c, 0xef, 0x9f, 0x52, 0xfc, 0x04, 0x5d, 0x58, 0x10}}}, {{{0xce, 0x82, 0xf0, 0x8f, 0x79, 0x02, 0xa8, 0xd1, 0xda, 0x14, 0x09, 0x48, 0xee, 0x8a, 0x40, 0x98, 0x76, 0x60, 0x54, 0x5a, 0xde, 0x03, 0x24, 0xf5, 0xe6, 0x2f, 0xe1, 0x03, 0xbf, 0x68, 0x82, 0x7f}} , {{0x64, 0xe9, 0x28, 0xc7, 0xa4, 0xcf, 0x2a, 0xf9, 0x90, 0x64, 0x72, 0x2c, 0x8b, 0xeb, 0xec, 0xa0, 0xf2, 0x7d, 0x35, 0xb5, 0x90, 0x4d, 0x7f, 0x5b, 0x4a, 0x49, 0xe4, 0xb8, 0x3b, 0xc8, 0xa1, 0x2f}}}, {{{0x8b, 0xc5, 0xcc, 0x3d, 0x69, 0xa6, 0xa1, 0x18, 0x44, 0xbc, 0x4d, 0x77, 0x37, 0xc7, 0x86, 0xec, 0x0c, 0xc9, 0xd6, 0x44, 0xa9, 0x23, 0x27, 0xb9, 0x03, 0x34, 0xa7, 0x0a, 0xd5, 0xc7, 0x34, 0x37}} , {{0xf9, 0x7e, 0x3e, 0x66, 0xee, 0xf9, 0x99, 0x28, 0xff, 0xad, 0x11, 0xd8, 0xe2, 0x66, 0xc5, 0xcd, 0x0f, 0x0d, 0x0b, 0x6a, 0xfc, 0x7c, 0x24, 0xa8, 0x4f, 0xa8, 0x5e, 0x80, 0x45, 0x8b, 0x6c, 0x41}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xef, 0x1e, 0xec, 0xf7, 0x8d, 0x77, 0xf2, 0xea, 0xdb, 0x60, 0x03, 0x21, 0xc0, 0xff, 0x5e, 0x67, 0xc3, 0x71, 0x0b, 0x21, 0xb4, 0x41, 0xa0, 0x68, 0x38, 0xc6, 0x01, 0xa3, 0xd3, 0x51, 0x3c, 0x3c}} , {{0x92, 0xf8, 0xd6, 0x4b, 0xef, 0x42, 0x13, 0xb2, 0x4a, 0xc4, 0x2e, 0x72, 0x3f, 0xc9, 0x11, 0xbd, 0x74, 0x02, 0x0e, 0xf5, 0x13, 0x9d, 0x83, 0x1a, 0x1b, 0xd5, 0x54, 0xde, 0xc4, 0x1e, 0x16, 0x6c}}}, {{{0x27, 0x52, 0xe4, 0x63, 0xaa, 0x94, 0xe6, 0xc3, 0x28, 0x9c, 0xc6, 0x56, 0xac, 0xfa, 0xb6, 0xbd, 0xe2, 0xcc, 0x76, 0xc6, 0x27, 0x27, 0xa2, 0x8e, 0x78, 0x2b, 0x84, 0x72, 0x10, 0xbd, 0x4e, 0x2a}} , {{0xea, 0xa7, 0x23, 0xef, 0x04, 0x61, 0x80, 0x50, 0xc9, 0x6e, 0xa5, 0x96, 0xd1, 0xd1, 0xc8, 0xc3, 0x18, 0xd7, 0x2d, 0xfd, 0x26, 0xbd, 0xcb, 0x7b, 0x92, 0x51, 0x0e, 0x4a, 0x65, 0x57, 0xb8, 0x49}}}, {{{0xab, 0x55, 0x36, 0xc3, 0xec, 0x63, 0x55, 0x11, 0x55, 0xf6, 0xa5, 0xc7, 0x01, 0x5f, 0xfe, 0x79, 0xd8, 0x0a, 0xf7, 0x03, 0xd8, 0x98, 0x99, 0xf5, 0xd0, 0x00, 0x54, 0x6b, 0x66, 0x28, 0xf5, 0x25}} , {{0x7a, 0x8d, 0xa1, 0x5d, 0x70, 0x5d, 0x51, 0x27, 0xee, 0x30, 0x65, 0x56, 0x95, 0x46, 0xde, 0xbd, 0x03, 0x75, 0xb4, 0x57, 0x59, 0x89, 0xeb, 0x02, 0x9e, 0xcc, 0x89, 0x19, 0xa7, 0xcb, 0x17, 0x67}}}, {{{0x6a, 0xeb, 0xfc, 0x9a, 0x9a, 0x10, 0xce, 0xdb, 0x3a, 0x1c, 0x3c, 0x6a, 0x9d, 0xea, 0x46, 0xbc, 0x45, 0x49, 0xac, 0xe3, 0x41, 0x12, 0x7c, 0xf0, 0xf7, 0x4f, 0xf9, 0xf7, 0xff, 0x2c, 0x89, 0x04}} , {{0x30, 0x31, 0x54, 0x1a, 0x46, 0xca, 0xe6, 0xc6, 0xcb, 0xe2, 0xc3, 0xc1, 0x8b, 0x75, 0x81, 0xbe, 0xee, 0xf8, 0xa3, 0x11, 0x1c, 0x25, 0xa3, 0xa7, 0x35, 0x51, 0x55, 0xe2, 0x25, 0xaa, 0xe2, 0x3a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xb4, 0x48, 0x10, 0x9f, 0x8a, 0x09, 0x76, 0xfa, 0xf0, 0x7a, 0xb0, 0x70, 0xf7, 0x83, 0x80, 0x52, 0x84, 0x2b, 0x26, 0xa2, 0xc4, 0x5d, 0x4f, 0xba, 0xb1, 0xc8, 0x40, 0x0d, 0x78, 0x97, 0xc4, 0x60}} , {{0xd4, 0xb1, 0x6c, 0x08, 0xc7, 0x40, 0x38, 0x73, 0x5f, 0x0b, 0xf3, 0x76, 0x5d, 0xb2, 0xa5, 0x2f, 0x57, 0x57, 0x07, 0xed, 0x08, 0xa2, 0x6c, 0x4f, 0x08, 0x02, 0xb5, 0x0e, 0xee, 0x44, 0xfa, 0x22}}}, {{{0x0f, 0x00, 0x3f, 0xa6, 0x04, 0x19, 0x56, 0x65, 0x31, 0x7f, 0x8b, 0xeb, 0x0d, 0xe1, 0x47, 0x89, 0x97, 0x16, 0x53, 0xfa, 0x81, 0xa7, 0xaa, 0xb2, 0xbf, 0x67, 0xeb, 0x72, 0x60, 0x81, 0x0d, 0x48}} , {{0x7e, 0x13, 0x33, 0xcd, 0xa8, 0x84, 0x56, 0x1e, 0x67, 0xaf, 0x6b, 0x43, 0xac, 0x17, 0xaf, 0x16, 0xc0, 0x52, 0x99, 0x49, 0x5b, 0x87, 0x73, 0x7e, 0xb5, 0x43, 0xda, 0x6b, 0x1d, 0x0f, 0x2d, 0x55}}}, {{{0xe9, 0x58, 0x1f, 0xff, 0x84, 0x3f, 0x93, 0x1c, 0xcb, 0xe1, 0x30, 0x69, 0xa5, 0x75, 0x19, 0x7e, 0x14, 0x5f, 0xf8, 0xfc, 0x09, 0xdd, 0xa8, 0x78, 0x9d, 0xca, 0x59, 0x8b, 0xd1, 0x30, 0x01, 0x13}} , {{0xff, 0x76, 0x03, 0xc5, 0x4b, 0x89, 0x99, 0x70, 0x00, 0x59, 0x70, 0x9c, 0xd5, 0xd9, 0x11, 0x89, 0x5a, 0x46, 0xfe, 0xef, 0xdc, 0xd9, 0x55, 0x2b, 0x45, 0xa7, 0xb0, 0x2d, 0xfb, 0x24, 0xc2, 0x29}}}, {{{0x38, 0x06, 0xf8, 0x0b, 0xac, 0x82, 0xc4, 0x97, 0x2b, 0x90, 0xe0, 0xf7, 0xa8, 0xab, 0x6c, 0x08, 0x80, 0x66, 0x90, 0x46, 0xf7, 0x26, 0x2d, 0xf8, 0xf1, 0xc4, 0x6b, 0x4a, 0x82, 0x98, 0x8e, 0x37}} , {{0x8e, 0xb4, 0xee, 0xb8, 0xd4, 0x3f, 0xb2, 0x1b, 0xe0, 0x0a, 0x3d, 0x75, 0x34, 0x28, 0xa2, 0x8e, 0xc4, 0x92, 0x7b, 0xfe, 0x60, 0x6e, 0x6d, 0xb8, 0x31, 0x1d, 0x62, 0x0d, 0x78, 0x14, 0x42, 0x11}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x5e, 0xa8, 0xd8, 0x04, 0x9b, 0x73, 0xc9, 0xc9, 0xdc, 0x0d, 0x73, 0xbf, 0x0a, 0x0a, 0x73, 0xff, 0x18, 0x1f, 0x9c, 0x51, 0xaa, 0xc6, 0xf1, 0x83, 0x25, 0xfd, 0xab, 0xa3, 0x11, 0xd3, 0x01, 0x24}} , {{0x4d, 0xe3, 0x7e, 0x38, 0x62, 0x5e, 0x64, 0xbb, 0x2b, 0x53, 0xb5, 0x03, 0x68, 0xc4, 0xf2, 0x2b, 0x5a, 0x03, 0x32, 0x99, 0x4a, 0x41, 0x9a, 0xe1, 0x1a, 0xae, 0x8c, 0x48, 0xf3, 0x24, 0x32, 0x65}}}, {{{0xe8, 0xdd, 0xad, 0x3a, 0x8c, 0xea, 0xf4, 0xb3, 0xb2, 0xe5, 0x73, 0xf2, 0xed, 0x8b, 0xbf, 0xed, 0xb1, 0x0c, 0x0c, 0xfb, 0x2b, 0xf1, 0x01, 0x48, 0xe8, 0x26, 0x03, 0x8e, 0x27, 0x4d, 0x96, 0x72}} , {{0xc8, 0x09, 0x3b, 0x60, 0xc9, 0x26, 0x4d, 0x7c, 0xf2, 0x9c, 0xd4, 0xa1, 0x3b, 0x26, 0xc2, 0x04, 0x33, 0x44, 0x76, 0x3c, 0x02, 0xbb, 0x11, 0x42, 0x0c, 0x22, 0xb7, 0xc6, 0xe1, 0xac, 0xb4, 0x0e}}}, {{{0x6f, 0x85, 0xe7, 0xef, 0xde, 0x67, 0x30, 0xfc, 0xbf, 0x5a, 0xe0, 0x7b, 0x7a, 0x2a, 0x54, 0x6b, 0x5d, 0x62, 0x85, 0xa1, 0xf8, 0x16, 0x88, 0xec, 0x61, 0xb9, 0x96, 0xb5, 0xef, 0x2d, 0x43, 0x4d}} , {{0x7c, 0x31, 0x33, 0xcc, 0xe4, 0xcf, 0x6c, 0xff, 0x80, 0x47, 0x77, 0xd1, 0xd8, 0xe9, 0x69, 0x97, 0x98, 0x7f, 0x20, 0x57, 0x1d, 0x1d, 0x4f, 0x08, 0x27, 0xc8, 0x35, 0x57, 0x40, 0xc6, 0x21, 0x0c}}}, {{{0xd2, 0x8e, 0x9b, 0xfa, 0x42, 0x8e, 0xdf, 0x8f, 0xc7, 0x86, 0xf9, 0xa4, 0xca, 0x70, 0x00, 0x9d, 0x21, 0xbf, 0xec, 0x57, 0x62, 0x30, 0x58, 0x8c, 0x0d, 0x35, 0xdb, 0x5d, 0x8b, 0x6a, 0xa0, 0x5a}} , {{0xc1, 0x58, 0x7c, 0x0d, 0x20, 0xdd, 0x11, 0x26, 0x5f, 0x89, 0x3b, 0x97, 0x58, 0xf8, 0x8b, 0xe3, 0xdf, 0x32, 0xe2, 0xfc, 0xd8, 0x67, 0xf2, 0xa5, 0x37, 0x1e, 0x6d, 0xec, 0x7c, 0x27, 0x20, 0x79}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0xe9, 0xc0, 0xfa, 0x95, 0x45, 0x23, 0x96, 0xf1, 0x2c, 0x79, 0x25, 0x14, 0xce, 0x40, 0x14, 0x44, 0x2c, 0x36, 0x50, 0xd9, 0x63, 0x56, 0xb7, 0x56, 0x3b, 0x9e, 0xa7, 0xef, 0x89, 0xbb, 0x0e}} , {{0xce, 0x7f, 0xdc, 0x0a, 0xcc, 0x82, 0x1c, 0x0a, 0x78, 0x71, 0xe8, 0x74, 0x8d, 0x01, 0x30, 0x0f, 0xa7, 0x11, 0x4c, 0xdf, 0x38, 0xd7, 0xa7, 0x0d, 0xf8, 0x48, 0x52, 0x00, 0x80, 0x7b, 0x5f, 0x0e}}}, {{{0x25, 0x83, 0xe6, 0x94, 0x7b, 0x81, 0xb2, 0x91, 0xae, 0x0e, 0x05, 0xc9, 0xa3, 0x68, 0x2d, 0xd9, 0x88, 0x25, 0x19, 0x2a, 0x61, 0x61, 0x21, 0x97, 0x15, 0xa1, 0x35, 0xa5, 0x46, 0xc8, 0xa2, 0x0e}} , {{0x1b, 0x03, 0x0d, 0x8b, 0x5a, 0x1b, 0x97, 0x4b, 0xf2, 0x16, 0x31, 0x3d, 0x1f, 0x33, 0xa0, 0x50, 0x3a, 0x18, 0xbe, 0x13, 0xa1, 0x76, 0xc1, 0xba, 0x1b, 0xf1, 0x05, 0x7b, 0x33, 0xa8, 0x82, 0x3b}}}, {{{0xba, 0x36, 0x7b, 0x6d, 0xa9, 0xea, 0x14, 0x12, 0xc5, 0xfa, 0x91, 0x00, 0xba, 0x9b, 0x99, 0xcc, 0x56, 0x02, 0xe9, 0xa0, 0x26, 0x40, 0x66, 0x8c, 0xc4, 0xf8, 0x85, 0x33, 0x68, 0xe7, 0x03, 0x20}} , {{0x50, 0x5b, 0xff, 0xa9, 0xb2, 0xf1, 0xf1, 0x78, 0xcf, 0x14, 0xa4, 0xa9, 0xfc, 0x09, 0x46, 0x94, 0x54, 0x65, 0x0d, 0x9c, 0x5f, 0x72, 0x21, 0xe2, 0x97, 0xa5, 0x2d, 0x81, 0xce, 0x4a, 0x5f, 0x79}}}, {{{0x3d, 0x5f, 0x5c, 0xd2, 0xbc, 0x7d, 0x77, 0x0e, 0x2a, 0x6d, 0x22, 0x45, 0x84, 0x06, 0xc4, 0xdd, 0xc6, 0xa6, 0xc6, 0xd7, 0x49, 0xad, 0x6d, 0x87, 0x91, 0x0e, 0x3a, 0x67, 0x1d, 0x2c, 0x1d, 0x56}} , {{0xfe, 0x7a, 0x74, 0xcf, 0xd4, 0xd2, 0xe5, 0x19, 0xde, 0xd0, 0xdb, 0x70, 0x23, 0x69, 0xe6, 0x6d, 0xec, 0xec, 0xcc, 0x09, 0x33, 0x6a, 0x77, 0xdc, 0x6b, 0x22, 0x76, 0x5d, 0x92, 0x09, 0xac, 0x2d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x23, 0x15, 0x17, 0xeb, 0xd3, 0xdb, 0x12, 0x5e, 0x01, 0xf0, 0x91, 0xab, 0x2c, 0x41, 0xce, 0xac, 0xed, 0x1b, 0x4b, 0x2d, 0xbc, 0xdb, 0x17, 0x66, 0x89, 0x46, 0xad, 0x4b, 0x1e, 0x6f, 0x0b, 0x14}} , {{0x11, 0xce, 0xbf, 0xb6, 0x77, 0x2d, 0x48, 0x22, 0x18, 0x4f, 0xa3, 0x5d, 0x4a, 0xb0, 0x70, 0x12, 0x3e, 0x54, 0xd7, 0xd8, 0x0e, 0x2b, 0x27, 0xdc, 0x53, 0xff, 0xca, 0x8c, 0x59, 0xb3, 0x4e, 0x44}}}, {{{0x07, 0x76, 0x61, 0x0f, 0x66, 0xb2, 0x21, 0x39, 0x7e, 0xc0, 0xec, 0x45, 0x28, 0x82, 0xa1, 0x29, 0x32, 0x44, 0x35, 0x13, 0x5e, 0x61, 0x5e, 0x54, 0xcb, 0x7c, 0xef, 0xf6, 0x41, 0xcf, 0x9f, 0x0a}} , {{0xdd, 0xf9, 0xda, 0x84, 0xc3, 0xe6, 0x8a, 0x9f, 0x24, 0xd2, 0x96, 0x5d, 0x39, 0x6f, 0x58, 0x8c, 0xc1, 0x56, 0x93, 0xab, 0xb5, 0x79, 0x3b, 0xd2, 0xa8, 0x73, 0x16, 0xed, 0xfa, 0xb4, 0x2f, 0x73}}}, {{{0x8b, 0xb1, 0x95, 0xe5, 0x92, 0x50, 0x35, 0x11, 0x76, 0xac, 0xf4, 0x4d, 0x24, 0xc3, 0x32, 0xe6, 0xeb, 0xfe, 0x2c, 0x87, 0xc4, 0xf1, 0x56, 0xc4, 0x75, 0x24, 0x7a, 0x56, 0x85, 0x5a, 0x3a, 0x13}} , {{0x0d, 0x16, 0xac, 0x3c, 0x4a, 0x58, 0x86, 0x3a, 0x46, 0x7f, 0x6c, 0xa3, 0x52, 0x6e, 0x37, 0xe4, 0x96, 0x9c, 0xe9, 0x5c, 0x66, 0x41, 0x67, 0xe4, 0xfb, 0x79, 0x0c, 0x05, 0xf6, 0x64, 0xd5, 0x7c}}}, {{{0x28, 0xc1, 0xe1, 0x54, 0x73, 0xf2, 0xbf, 0x76, 0x74, 0x19, 0x19, 0x1b, 0xe4, 0xb9, 0xa8, 0x46, 0x65, 0x73, 0xf3, 0x77, 0x9b, 0x29, 0x74, 0x5b, 0xc6, 0x89, 0x6c, 0x2c, 0x7c, 0xf8, 0xb3, 0x0f}} , {{0xf7, 0xd5, 0xe9, 0x74, 0x5d, 0xb8, 0x25, 0x16, 0xb5, 0x30, 0xbc, 0x84, 0xc5, 0xf0, 0xad, 0xca, 0x12, 0x28, 0xbc, 0x9d, 0xd4, 0xfa, 0x82, 0xe6, 0xe3, 0xbf, 0xa2, 0x15, 0x2c, 0xd4, 0x34, 0x10}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x61, 0xb1, 0x46, 0xba, 0x0e, 0x31, 0xa5, 0x67, 0x6c, 0x7f, 0xd6, 0xd9, 0x27, 0x85, 0x0f, 0x79, 0x14, 0xc8, 0x6c, 0x2f, 0x5f, 0x5b, 0x9c, 0x35, 0x3d, 0x38, 0x86, 0x77, 0x65, 0x55, 0x6a, 0x7b}} , {{0xd3, 0xb0, 0x3a, 0x66, 0x60, 0x1b, 0x43, 0xf1, 0x26, 0x58, 0x99, 0x09, 0x8f, 0x2d, 0xa3, 0x14, 0x71, 0x85, 0xdb, 0xed, 0xf6, 0x26, 0xd5, 0x61, 0x9a, 0x73, 0xac, 0x0e, 0xea, 0xac, 0xb7, 0x0c}}}, {{{0x5e, 0xf4, 0xe5, 0x17, 0x0e, 0x10, 0x9f, 0xe7, 0x43, 0x5f, 0x67, 0x5c, 0xac, 0x4b, 0xe5, 0x14, 0x41, 0xd2, 0xbf, 0x48, 0xf5, 0x14, 0xb0, 0x71, 0xc6, 0x61, 0xc1, 0xb2, 0x70, 0x58, 0xd2, 0x5a}} , {{0x2d, 0xba, 0x16, 0x07, 0x92, 0x94, 0xdc, 0xbd, 0x50, 0x2b, 0xc9, 0x7f, 0x42, 0x00, 0xba, 0x61, 0xed, 0xf8, 0x43, 0xed, 0xf5, 0xf9, 0x40, 0x60, 0xb2, 0xb0, 0x82, 0xcb, 0xed, 0x75, 0xc7, 0x65}}}, {{{0x80, 0xba, 0x0d, 0x09, 0x40, 0xa7, 0x39, 0xa6, 0x67, 0x34, 0x7e, 0x66, 0xbe, 0x56, 0xfb, 0x53, 0x78, 0xc4, 0x46, 0xe8, 0xed, 0x68, 0x6c, 0x7f, 0xce, 0xe8, 0x9f, 0xce, 0xa2, 0x64, 0x58, 0x53}} , {{0xe8, 0xc1, 0xa9, 0xc2, 0x7b, 0x59, 0x21, 0x33, 0xe2, 0x43, 0x73, 0x2b, 0xac, 0x2d, 0xc1, 0x89, 0x3b, 0x15, 0xe2, 0xd5, 0xc0, 0x97, 0x8a, 0xfd, 0x6f, 0x36, 0x33, 0xb7, 0xb9, 0xc3, 0x88, 0x09}}}, {{{0xd0, 0xb6, 0x56, 0x30, 0x5c, 0xae, 0xb3, 0x75, 0x44, 0xa4, 0x83, 0x51, 0x6e, 0x01, 0x65, 0xef, 0x45, 0x76, 0xe6, 0xf5, 0xa2, 0x0d, 0xd4, 0x16, 0x3b, 0x58, 0x2f, 0xf2, 0x2f, 0x36, 0x18, 0x3f}} , {{0xfd, 0x2f, 0xe0, 0x9b, 0x1e, 0x8c, 0xc5, 0x18, 0xa9, 0xca, 0xd4, 0x2b, 0x35, 0xb6, 0x95, 0x0a, 0x9f, 0x7e, 0xfb, 0xc4, 0xef, 0x88, 0x7b, 0x23, 0x43, 0xec, 0x2f, 0x0d, 0x0f, 0x7a, 0xfc, 0x5c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb, 0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c, 0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b}} , {{0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63, 0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a, 0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61}}}, {{{0x54, 0x83, 0x02, 0x18, 0x82, 0x93, 0x99, 0x07, 0xd0, 0xa7, 0xda, 0xd8, 0x75, 0x89, 0xfa, 0xf2, 0xd9, 0xa3, 0xb8, 0x6b, 0x5a, 0x35, 0x28, 0xd2, 0x6b, 0x59, 0xc2, 0xf8, 0x45, 0xe2, 0xbc, 0x06}} , {{0x65, 0xc0, 0xa3, 0x88, 0x51, 0x95, 0xfc, 0x96, 0x94, 0x78, 0xe8, 0x0d, 0x8b, 0x41, 0xc9, 0xc2, 0x58, 0x48, 0x75, 0x10, 0x2f, 0xcd, 0x2a, 0xc9, 0xa0, 0x6d, 0x0f, 0xdd, 0x9c, 0x98, 0x26, 0x3d}}}, {{{0x2f, 0x66, 0x29, 0x1b, 0x04, 0x89, 0xbd, 0x7e, 0xee, 0x6e, 0xdd, 0xb7, 0x0e, 0xef, 0xb0, 0x0c, 0xb4, 0xfc, 0x7f, 0xc2, 0xc9, 0x3a, 0x3c, 0x64, 0xef, 0x45, 0x44, 0xaf, 0x8a, 0x90, 0x65, 0x76}} , {{0xa1, 0x4c, 0x70, 0x4b, 0x0e, 0xa0, 0x83, 0x70, 0x13, 0xa4, 0xaf, 0xb8, 0x38, 0x19, 0x22, 0x65, 0x09, 0xb4, 0x02, 0x4f, 0x06, 0xf8, 0x17, 0xce, 0x46, 0x45, 0xda, 0x50, 0x7c, 0x8a, 0xd1, 0x4e}}}, {{{0xf7, 0xd4, 0x16, 0x6c, 0x4e, 0x95, 0x9d, 0x5d, 0x0f, 0x91, 0x2b, 0x52, 0xfe, 0x5c, 0x34, 0xe5, 0x30, 0xe6, 0xa4, 0x3b, 0xf3, 0xf3, 0x34, 0x08, 0xa9, 0x4a, 0xa0, 0xb5, 0x6e, 0xb3, 0x09, 0x0a}} , {{0x26, 0xd9, 0x5e, 0xa3, 0x0f, 0xeb, 0xa2, 0xf3, 0x20, 0x3b, 0x37, 0xd4, 0xe4, 0x9e, 0xce, 0x06, 0x3d, 0x53, 0xed, 0xae, 0x2b, 0xeb, 0xb6, 0x24, 0x0a, 0x11, 0xa3, 0x0f, 0xd6, 0x7f, 0xa4, 0x3a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xdb, 0x9f, 0x2c, 0xfc, 0xd6, 0xb2, 0x1e, 0x2e, 0x52, 0x7a, 0x06, 0x87, 0x2d, 0x86, 0x72, 0x2b, 0x6d, 0x90, 0x77, 0x46, 0x43, 0xb5, 0x7a, 0xf8, 0x60, 0x7d, 0x91, 0x60, 0x5b, 0x9d, 0x9e, 0x07}} , {{0x97, 0x87, 0xc7, 0x04, 0x1c, 0x38, 0x01, 0x39, 0x58, 0xc7, 0x85, 0xa3, 0xfc, 0x64, 0x00, 0x64, 0x25, 0xa2, 0xbf, 0x50, 0x94, 0xca, 0x26, 0x31, 0x45, 0x0a, 0x24, 0xd2, 0x51, 0x29, 0x51, 0x16}}}, {{{0x4d, 0x4a, 0xd7, 0x98, 0x71, 0x57, 0xac, 0x7d, 0x8b, 0x37, 0xbd, 0x63, 0xff, 0x87, 0xb1, 0x49, 0x95, 0x20, 0x7c, 0xcf, 0x7c, 0x59, 0xc4, 0x91, 0x9c, 0xef, 0xd0, 0xdb, 0x60, 0x09, 0x9d, 0x46}} , {{0xcb, 0x78, 0x94, 0x90, 0xe4, 0x45, 0xb3, 0xf6, 0xd9, 0xf6, 0x57, 0x74, 0xd5, 0xf8, 0x83, 0x4f, 0x39, 0xc9, 0xbd, 0x88, 0xc2, 0x57, 0x21, 0x1f, 0x24, 0x32, 0x68, 0xf8, 0xc7, 0x21, 0x5f, 0x0b}}}, {{{0x2a, 0x36, 0x68, 0xfc, 0x5f, 0xb6, 0x4f, 0xa5, 0xe3, 0x9d, 0x24, 0x2f, 0xc0, 0x93, 0x61, 0xcf, 0xf8, 0x0a, 0xed, 0xe1, 0xdb, 0x27, 0xec, 0x0e, 0x14, 0x32, 0x5f, 0x8e, 0xa1, 0x62, 0x41, 0x16}} , {{0x95, 0x21, 0x01, 0xce, 0x95, 0x5b, 0x0e, 0x57, 0xc7, 0xb9, 0x62, 0xb5, 0x28, 0xca, 0x11, 0xec, 0xb4, 0x46, 0x06, 0x73, 0x26, 0xff, 0xfb, 0x66, 0x7d, 0xee, 0x5f, 0xb2, 0x56, 0xfd, 0x2a, 0x08}}}, {{{0x92, 0x67, 0x77, 0x56, 0xa1, 0xff, 0xc4, 0xc5, 0x95, 0xf0, 0xe3, 0x3a, 0x0a, 0xca, 0x94, 0x4d, 0x9e, 0x7e, 0x3d, 0xb9, 0x6e, 0xb6, 0xb0, 0xce, 0xa4, 0x30, 0x89, 0x99, 0xe9, 0xad, 0x11, 0x59}} , {{0xf6, 0x48, 0x95, 0xa1, 0x6f, 0x5f, 0xb7, 0xa5, 0xbb, 0x30, 0x00, 0x1c, 0xd2, 0x8a, 0xd6, 0x25, 0x26, 0x1b, 0xb2, 0x0d, 0x37, 0x6a, 0x05, 0xf4, 0x9d, 0x3e, 0x17, 0x2a, 0x43, 0xd2, 0x3a, 0x06}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x32, 0x99, 0x93, 0xd1, 0x9a, 0x72, 0xf3, 0xa9, 0x16, 0xbd, 0xb4, 0x4c, 0xdd, 0xf9, 0xd4, 0xb2, 0x64, 0x9a, 0xd3, 0x05, 0xe4, 0xa3, 0x73, 0x1c, 0xcb, 0x7e, 0x57, 0x67, 0xff, 0x04, 0xb3, 0x10}} , {{0xb9, 0x4b, 0xa4, 0xad, 0xd0, 0x6d, 0x61, 0x23, 0xb4, 0xaf, 0x34, 0xa9, 0xaa, 0x65, 0xec, 0xd9, 0x69, 0xe3, 0x85, 0xcd, 0xcc, 0xe7, 0xb0, 0x9b, 0x41, 0xc1, 0x1c, 0xf9, 0xa0, 0xfa, 0xb7, 0x13}}}, {{{0x04, 0xfd, 0x88, 0x3c, 0x0c, 0xd0, 0x09, 0x52, 0x51, 0x4f, 0x06, 0x19, 0xcc, 0xc3, 0xbb, 0xde, 0x80, 0xc5, 0x33, 0xbc, 0xf9, 0xf3, 0x17, 0x36, 0xdd, 0xc6, 0xde, 0xe8, 0x9b, 0x5d, 0x79, 0x1b}} , {{0x65, 0x0a, 0xbe, 0x51, 0x57, 0xad, 0x50, 0x79, 0x08, 0x71, 0x9b, 0x07, 0x95, 0x8f, 0xfb, 0xae, 0x4b, 0x38, 0xba, 0xcf, 0x53, 0x2a, 0x86, 0x1e, 0xc0, 0x50, 0x5c, 0x67, 0x1b, 0xf6, 0x87, 0x6c}}}, {{{0x4f, 0x00, 0xb2, 0x66, 0x55, 0xed, 0x4a, 0xed, 0x8d, 0xe1, 0x66, 0x18, 0xb2, 0x14, 0x74, 0x8d, 0xfd, 0x1a, 0x36, 0x0f, 0x26, 0x5c, 0x8b, 0x89, 0xf3, 0xab, 0xf2, 0xf3, 0x24, 0x67, 0xfd, 0x70}} , {{0xfd, 0x4e, 0x2a, 0xc1, 0x3a, 0xca, 0x8f, 0x00, 0xd8, 0xec, 0x74, 0x67, 0xef, 0x61, 0xe0, 0x28, 0xd0, 0x96, 0xf4, 0x48, 0xde, 0x81, 0xe3, 0xef, 0xdc, 0xaa, 0x7d, 0xf3, 0xb6, 0x55, 0xa6, 0x65}}}, {{{0xeb, 0xcb, 0xc5, 0x70, 0x91, 0x31, 0x10, 0x93, 0x0d, 0xc8, 0xd0, 0xef, 0x62, 0xe8, 0x6f, 0x82, 0xe3, 0x69, 0x3d, 0x91, 0x7f, 0x31, 0xe1, 0x26, 0x35, 0x3c, 0x4a, 0x2f, 0xab, 0xc4, 0x9a, 0x5e}} , {{0xab, 0x1b, 0xb5, 0xe5, 0x2b, 0xc3, 0x0e, 0x29, 0xb0, 0xd0, 0x73, 0xe6, 0x4f, 0x64, 0xf2, 0xbc, 0xe4, 0xe4, 0xe1, 0x9a, 0x52, 0x33, 0x2f, 0xbd, 0xcc, 0x03, 0xee, 0x8a, 0xfa, 0x00, 0x5f, 0x50}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf6, 0xdb, 0x0d, 0x22, 0x3d, 0xb5, 0x14, 0x75, 0x31, 0xf0, 0x81, 0xe2, 0xb9, 0x37, 0xa2, 0xa9, 0x84, 0x11, 0x9a, 0x07, 0xb5, 0x53, 0x89, 0x78, 0xa9, 0x30, 0x27, 0xa1, 0xf1, 0x4e, 0x5c, 0x2e}} , {{0x8b, 0x00, 0x54, 0xfb, 0x4d, 0xdc, 0xcb, 0x17, 0x35, 0x40, 0xff, 0xb7, 0x8c, 0xfe, 0x4a, 0xe4, 0x4e, 0x99, 0x4e, 0xa8, 0x74, 0x54, 0x5d, 0x5c, 0x96, 0xa3, 0x12, 0x55, 0x36, 0x31, 0x17, 0x5c}}}, {{{0xce, 0x24, 0xef, 0x7b, 0x86, 0xf2, 0x0f, 0x77, 0xe8, 0x5c, 0x7d, 0x87, 0x38, 0x2d, 0xef, 0xaf, 0xf2, 0x8c, 0x72, 0x2e, 0xeb, 0xb6, 0x55, 0x4b, 0x6e, 0xf1, 0x4e, 0x8a, 0x0e, 0x9a, 0x6c, 0x4c}} , {{0x25, 0xea, 0x86, 0xc2, 0xd1, 0x4f, 0xb7, 0x3e, 0xa8, 0x5c, 0x8d, 0x66, 0x81, 0x25, 0xed, 0xc5, 0x4c, 0x05, 0xb9, 0xd8, 0xd6, 0x70, 0xbe, 0x73, 0x82, 0xe8, 0xa1, 0xe5, 0x1e, 0x71, 0xd5, 0x26}}}, {{{0x4e, 0x6d, 0xc3, 0xa7, 0x4f, 0x22, 0x45, 0x26, 0xa2, 0x7e, 0x16, 0xf7, 0xf7, 0x63, 0xdc, 0x86, 0x01, 0x2a, 0x71, 0x38, 0x5c, 0x33, 0xc3, 0xce, 0x30, 0xff, 0xf9, 0x2c, 0x91, 0x71, 0x8a, 0x72}} , {{0x8c, 0x44, 0x09, 0x28, 0xd5, 0x23, 0xc9, 0x8f, 0xf3, 0x84, 0x45, 0xc6, 0x9a, 0x5e, 0xff, 0xd2, 0xc7, 0x57, 0x93, 0xa3, 0xc1, 0x69, 0xdd, 0x62, 0x0f, 0xda, 0x5c, 0x30, 0x59, 0x5d, 0xe9, 0x4c}}}, {{{0x92, 0x7e, 0x50, 0x27, 0x72, 0xd7, 0x0c, 0xd6, 0x69, 0x96, 0x81, 0x35, 0x84, 0x94, 0x35, 0x8b, 0x6c, 0xaa, 0x62, 0x86, 0x6e, 0x1c, 0x15, 0xf3, 0x6c, 0xb3, 0xff, 0x65, 0x1b, 0xa2, 0x9b, 0x59}} , {{0xe2, 0xa9, 0x65, 0x88, 0xc4, 0x50, 0xfa, 0xbb, 0x3b, 0x6e, 0x5f, 0x44, 0x01, 0xca, 0x97, 0xd4, 0xdd, 0xf6, 0xcd, 0x3f, 0x3f, 0xe5, 0x97, 0x67, 0x2b, 0x8c, 0x66, 0x0f, 0x35, 0x9b, 0xf5, 0x07}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf1, 0x59, 0x27, 0xd8, 0xdb, 0x5a, 0x11, 0x5e, 0x82, 0xf3, 0x38, 0xff, 0x1c, 0xed, 0xfe, 0x3f, 0x64, 0x54, 0x3f, 0x7f, 0xd1, 0x81, 0xed, 0xef, 0x65, 0xc5, 0xcb, 0xfd, 0xe1, 0x80, 0xcd, 0x11}} , {{0xe0, 0xdb, 0x22, 0x28, 0xe6, 0xff, 0x61, 0x9d, 0x41, 0x14, 0x2d, 0x3b, 0x26, 0x22, 0xdf, 0xf1, 0x34, 0x81, 0xe9, 0x45, 0xee, 0x0f, 0x98, 0x8b, 0xa6, 0x3f, 0xef, 0xf7, 0x43, 0x19, 0xf1, 0x43}}}, {{{0xee, 0xf3, 0x00, 0xa1, 0x50, 0xde, 0xc0, 0xb6, 0x01, 0xe3, 0x8c, 0x3c, 0x4d, 0x31, 0xd2, 0xb0, 0x58, 0xcd, 0xed, 0x10, 0x4a, 0x7a, 0xef, 0x80, 0xa9, 0x19, 0x32, 0xf3, 0xd8, 0x33, 0x8c, 0x06}} , {{0xcb, 0x7d, 0x4f, 0xff, 0x30, 0xd8, 0x12, 0x3b, 0x39, 0x1c, 0x06, 0xf9, 0x4c, 0x34, 0x35, 0x71, 0xb5, 0x16, 0x94, 0x67, 0xdf, 0xee, 0x11, 0xde, 0xa4, 0x1d, 0x88, 0x93, 0x35, 0xa9, 0x32, 0x10}}}, {{{0xe9, 0xc3, 0xbc, 0x7b, 0x5c, 0xfc, 0xb2, 0xf9, 0xc9, 0x2f, 0xe5, 0xba, 0x3a, 0x0b, 0xab, 0x64, 0x38, 0x6f, 0x5b, 0x4b, 0x93, 0xda, 0x64, 0xec, 0x4d, 0x3d, 0xa0, 0xf5, 0xbb, 0xba, 0x47, 0x48}} , {{0x60, 0xbc, 0x45, 0x1f, 0x23, 0xa2, 0x3b, 0x70, 0x76, 0xe6, 0x97, 0x99, 0x4f, 0x77, 0x54, 0x67, 0x30, 0x9a, 0xe7, 0x66, 0xd6, 0xcd, 0x2e, 0x51, 0x24, 0x2c, 0x42, 0x4a, 0x11, 0xfe, 0x6f, 0x7e}}}, {{{0x87, 0xc0, 0xb1, 0xf0, 0xa3, 0x6f, 0x0c, 0x93, 0xa9, 0x0a, 0x72, 0xef, 0x5c, 0xbe, 0x65, 0x35, 0xa7, 0x6a, 0x4e, 0x2c, 0xbf, 0x21, 0x23, 0xe8, 0x2f, 0x97, 0xc7, 0x3e, 0xc8, 0x17, 0xac, 0x1e}} , {{0x7b, 0xef, 0x21, 0xe5, 0x40, 0xcc, 0x1e, 0xdc, 0xd6, 0xbd, 0x97, 0x7a, 0x7c, 0x75, 0x86, 0x7a, 0x25, 0x5a, 0x6e, 0x7c, 0xe5, 0x51, 0x3c, 0x1b, 0x5b, 0x82, 0x9a, 0x07, 0x60, 0xa1, 0x19, 0x04}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x96, 0x88, 0xa6, 0xab, 0x8f, 0xe3, 0x3a, 0x49, 0xf8, 0xfe, 0x34, 0xe7, 0x6a, 0xb2, 0xfe, 0x40, 0x26, 0x74, 0x57, 0x4c, 0xf6, 0xd4, 0x99, 0xce, 0x5d, 0x7b, 0x2f, 0x67, 0xd6, 0x5a, 0xe4, 0x4e}} , {{0x5c, 0x82, 0xb3, 0xbd, 0x55, 0x25, 0xf6, 0x6a, 0x93, 0xa4, 0x02, 0xc6, 0x7d, 0x5c, 0xb1, 0x2b, 0x5b, 0xff, 0xfb, 0x56, 0xf8, 0x01, 0x41, 0x90, 0xc6, 0xb6, 0xac, 0x4f, 0xfe, 0xa7, 0x41, 0x70}}}, {{{0xdb, 0xfa, 0x9b, 0x2c, 0xd4, 0x23, 0x67, 0x2c, 0x8a, 0x63, 0x6c, 0x07, 0x26, 0x48, 0x4f, 0xc2, 0x03, 0xd2, 0x53, 0x20, 0x28, 0xed, 0x65, 0x71, 0x47, 0xa9, 0x16, 0x16, 0x12, 0xbc, 0x28, 0x33}} , {{0x39, 0xc0, 0xfa, 0xfa, 0xcd, 0x33, 0x43, 0xc7, 0x97, 0x76, 0x9b, 0x93, 0x91, 0x72, 0xeb, 0xc5, 0x18, 0x67, 0x4c, 0x11, 0xf0, 0xf4, 0xe5, 0x73, 0xb2, 0x5c, 0x1b, 0xc2, 0x26, 0x3f, 0xbf, 0x2b}}}, {{{0x86, 0xe6, 0x8c, 0x1d, 0xdf, 0xca, 0xfc, 0xd5, 0xf8, 0x3a, 0xc3, 0x44, 0x72, 0xe6, 0x78, 0x9d, 0x2b, 0x97, 0xf8, 0x28, 0x45, 0xb4, 0x20, 0xc9, 0x2a, 0x8c, 0x67, 0xaa, 0x11, 0xc5, 0x5b, 0x2f}} , {{0x17, 0x0f, 0x86, 0x52, 0xd7, 0x9d, 0xc3, 0x44, 0x51, 0x76, 0x32, 0x65, 0xb4, 0x37, 0x81, 0x99, 0x46, 0x37, 0x62, 0xed, 0xcf, 0x64, 0x9d, 0x72, 0x40, 0x7a, 0x4c, 0x0b, 0x76, 0x2a, 0xfb, 0x56}}}, {{{0x33, 0xa7, 0x90, 0x7c, 0xc3, 0x6f, 0x17, 0xa5, 0xa0, 0x67, 0x72, 0x17, 0xea, 0x7e, 0x63, 0x14, 0x83, 0xde, 0xc1, 0x71, 0x2d, 0x41, 0x32, 0x7a, 0xf3, 0xd1, 0x2b, 0xd8, 0x2a, 0xa6, 0x46, 0x36}} , {{0xac, 0xcc, 0x6b, 0x7c, 0xf9, 0xb8, 0x8b, 0x08, 0x5c, 0xd0, 0x7d, 0x8f, 0x73, 0xea, 0x20, 0xda, 0x86, 0xca, 0x00, 0xc7, 0xad, 0x73, 0x4d, 0xe9, 0xe8, 0xa9, 0xda, 0x1f, 0x03, 0x06, 0xdd, 0x24}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9c, 0xb2, 0x61, 0x0a, 0x98, 0x2a, 0xa5, 0xd7, 0xee, 0xa9, 0xac, 0x65, 0xcb, 0x0a, 0x1e, 0xe2, 0xbe, 0xdc, 0x85, 0x59, 0x0f, 0x9c, 0xa6, 0x57, 0x34, 0xa5, 0x87, 0xeb, 0x7b, 0x1e, 0x0c, 0x3c}} , {{0x2f, 0xbd, 0x84, 0x63, 0x0d, 0xb5, 0xa0, 0xf0, 0x4b, 0x9e, 0x93, 0xc6, 0x34, 0x9a, 0x34, 0xff, 0x73, 0x19, 0x2f, 0x6e, 0x54, 0x45, 0x2c, 0x92, 0x31, 0x76, 0x34, 0xf1, 0xb2, 0x26, 0xe8, 0x74}}}, {{{0x0a, 0x67, 0x90, 0x6d, 0x0c, 0x4c, 0xcc, 0xc0, 0xe6, 0xbd, 0xa7, 0x5e, 0x55, 0x8c, 0xcd, 0x58, 0x9b, 0x11, 0xa2, 0xbb, 0x4b, 0xb1, 0x43, 0x04, 0x3c, 0x55, 0xed, 0x23, 0xfe, 0xcd, 0xb1, 0x53}} , {{0x05, 0xfb, 0x75, 0xf5, 0x01, 0xaf, 0x38, 0x72, 0x58, 0xfc, 0x04, 0x29, 0x34, 0x7a, 0x67, 0xa2, 0x08, 0x50, 0x6e, 0xd0, 0x2b, 0x73, 0xd5, 0xb8, 0xe4, 0x30, 0x96, 0xad, 0x45, 0xdf, 0xa6, 0x5c}}}, {{{0x0d, 0x88, 0x1a, 0x90, 0x7e, 0xdc, 0xd8, 0xfe, 0xc1, 0x2f, 0x5d, 0x67, 0xee, 0x67, 0x2f, 0xed, 0x6f, 0x55, 0x43, 0x5f, 0x87, 0x14, 0x35, 0x42, 0xd3, 0x75, 0xae, 0xd5, 0xd3, 0x85, 0x1a, 0x76}} , {{0x87, 0xc8, 0xa0, 0x6e, 0xe1, 0xb0, 0xad, 0x6a, 0x4a, 0x34, 0x71, 0xed, 0x7c, 0xd6, 0x44, 0x03, 0x65, 0x4a, 0x5c, 0x5c, 0x04, 0xf5, 0x24, 0x3f, 0xb0, 0x16, 0x5e, 0x8c, 0xb2, 0xd2, 0xc5, 0x20}}}, {{{0x98, 0x83, 0xc2, 0x37, 0xa0, 0x41, 0xa8, 0x48, 0x5c, 0x5f, 0xbf, 0xc8, 0xfa, 0x24, 0xe0, 0x59, 0x2c, 0xbd, 0xf6, 0x81, 0x7e, 0x88, 0xe6, 0xca, 0x04, 0xd8, 0x5d, 0x60, 0xbb, 0x74, 0xa7, 0x0b}} , {{0x21, 0x13, 0x91, 0xbf, 0x77, 0x7a, 0x33, 0xbc, 0xe9, 0x07, 0x39, 0x0a, 0xdd, 0x7d, 0x06, 0x10, 0x9a, 0xee, 0x47, 0x73, 0x1b, 0x15, 0x5a, 0xfb, 0xcd, 0x4d, 0xd0, 0xd2, 0x3a, 0x01, 0xba, 0x54}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x48, 0xd5, 0x39, 0x4a, 0x0b, 0x20, 0x6a, 0x43, 0xa0, 0x07, 0x82, 0x5e, 0x49, 0x7c, 0xc9, 0x47, 0xf1, 0x7c, 0x37, 0xb9, 0x23, 0xef, 0x6b, 0x46, 0x45, 0x8c, 0x45, 0x76, 0xdf, 0x14, 0x6b, 0x6e}} , {{0x42, 0xc9, 0xca, 0x29, 0x4c, 0x76, 0x37, 0xda, 0x8a, 0x2d, 0x7c, 0x3a, 0x58, 0xf2, 0x03, 0xb4, 0xb5, 0xb9, 0x1a, 0x13, 0x2d, 0xde, 0x5f, 0x6b, 0x9d, 0xba, 0x52, 0xc9, 0x5d, 0xb3, 0xf3, 0x30}}}, {{{0x4c, 0x6f, 0xfe, 0x6b, 0x0c, 0x62, 0xd7, 0x48, 0x71, 0xef, 0xb1, 0x85, 0x79, 0xc0, 0xed, 0x24, 0xb1, 0x08, 0x93, 0x76, 0x8e, 0xf7, 0x38, 0x8e, 0xeb, 0xfe, 0x80, 0x40, 0xaf, 0x90, 0x64, 0x49}} , {{0x4a, 0x88, 0xda, 0xc1, 0x98, 0x44, 0x3c, 0x53, 0x4e, 0xdb, 0x4b, 0xb9, 0x12, 0x5f, 0xcd, 0x08, 0x04, 0xef, 0x75, 0xe7, 0xb1, 0x3a, 0xe5, 0x07, 0xfa, 0xca, 0x65, 0x7b, 0x72, 0x10, 0x64, 0x7f}}}, {{{0x3d, 0x81, 0xf0, 0xeb, 0x16, 0xfd, 0x58, 0x33, 0x8d, 0x7c, 0x1a, 0xfb, 0x20, 0x2c, 0x8a, 0xee, 0x90, 0xbb, 0x33, 0x6d, 0x45, 0xe9, 0x8e, 0x99, 0x85, 0xe1, 0x08, 0x1f, 0xc5, 0xf1, 0xb5, 0x46}} , {{0xe4, 0xe7, 0x43, 0x4b, 0xa0, 0x3f, 0x2b, 0x06, 0xba, 0x17, 0xae, 0x3d, 0xe6, 0xce, 0xbd, 0xb8, 0xed, 0x74, 0x11, 0x35, 0xec, 0x96, 0xfe, 0x31, 0xe3, 0x0e, 0x7a, 0x4e, 0xc9, 0x1d, 0xcb, 0x20}}}, {{{0xe0, 0x67, 0xe9, 0x7b, 0xdb, 0x96, 0x5c, 0xb0, 0x32, 0xd0, 0x59, 0x31, 0x90, 0xdc, 0x92, 0x97, 0xac, 0x09, 0x38, 0x31, 0x0f, 0x7e, 0xd6, 0x5d, 0xd0, 0x06, 0xb6, 0x1f, 0xea, 0xf0, 0x5b, 0x07}} , {{0x81, 0x9f, 0xc7, 0xde, 0x6b, 0x41, 0x22, 0x35, 0x14, 0x67, 0x77, 0x3e, 0x90, 0x81, 0xb0, 0xd9, 0x85, 0x4c, 0xca, 0x9b, 0x3f, 0x04, 0x59, 0xd6, 0xaa, 0x17, 0xc3, 0x88, 0x34, 0x37, 0xba, 0x43}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x4c, 0xb6, 0x69, 0xc8, 0x81, 0x95, 0x94, 0x33, 0x92, 0x34, 0xe9, 0x3c, 0x84, 0x0d, 0x3d, 0x5a, 0x37, 0x9c, 0x22, 0xa0, 0xaa, 0x65, 0xce, 0xb4, 0xc2, 0x2d, 0x66, 0x67, 0x02, 0xff, 0x74, 0x10}} , {{0x22, 0xb0, 0xd5, 0xe6, 0xc7, 0xef, 0xb1, 0xa7, 0x13, 0xda, 0x60, 0xb4, 0x80, 0xc1, 0x42, 0x7d, 0x10, 0x70, 0x97, 0x04, 0x4d, 0xda, 0x23, 0x89, 0xc2, 0x0e, 0x68, 0xcb, 0xde, 0xe0, 0x9b, 0x29}}}, {{{0x33, 0xfe, 0x42, 0x2a, 0x36, 0x2b, 0x2e, 0x36, 0x64, 0x5c, 0x8b, 0xcc, 0x81, 0x6a, 0x15, 0x08, 0xa1, 0x27, 0xe8, 0x57, 0xe5, 0x78, 0x8e, 0xf2, 0x58, 0x19, 0x12, 0x42, 0xae, 0xc4, 0x63, 0x3e}} , {{0x78, 0x96, 0x9c, 0xa7, 0xca, 0x80, 0xae, 0x02, 0x85, 0xb1, 0x7c, 0x04, 0x5c, 0xc1, 0x5b, 0x26, 0xc1, 0xba, 0xed, 0xa5, 0x59, 0x70, 0x85, 0x8c, 0x8c, 0xe8, 0x87, 0xac, 0x6a, 0x28, 0x99, 0x35}}}, {{{0x9f, 0x04, 0x08, 0x28, 0xbe, 0x87, 0xda, 0x80, 0x28, 0x38, 0xde, 0x9f, 0xcd, 0xe4, 0xe3, 0x62, 0xfb, 0x2e, 0x46, 0x8d, 0x01, 0xb3, 0x06, 0x51, 0xd4, 0x19, 0x3b, 0x11, 0xfa, 0xe2, 0xad, 0x1e}} , {{0xa0, 0x20, 0x99, 0x69, 0x0a, 0xae, 0xa3, 0x70, 0x4e, 0x64, 0x80, 0xb7, 0x85, 0x9c, 0x87, 0x54, 0x43, 0x43, 0x55, 0x80, 0x6d, 0x8d, 0x7c, 0xa9, 0x64, 0xca, 0x6c, 0x2e, 0x21, 0xd8, 0xc8, 0x6c}}}, {{{0x91, 0x4a, 0x07, 0xad, 0x08, 0x75, 0xc1, 0x4f, 0xa4, 0xb2, 0xc3, 0x6f, 0x46, 0x3e, 0xb1, 0xce, 0x52, 0xab, 0x67, 0x09, 0x54, 0x48, 0x6b, 0x6c, 0xd7, 0x1d, 0x71, 0x76, 0xcb, 0xff, 0xdd, 0x31}} , {{0x36, 0x88, 0xfa, 0xfd, 0xf0, 0x36, 0x6f, 0x07, 0x74, 0x88, 0x50, 0xd0, 0x95, 0x38, 0x4a, 0x48, 0x2e, 0x07, 0x64, 0x97, 0x11, 0x76, 0x01, 0x1a, 0x27, 0x4d, 0x8e, 0x25, 0x9a, 0x9b, 0x1c, 0x22}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xbe, 0x57, 0xbd, 0x0e, 0x0f, 0xac, 0x5e, 0x76, 0xa3, 0x71, 0xad, 0x2b, 0x10, 0x45, 0x02, 0xec, 0x59, 0xd5, 0x5d, 0xa9, 0x44, 0xcc, 0x25, 0x4c, 0xb3, 0x3c, 0x5b, 0x69, 0x07, 0x55, 0x26, 0x6b}} , {{0x30, 0x6b, 0xd4, 0xa7, 0x51, 0x29, 0xe3, 0xf9, 0x7a, 0x75, 0x2a, 0x82, 0x2f, 0xd6, 0x1d, 0x99, 0x2b, 0x80, 0xd5, 0x67, 0x1e, 0x15, 0x9d, 0xca, 0xfd, 0xeb, 0xac, 0x97, 0x35, 0x09, 0x7f, 0x3f}}}, {{{0x35, 0x0d, 0x34, 0x0a, 0xb8, 0x67, 0x56, 0x29, 0x20, 0xf3, 0x19, 0x5f, 0xe2, 0x83, 0x42, 0x73, 0x53, 0xa8, 0xc5, 0x02, 0x19, 0x33, 0xb4, 0x64, 0xbd, 0xc3, 0x87, 0x8c, 0xd7, 0x76, 0xed, 0x25}} , {{0x47, 0x39, 0x37, 0x76, 0x0d, 0x1d, 0x0c, 0xf5, 0x5a, 0x6d, 0x43, 0x88, 0x99, 0x15, 0xb4, 0x52, 0x0f, 0x2a, 0xb3, 0xb0, 0x3f, 0xa6, 0xb3, 0x26, 0xb3, 0xc7, 0x45, 0xf5, 0x92, 0x5f, 0x9b, 0x17}}}, {{{0x9d, 0x23, 0xbd, 0x15, 0xfe, 0x52, 0x52, 0x15, 0x26, 0x79, 0x86, 0xba, 0x06, 0x56, 0x66, 0xbb, 0x8c, 0x2e, 0x10, 0x11, 0xd5, 0x4a, 0x18, 0x52, 0xda, 0x84, 0x44, 0xf0, 0x3e, 0xe9, 0x8c, 0x35}} , {{0xad, 0xa0, 0x41, 0xec, 0xc8, 0x4d, 0xb9, 0xd2, 0x6e, 0x96, 0x4e, 0x5b, 0xc5, 0xc2, 0xa0, 0x1b, 0xcf, 0x0c, 0xbf, 0x17, 0x66, 0x57, 0xc1, 0x17, 0x90, 0x45, 0x71, 0xc2, 0xe1, 0x24, 0xeb, 0x27}}}, {{{0x2c, 0xb9, 0x42, 0xa4, 0xaf, 0x3b, 0x42, 0x0e, 0xc2, 0x0f, 0xf2, 0xea, 0x83, 0xaf, 0x9a, 0x13, 0x17, 0xb0, 0xbd, 0x89, 0x17, 0xe3, 0x72, 0xcb, 0x0e, 0x76, 0x7e, 0x41, 0x63, 0x04, 0x88, 0x71}} , {{0x75, 0x78, 0x38, 0x86, 0x57, 0xdd, 0x9f, 0xee, 0x54, 0x70, 0x65, 0xbf, 0xf1, 0x2c, 0xe0, 0x39, 0x0d, 0xe3, 0x89, 0xfd, 0x8e, 0x93, 0x4f, 0x43, 0xdc, 0xd5, 0x5b, 0xde, 0xf9, 0x98, 0xe5, 0x7b}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xe7, 0x3b, 0x65, 0x11, 0xdf, 0xb2, 0xf2, 0x63, 0x94, 0x12, 0x6f, 0x5c, 0x9e, 0x77, 0xc1, 0xb6, 0xd8, 0xab, 0x58, 0x7a, 0x1d, 0x95, 0x73, 0xdd, 0xe7, 0xe3, 0x6f, 0xf2, 0x03, 0x1d, 0xdb, 0x76}} , {{0xae, 0x06, 0x4e, 0x2c, 0x52, 0x1b, 0xbc, 0x5a, 0x5a, 0xa5, 0xbe, 0x27, 0xbd, 0xeb, 0xe1, 0x14, 0x17, 0x68, 0x26, 0x07, 0x03, 0xd1, 0x18, 0x0b, 0xdf, 0xf1, 0x06, 0x5c, 0xa6, 0x1b, 0xb9, 0x24}}}, {{{0xc5, 0x66, 0x80, 0x13, 0x0e, 0x48, 0x8c, 0x87, 0x31, 0x84, 0xb4, 0x60, 0xed, 0xc5, 0xec, 0xb6, 0xc5, 0x05, 0x33, 0x5f, 0x2f, 0x7d, 0x40, 0xb6, 0x32, 0x1d, 0x38, 0x74, 0x1b, 0xf1, 0x09, 0x3d}} , {{0xd4, 0x69, 0x82, 0xbc, 0x8d, 0xf8, 0x34, 0x36, 0x75, 0x55, 0x18, 0x55, 0x58, 0x3c, 0x79, 0xaf, 0x26, 0x80, 0xab, 0x9b, 0x95, 0x00, 0xf1, 0xcb, 0xda, 0xc1, 0x9f, 0xf6, 0x2f, 0xa2, 0xf4, 0x45}}}, {{{0x17, 0xbe, 0xeb, 0x85, 0xed, 0x9e, 0xcd, 0x56, 0xf5, 0x17, 0x45, 0x42, 0xb4, 0x1f, 0x44, 0x4c, 0x05, 0x74, 0x15, 0x47, 0x00, 0xc6, 0x6a, 0x3d, 0x24, 0x09, 0x0d, 0x58, 0xb1, 0x42, 0xd7, 0x04}} , {{0x8d, 0xbd, 0xa3, 0xc4, 0x06, 0x9b, 0x1f, 0x90, 0x58, 0x60, 0x74, 0xb2, 0x00, 0x3b, 0x3c, 0xd2, 0xda, 0x82, 0xbb, 0x10, 0x90, 0x69, 0x92, 0xa9, 0xb4, 0x30, 0x81, 0xe3, 0x7c, 0xa8, 0x89, 0x45}}}, {{{0x3f, 0xdc, 0x05, 0xcb, 0x41, 0x3c, 0xc8, 0x23, 0x04, 0x2c, 0x38, 0x99, 0xe3, 0x68, 0x55, 0xf9, 0xd3, 0x32, 0xc7, 0xbf, 0xfa, 0xd4, 0x1b, 0x5d, 0xde, 0xdc, 0x10, 0x42, 0xc0, 0x42, 0xd9, 0x75}} , {{0x2d, 0xab, 0x35, 0x4e, 0x87, 0xc4, 0x65, 0x97, 0x67, 0x24, 0xa4, 0x47, 0xad, 0x3f, 0x8e, 0xf3, 0xcb, 0x31, 0x17, 0x77, 0xc5, 0xe2, 0xd7, 0x8f, 0x3c, 0xc1, 0xcd, 0x56, 0x48, 0xc1, 0x6c, 0x69}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x14, 0xae, 0x5f, 0x88, 0x7b, 0xa5, 0x90, 0xdf, 0x10, 0xb2, 0x8b, 0x5e, 0x24, 0x17, 0xc3, 0xa3, 0xd4, 0x0f, 0x92, 0x61, 0x1a, 0x19, 0x5a, 0xad, 0x76, 0xbd, 0xd8, 0x1c, 0xdd, 0xe0, 0x12, 0x6d}} , {{0x8e, 0xbd, 0x70, 0x8f, 0x02, 0xa3, 0x24, 0x4d, 0x5a, 0x67, 0xc4, 0xda, 0xf7, 0x20, 0x0f, 0x81, 0x5b, 0x7a, 0x05, 0x24, 0x67, 0x83, 0x0b, 0x2a, 0x80, 0xe7, 0xfd, 0x74, 0x4b, 0x9e, 0x5c, 0x0d}}}, {{{0x94, 0xd5, 0x5f, 0x1f, 0xa2, 0xfb, 0xeb, 0xe1, 0x07, 0x34, 0xf8, 0x20, 0xad, 0x81, 0x30, 0x06, 0x2d, 0xa1, 0x81, 0x95, 0x36, 0xcf, 0x11, 0x0b, 0xaf, 0xc1, 0x2b, 0x9a, 0x6c, 0x55, 0xc1, 0x16}} , {{0x36, 0x4f, 0xf1, 0x5e, 0x74, 0x35, 0x13, 0x28, 0xd7, 0x11, 0xcf, 0xb8, 0xde, 0x93, 0xb3, 0x05, 0xb8, 0xb5, 0x73, 0xe9, 0xeb, 0xad, 0x19, 0x1e, 0x89, 0x0f, 0x8b, 0x15, 0xd5, 0x8c, 0xe3, 0x23}}}, {{{0x33, 0x79, 0xe7, 0x18, 0xe6, 0x0f, 0x57, 0x93, 0x15, 0xa0, 0xa7, 0xaa, 0xc4, 0xbf, 0x4f, 0x30, 0x74, 0x95, 0x5e, 0x69, 0x4a, 0x5b, 0x45, 0xe4, 0x00, 0xeb, 0x23, 0x74, 0x4c, 0xdf, 0x6b, 0x45}} , {{0x97, 0x29, 0x6c, 0xc4, 0x42, 0x0b, 0xdd, 0xc0, 0x29, 0x5c, 0x9b, 0x34, 0x97, 0xd0, 0xc7, 0x79, 0x80, 0x63, 0x74, 0xe4, 0x8e, 0x37, 0xb0, 0x2b, 0x7c, 0xe8, 0x68, 0x6c, 0xc3, 0x82, 0x97, 0x57}}}, {{{0x22, 0xbe, 0x83, 0xb6, 0x4b, 0x80, 0x6b, 0x43, 0x24, 0x5e, 0xef, 0x99, 0x9b, 0xa8, 0xfc, 0x25, 0x8d, 0x3b, 0x03, 0x94, 0x2b, 0x3e, 0xe7, 0x95, 0x76, 0x9b, 0xcc, 0x15, 0xdb, 0x32, 0xe6, 0x66}} , {{0x84, 0xf0, 0x4a, 0x13, 0xa6, 0xd6, 0xfa, 0x93, 0x46, 0x07, 0xf6, 0x7e, 0x5c, 0x6d, 0x5e, 0xf6, 0xa6, 0xe7, 0x48, 0xf0, 0x06, 0xea, 0xff, 0x90, 0xc1, 0xcc, 0x4c, 0x19, 0x9c, 0x3c, 0x4e, 0x53}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2a, 0x50, 0xe3, 0x07, 0x15, 0x59, 0xf2, 0x8b, 0x81, 0xf2, 0xf3, 0xd3, 0x6c, 0x99, 0x8c, 0x70, 0x67, 0xec, 0xcc, 0xee, 0x9e, 0x59, 0x45, 0x59, 0x7d, 0x47, 0x75, 0x69, 0xf5, 0x24, 0x93, 0x5d}} , {{0x6a, 0x4f, 0x1b, 0xbe, 0x6b, 0x30, 0xcf, 0x75, 0x46, 0xe3, 0x7b, 0x9d, 0xfc, 0xcd, 0xd8, 0x5c, 0x1f, 0xb4, 0xc8, 0xe2, 0x24, 0xec, 0x1a, 0x28, 0x05, 0x32, 0x57, 0xfd, 0x3c, 0x5a, 0x98, 0x10}}}, {{{0xa3, 0xdb, 0xf7, 0x30, 0xd8, 0xc2, 0x9a, 0xe1, 0xd3, 0xce, 0x22, 0xe5, 0x80, 0x1e, 0xd9, 0xe4, 0x1f, 0xab, 0xc0, 0x71, 0x1a, 0x86, 0x0e, 0x27, 0x99, 0x5b, 0xfa, 0x76, 0x99, 0xb0, 0x08, 0x3c}} , {{0x2a, 0x93, 0xd2, 0x85, 0x1b, 0x6a, 0x5d, 0xa6, 0xee, 0xd1, 0xd1, 0x33, 0xbd, 0x6a, 0x36, 0x73, 0x37, 0x3a, 0x44, 0xb4, 0xec, 0xa9, 0x7a, 0xde, 0x83, 0x40, 0xd7, 0xdf, 0x28, 0xba, 0xa2, 0x30}}}, {{{0xd3, 0xb5, 0x6d, 0x05, 0x3f, 0x9f, 0xf3, 0x15, 0x8d, 0x7c, 0xca, 0xc9, 0xfc, 0x8a, 0x7c, 0x94, 0xb0, 0x63, 0x36, 0x9b, 0x78, 0xd1, 0x91, 0x1f, 0x93, 0xd8, 0x57, 0x43, 0xde, 0x76, 0xa3, 0x43}} , {{0x9b, 0x35, 0xe2, 0xa9, 0x3d, 0x32, 0x1e, 0xbb, 0x16, 0x28, 0x70, 0xe9, 0x45, 0x2f, 0x8f, 0x70, 0x7f, 0x08, 0x7e, 0x53, 0xc4, 0x7a, 0xbf, 0xf7, 0xe1, 0xa4, 0x6a, 0xd8, 0xac, 0x64, 0x1b, 0x11}}}, {{{0xb2, 0xeb, 0x47, 0x46, 0x18, 0x3e, 0x1f, 0x99, 0x0c, 0xcc, 0xf1, 0x2c, 0xe0, 0xe7, 0x8f, 0xe0, 0x01, 0x7e, 0x65, 0xb8, 0x0c, 0xd0, 0xfb, 0xc8, 0xb9, 0x90, 0x98, 0x33, 0x61, 0x3b, 0xd8, 0x27}} , {{0xa0, 0xbe, 0x72, 0x3a, 0x50, 0x4b, 0x74, 0xab, 0x01, 0xc8, 0x93, 0xc5, 0xe4, 0xc7, 0x08, 0x6c, 0xb4, 0xca, 0xee, 0xeb, 0x8e, 0xd7, 0x4e, 0x26, 0xc6, 0x1d, 0xe2, 0x71, 0xaf, 0x89, 0xa0, 0x2a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x98, 0x0b, 0xe4, 0xde, 0xdb, 0xa8, 0xfa, 0x82, 0x74, 0x06, 0x52, 0x6d, 0x08, 0x52, 0x8a, 0xff, 0x62, 0xc5, 0x6a, 0x44, 0x0f, 0x51, 0x8c, 0x1f, 0x6e, 0xb6, 0xc6, 0x2c, 0x81, 0xd3, 0x76, 0x46}} , {{0xf4, 0x29, 0x74, 0x2e, 0x80, 0xa7, 0x1a, 0x8f, 0xf6, 0xbd, 0xd6, 0x8e, 0xbf, 0xc1, 0x95, 0x2a, 0xeb, 0xa0, 0x7f, 0x45, 0xa0, 0x50, 0x14, 0x05, 0xb1, 0x57, 0x4c, 0x74, 0xb7, 0xe2, 0x89, 0x7d}}}, {{{0x07, 0xee, 0xa7, 0xad, 0xb7, 0x09, 0x0b, 0x49, 0x4e, 0xbf, 0xca, 0xe5, 0x21, 0xe6, 0xe6, 0xaf, 0xd5, 0x67, 0xf3, 0xce, 0x7e, 0x7c, 0x93, 0x7b, 0x5a, 0x10, 0x12, 0x0e, 0x6c, 0x06, 0x11, 0x75}} , {{0xd5, 0xfc, 0x86, 0xa3, 0x3b, 0xa3, 0x3e, 0x0a, 0xfb, 0x0b, 0xf7, 0x36, 0xb1, 0x5b, 0xda, 0x70, 0xb7, 0x00, 0xa7, 0xda, 0x88, 0x8f, 0x84, 0xa8, 0xbc, 0x1c, 0x39, 0xb8, 0x65, 0xf3, 0x4d, 0x60}}}, {{{0x96, 0x9d, 0x31, 0xf4, 0xa2, 0xbe, 0x81, 0xb9, 0xa5, 0x59, 0x9e, 0xba, 0x07, 0xbe, 0x74, 0x58, 0xd8, 0xeb, 0xc5, 0x9f, 0x3d, 0xd1, 0xf4, 0xae, 0xce, 0x53, 0xdf, 0x4f, 0xc7, 0x2a, 0x89, 0x4d}} , {{0x29, 0xd8, 0xf2, 0xaa, 0xe9, 0x0e, 0xf7, 0x2e, 0x5f, 0x9d, 0x8a, 0x5b, 0x09, 0xed, 0xc9, 0x24, 0x22, 0xf4, 0x0f, 0x25, 0x8f, 0x1c, 0x84, 0x6e, 0x34, 0x14, 0x6c, 0xea, 0xb3, 0x86, 0x5d, 0x04}}}, {{{0x07, 0x98, 0x61, 0xe8, 0x6a, 0xd2, 0x81, 0x49, 0x25, 0xd5, 0x5b, 0x18, 0xc7, 0x35, 0x52, 0x51, 0xa4, 0x46, 0xad, 0x18, 0x0d, 0xc9, 0x5f, 0x18, 0x91, 0x3b, 0xb4, 0xc0, 0x60, 0x59, 0x8d, 0x66}} , {{0x03, 0x1b, 0x79, 0x53, 0x6e, 0x24, 0xae, 0x57, 0xd9, 0x58, 0x09, 0x85, 0x48, 0xa2, 0xd3, 0xb5, 0xe2, 0x4d, 0x11, 0x82, 0xe6, 0x86, 0x3c, 0xe9, 0xb1, 0x00, 0x19, 0xc2, 0x57, 0xf7, 0x66, 0x7a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0f, 0xe3, 0x89, 0x03, 0xd7, 0x22, 0x95, 0x9f, 0xca, 0xb4, 0x8d, 0x9e, 0x6d, 0x97, 0xff, 0x8d, 0x21, 0x59, 0x07, 0xef, 0x03, 0x2d, 0x5e, 0xf8, 0x44, 0x46, 0xe7, 0x85, 0x80, 0xc5, 0x89, 0x50}} , {{0x8b, 0xd8, 0x53, 0x86, 0x24, 0x86, 0x29, 0x52, 0x01, 0xfa, 0x20, 0xc3, 0x4e, 0x95, 0xcb, 0xad, 0x7b, 0x34, 0x94, 0x30, 0xb7, 0x7a, 0xfa, 0x96, 0x41, 0x60, 0x2b, 0xcb, 0x59, 0xb9, 0xca, 0x50}}}, {{{0xc2, 0x5b, 0x9b, 0x78, 0x23, 0x1b, 0x3a, 0x88, 0x94, 0x5f, 0x0a, 0x9b, 0x98, 0x2b, 0x6e, 0x53, 0x11, 0xf6, 0xff, 0xc6, 0x7d, 0x42, 0xcc, 0x02, 0x80, 0x40, 0x0d, 0x1e, 0xfb, 0xaf, 0x61, 0x07}} , {{0xb0, 0xe6, 0x2f, 0x81, 0x70, 0xa1, 0x2e, 0x39, 0x04, 0x7c, 0xc4, 0x2c, 0x87, 0x45, 0x4a, 0x5b, 0x69, 0x97, 0xac, 0x6d, 0x2c, 0x10, 0x42, 0x7c, 0x3b, 0x15, 0x70, 0x60, 0x0e, 0x11, 0x6d, 0x3a}}}, {{{0x9b, 0x18, 0x80, 0x5e, 0xdb, 0x05, 0xbd, 0xc6, 0xb7, 0x3c, 0xc2, 0x40, 0x4d, 0x5d, 0xce, 0x97, 0x8a, 0x34, 0x15, 0xab, 0x28, 0x5d, 0x10, 0xf0, 0x37, 0x0c, 0xcc, 0x16, 0xfa, 0x1f, 0x33, 0x0d}} , {{0x19, 0xf9, 0x35, 0xaa, 0x59, 0x1a, 0x0c, 0x5c, 0x06, 0xfc, 0x6a, 0x0b, 0x97, 0x53, 0x36, 0xfc, 0x2a, 0xa5, 0x5a, 0x9b, 0x30, 0xef, 0x23, 0xaf, 0x39, 0x5d, 0x9a, 0x6b, 0x75, 0x57, 0x48, 0x0b}}}, {{{0x26, 0xdc, 0x76, 0x3b, 0xfc, 0xf9, 0x9c, 0x3f, 0x89, 0x0b, 0x62, 0x53, 0xaf, 0x83, 0x01, 0x2e, 0xbc, 0x6a, 0xc6, 0x03, 0x0d, 0x75, 0x2a, 0x0d, 0xe6, 0x94, 0x54, 0xcf, 0xb3, 0xe5, 0x96, 0x25}} , {{0xfe, 0x82, 0xb1, 0x74, 0x31, 0x8a, 0xa7, 0x6f, 0x56, 0xbd, 0x8d, 0xf4, 0xe0, 0x94, 0x51, 0x59, 0xde, 0x2c, 0x5a, 0xf4, 0x84, 0x6b, 0x4a, 0x88, 0x93, 0xc0, 0x0c, 0x9a, 0xac, 0xa7, 0xa0, 0x68}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0x0d, 0xd6, 0xc7, 0x23, 0x47, 0x10, 0xad, 0xc7, 0x08, 0x5c, 0x87, 0x87, 0x93, 0x98, 0x18, 0xb8, 0xd3, 0x9c, 0xac, 0x5a, 0x3d, 0xc5, 0x75, 0xf8, 0x49, 0x32, 0x14, 0xcc, 0x51, 0x96, 0x24}} , {{0x65, 0x9c, 0x5d, 0xf0, 0x37, 0x04, 0xf0, 0x34, 0x69, 0x2a, 0xf0, 0xa5, 0x64, 0xca, 0xde, 0x2b, 0x5b, 0x15, 0x10, 0xd2, 0xab, 0x06, 0xdd, 0xc4, 0xb0, 0xb6, 0x5b, 0xc1, 0x17, 0xdf, 0x8f, 0x02}}}, {{{0xbd, 0x59, 0x3d, 0xbf, 0x5c, 0x31, 0x44, 0x2c, 0x32, 0x94, 0x04, 0x60, 0x84, 0x0f, 0xad, 0x00, 0xb6, 0x8f, 0xc9, 0x1d, 0xcc, 0x5c, 0xa2, 0x49, 0x0e, 0x50, 0x91, 0x08, 0x9a, 0x43, 0x55, 0x05}} , {{0x5d, 0x93, 0x55, 0xdf, 0x9b, 0x12, 0x19, 0xec, 0x93, 0x85, 0x42, 0x9e, 0x66, 0x0f, 0x9d, 0xaf, 0x99, 0xaf, 0x26, 0x89, 0xbc, 0x61, 0xfd, 0xff, 0xce, 0x4b, 0xf4, 0x33, 0x95, 0xc9, 0x35, 0x58}}}, {{{0x12, 0x55, 0xf9, 0xda, 0xcb, 0x44, 0xa7, 0xdc, 0x57, 0xe2, 0xf9, 0x9a, 0xe6, 0x07, 0x23, 0x60, 0x54, 0xa7, 0x39, 0xa5, 0x9b, 0x84, 0x56, 0x6e, 0xaa, 0x8b, 0x8f, 0xb0, 0x2c, 0x87, 0xaf, 0x67}} , {{0x00, 0xa9, 0x4c, 0xb2, 0x12, 0xf8, 0x32, 0xa8, 0x7a, 0x00, 0x4b, 0x49, 0x32, 0xba, 0x1f, 0x5d, 0x44, 0x8e, 0x44, 0x7a, 0xdc, 0x11, 0xfb, 0x39, 0x08, 0x57, 0x87, 0xa5, 0x12, 0x42, 0x93, 0x0e}}}, {{{0x17, 0xb4, 0xae, 0x72, 0x59, 0xd0, 0xaa, 0xa8, 0x16, 0x8b, 0x63, 0x11, 0xb3, 0x43, 0x04, 0xda, 0x0c, 0xa8, 0xb7, 0x68, 0xdd, 0x4e, 0x54, 0xe7, 0xaf, 0x5d, 0x5d, 0x05, 0x76, 0x36, 0xec, 0x0d}} , {{0x6d, 0x7c, 0x82, 0x32, 0x38, 0x55, 0x57, 0x74, 0x5b, 0x7d, 0xc3, 0xc4, 0xfb, 0x06, 0x29, 0xf0, 0x13, 0x55, 0x54, 0xc6, 0xa7, 0xdc, 0x4c, 0x9f, 0x98, 0x49, 0x20, 0xa8, 0xc3, 0x8d, 0xfa, 0x48}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x87, 0x47, 0x9d, 0xe9, 0x25, 0xd5, 0xe3, 0x47, 0x78, 0xdf, 0x85, 0xa7, 0x85, 0x5e, 0x7a, 0x4c, 0x5f, 0x79, 0x1a, 0xf3, 0xa2, 0xb2, 0x28, 0xa0, 0x9c, 0xdd, 0x30, 0x40, 0xd4, 0x38, 0xbd, 0x28}} , {{0xfc, 0xbb, 0xd5, 0x78, 0x6d, 0x1d, 0xd4, 0x99, 0xb4, 0xaa, 0x44, 0x44, 0x7a, 0x1b, 0xd8, 0xfe, 0xb4, 0x99, 0xb9, 0xcc, 0xe7, 0xc4, 0xd3, 0x3a, 0x73, 0x83, 0x41, 0x5c, 0x40, 0xd7, 0x2d, 0x55}}}, {{{0x26, 0xe1, 0x7b, 0x5f, 0xe5, 0xdc, 0x3f, 0x7d, 0xa1, 0xa7, 0x26, 0x44, 0x22, 0x23, 0xc0, 0x8f, 0x7d, 0xf1, 0xb5, 0x11, 0x47, 0x7b, 0x19, 0xd4, 0x75, 0x6f, 0x1e, 0xa5, 0x27, 0xfe, 0xc8, 0x0e}} , {{0xd3, 0x11, 0x3d, 0xab, 0xef, 0x2c, 0xed, 0xb1, 0x3d, 0x7c, 0x32, 0x81, 0x6b, 0xfe, 0xf8, 0x1c, 0x3c, 0x7b, 0xc0, 0x61, 0xdf, 0xb8, 0x75, 0x76, 0x7f, 0xaa, 0xd8, 0x93, 0xaf, 0x3d, 0xe8, 0x3d}}}, {{{0xfd, 0x5b, 0x4e, 0x8d, 0xb6, 0x7e, 0x82, 0x9b, 0xef, 0xce, 0x04, 0x69, 0x51, 0x52, 0xff, 0xef, 0xa0, 0x52, 0xb5, 0x79, 0x17, 0x5e, 0x2f, 0xde, 0xd6, 0x3c, 0x2d, 0xa0, 0x43, 0xb4, 0x0b, 0x19}} , {{0xc0, 0x61, 0x48, 0x48, 0x17, 0xf4, 0x9e, 0x18, 0x51, 0x2d, 0xea, 0x2f, 0xf2, 0xf2, 0xe0, 0xa3, 0x14, 0xb7, 0x8b, 0x3a, 0x30, 0xf5, 0x81, 0xc1, 0x5d, 0x71, 0x39, 0x62, 0x55, 0x1f, 0x60, 0x5a}}}, {{{0xe5, 0x89, 0x8a, 0x76, 0x6c, 0xdb, 0x4d, 0x0a, 0x5b, 0x72, 0x9d, 0x59, 0x6e, 0x63, 0x63, 0x18, 0x7c, 0xe3, 0xfa, 0xe2, 0xdb, 0xa1, 0x8d, 0xf4, 0xa5, 0xd7, 0x16, 0xb2, 0xd0, 0xb3, 0x3f, 0x39}} , {{0xce, 0x60, 0x09, 0x6c, 0xf5, 0x76, 0x17, 0x24, 0x80, 0x3a, 0x96, 0xc7, 0x94, 0x2e, 0xf7, 0x6b, 0xef, 0xb5, 0x05, 0x96, 0xef, 0xd3, 0x7b, 0x51, 0xda, 0x05, 0x44, 0x67, 0xbc, 0x07, 0x21, 0x4e}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xe9, 0x73, 0x6f, 0x21, 0xb9, 0xde, 0x22, 0x7d, 0xeb, 0x97, 0x31, 0x10, 0xa3, 0xea, 0xe1, 0xc6, 0x37, 0xeb, 0x8f, 0x43, 0x58, 0xde, 0x41, 0x64, 0x0e, 0x3e, 0x07, 0x99, 0x3d, 0xf1, 0xdf, 0x1e}} , {{0xf8, 0xad, 0x43, 0xc2, 0x17, 0x06, 0xe2, 0xe4, 0xa9, 0x86, 0xcd, 0x18, 0xd7, 0x78, 0xc8, 0x74, 0x66, 0xd2, 0x09, 0x18, 0xa5, 0xf1, 0xca, 0xa6, 0x62, 0x92, 0xc1, 0xcb, 0x00, 0xeb, 0x42, 0x2e}}}, {{{0x7b, 0x34, 0x24, 0x4c, 0xcf, 0x38, 0xe5, 0x6c, 0x0a, 0x01, 0x2c, 0x22, 0x0b, 0x24, 0x38, 0xad, 0x24, 0x7e, 0x19, 0xf0, 0x6c, 0xf9, 0x31, 0xf4, 0x35, 0x11, 0xf6, 0x46, 0x33, 0x3a, 0x23, 0x59}} , {{0x20, 0x0b, 0xa1, 0x08, 0x19, 0xad, 0x39, 0x54, 0xea, 0x3e, 0x23, 0x09, 0xb6, 0xe2, 0xd2, 0xbc, 0x4d, 0xfc, 0x9c, 0xf0, 0x13, 0x16, 0x22, 0x3f, 0xb9, 0xd2, 0x11, 0x86, 0x90, 0x55, 0xce, 0x3c}}}, {{{0xc4, 0x0b, 0x4b, 0x62, 0x99, 0x37, 0x84, 0x3f, 0x74, 0xa2, 0xf9, 0xce, 0xe2, 0x0b, 0x0f, 0x2a, 0x3d, 0xa3, 0xe3, 0xdb, 0x5a, 0x9d, 0x93, 0xcc, 0xa5, 0xef, 0x82, 0x91, 0x1d, 0xe6, 0x6c, 0x68}} , {{0xa3, 0x64, 0x17, 0x9b, 0x8b, 0xc8, 0x3a, 0x61, 0xe6, 0x9d, 0xc6, 0xed, 0x7b, 0x03, 0x52, 0x26, 0x9d, 0x3a, 0xb3, 0x13, 0xcc, 0x8a, 0xfd, 0x2c, 0x1a, 0x1d, 0xed, 0x13, 0xd0, 0x55, 0x57, 0x0e}}}, {{{0x1a, 0xea, 0xbf, 0xfd, 0x4a, 0x3c, 0x8e, 0xec, 0x29, 0x7e, 0x77, 0x77, 0x12, 0x99, 0xd7, 0x84, 0xf9, 0x55, 0x7f, 0xf1, 0x8b, 0xb4, 0xd2, 0x95, 0xa3, 0x8d, 0xf0, 0x8a, 0xa7, 0xeb, 0x82, 0x4b}} , {{0x2c, 0x28, 0xf4, 0x3a, 0xf6, 0xde, 0x0a, 0xe0, 0x41, 0x44, 0x23, 0xf8, 0x3f, 0x03, 0x64, 0x9f, 0xc3, 0x55, 0x4c, 0xc6, 0xc1, 0x94, 0x1c, 0x24, 0x5d, 0x5f, 0x92, 0x45, 0x96, 0x57, 0x37, 0x14}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc1, 0xcd, 0x90, 0x66, 0xb9, 0x76, 0xa0, 0x5b, 0xa5, 0x85, 0x75, 0x23, 0xf9, 0x89, 0xa5, 0x82, 0xb2, 0x6f, 0xb1, 0xeb, 0xc4, 0x69, 0x6f, 0x18, 0x5a, 0xed, 0x94, 0x3d, 0x9d, 0xd9, 0x2c, 0x1a}} , {{0x35, 0xb0, 0xe6, 0x73, 0x06, 0xb7, 0x37, 0xe0, 0xf8, 0xb0, 0x22, 0xe8, 0xd2, 0xed, 0x0b, 0xef, 0xe6, 0xc6, 0x5a, 0x99, 0x9e, 0x1a, 0x9f, 0x04, 0x97, 0xe4, 0x4d, 0x0b, 0xbe, 0xba, 0x44, 0x40}}}, {{{0xc1, 0x56, 0x96, 0x91, 0x5f, 0x1f, 0xbb, 0x54, 0x6f, 0x88, 0x89, 0x0a, 0xb2, 0xd6, 0x41, 0x42, 0x6a, 0x82, 0xee, 0x14, 0xaa, 0x76, 0x30, 0x65, 0x0f, 0x67, 0x39, 0xa6, 0x51, 0x7c, 0x49, 0x24}} , {{0x35, 0xa3, 0x78, 0xd1, 0x11, 0x0f, 0x75, 0xd3, 0x70, 0x46, 0xdb, 0x20, 0x51, 0xcb, 0x92, 0x80, 0x54, 0x10, 0x74, 0x36, 0x86, 0xa9, 0xd7, 0xa3, 0x08, 0x78, 0xf1, 0x01, 0x29, 0xf8, 0x80, 0x3b}}}, {{{0xdb, 0xa7, 0x9d, 0x9d, 0xbf, 0xa0, 0xcc, 0xed, 0x53, 0xa2, 0xa2, 0x19, 0x39, 0x48, 0x83, 0x19, 0x37, 0x58, 0xd1, 0x04, 0x28, 0x40, 0xf7, 0x8a, 0xc2, 0x08, 0xb7, 0xa5, 0x42, 0xcf, 0x53, 0x4c}} , {{0xa7, 0xbb, 0xf6, 0x8e, 0xad, 0xdd, 0xf7, 0x90, 0xdd, 0x5f, 0x93, 0x89, 0xae, 0x04, 0x37, 0xe6, 0x9a, 0xb7, 0xe8, 0xc0, 0xdf, 0x16, 0x2a, 0xbf, 0xc4, 0x3a, 0x3c, 0x41, 0xd5, 0x89, 0x72, 0x5a}}}, {{{0x1f, 0x96, 0xff, 0x34, 0x2c, 0x13, 0x21, 0xcb, 0x0a, 0x89, 0x85, 0xbe, 0xb3, 0x70, 0x9e, 0x1e, 0xde, 0x97, 0xaf, 0x96, 0x30, 0xf7, 0x48, 0x89, 0x40, 0x8d, 0x07, 0xf1, 0x25, 0xf0, 0x30, 0x58}} , {{0x1e, 0xd4, 0x93, 0x57, 0xe2, 0x17, 0xe7, 0x9d, 0xab, 0x3c, 0x55, 0x03, 0x82, 0x2f, 0x2b, 0xdb, 0x56, 0x1e, 0x30, 0x2e, 0x24, 0x47, 0x6e, 0xe6, 0xff, 0x33, 0x24, 0x2c, 0x75, 0x51, 0xd4, 0x67}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2b, 0x06, 0xd9, 0xa1, 0x5d, 0xe1, 0xf4, 0xd1, 0x1e, 0x3c, 0x9a, 0xc6, 0x29, 0x2b, 0x13, 0x13, 0x78, 0xc0, 0xd8, 0x16, 0x17, 0x2d, 0x9e, 0xa9, 0xc9, 0x79, 0x57, 0xab, 0x24, 0x91, 0x92, 0x19}} , {{0x69, 0xfb, 0xa1, 0x9c, 0xa6, 0x75, 0x49, 0x7d, 0x60, 0x73, 0x40, 0x42, 0xc4, 0x13, 0x0a, 0x95, 0x79, 0x1e, 0x04, 0x83, 0x94, 0x99, 0x9b, 0x1e, 0x0c, 0xe8, 0x1f, 0x54, 0xef, 0xcb, 0xc0, 0x52}}}, {{{0x14, 0x89, 0x73, 0xa1, 0x37, 0x87, 0x6a, 0x7a, 0xcf, 0x1d, 0xd9, 0x2e, 0x1a, 0x67, 0xed, 0x74, 0xc0, 0xf0, 0x9c, 0x33, 0xdd, 0xdf, 0x08, 0xbf, 0x7b, 0xd1, 0x66, 0xda, 0xe6, 0xc9, 0x49, 0x08}} , {{0xe9, 0xdd, 0x5e, 0x55, 0xb0, 0x0a, 0xde, 0x21, 0x4c, 0x5a, 0x2e, 0xd4, 0x80, 0x3a, 0x57, 0x92, 0x7a, 0xf1, 0xc4, 0x2c, 0x40, 0xaf, 0x2f, 0xc9, 0x92, 0x03, 0xe5, 0x5a, 0xbc, 0xdc, 0xf4, 0x09}}}, {{{0xf3, 0xe1, 0x2b, 0x7c, 0x05, 0x86, 0x80, 0x93, 0x4a, 0xad, 0xb4, 0x8f, 0x7e, 0x99, 0x0c, 0xfd, 0xcd, 0xef, 0xd1, 0xff, 0x2c, 0x69, 0x34, 0x13, 0x41, 0x64, 0xcf, 0x3b, 0xd0, 0x90, 0x09, 0x1e}} , {{0x9d, 0x45, 0xd6, 0x80, 0xe6, 0x45, 0xaa, 0xf4, 0x15, 0xaa, 0x5c, 0x34, 0x87, 0x99, 0xa2, 0x8c, 0x26, 0x84, 0x62, 0x7d, 0xb6, 0x29, 0xc0, 0x52, 0xea, 0xf5, 0x81, 0x18, 0x0f, 0x35, 0xa9, 0x0e}}}, {{{0xe7, 0x20, 0x72, 0x7c, 0x6d, 0x94, 0x5f, 0x52, 0x44, 0x54, 0xe3, 0xf1, 0xb2, 0xb0, 0x36, 0x46, 0x0f, 0xae, 0x92, 0xe8, 0x70, 0x9d, 0x6e, 0x79, 0xb1, 0xad, 0x37, 0xa9, 0x5f, 0xc0, 0xde, 0x03}} , {{0x15, 0x55, 0x37, 0xc6, 0x1c, 0x27, 0x1c, 0x6d, 0x14, 0x4f, 0xca, 0xa4, 0xc4, 0x88, 0x25, 0x46, 0x39, 0xfc, 0x5a, 0xe5, 0xfe, 0x29, 0x11, 0x69, 0xf5, 0x72, 0x84, 0x4d, 0x78, 0x9f, 0x94, 0x15}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xec, 0xd3, 0xff, 0x57, 0x0b, 0xb0, 0xb2, 0xdc, 0xf8, 0x4f, 0xe2, 0x12, 0xd5, 0x36, 0xbe, 0x6b, 0x09, 0x43, 0x6d, 0xa3, 0x4d, 0x90, 0x2d, 0xb8, 0x74, 0xe8, 0x71, 0x45, 0x19, 0x8b, 0x0c, 0x6a}} , {{0xb8, 0x42, 0x1c, 0x03, 0xad, 0x2c, 0x03, 0x8e, 0xac, 0xd7, 0x98, 0x29, 0x13, 0xc6, 0x02, 0x29, 0xb5, 0xd4, 0xe7, 0xcf, 0xcc, 0x8b, 0x83, 0xec, 0x35, 0xc7, 0x9c, 0x74, 0xb7, 0xad, 0x85, 0x5f}}}, {{{0x78, 0x84, 0xe1, 0x56, 0x45, 0x69, 0x68, 0x5a, 0x4f, 0xb8, 0xb1, 0x29, 0xff, 0x33, 0x03, 0x31, 0xb7, 0xcb, 0x96, 0x25, 0xe6, 0xe6, 0x41, 0x98, 0x1a, 0xbb, 0x03, 0x56, 0xf2, 0xb2, 0x91, 0x34}} , {{0x2c, 0x6c, 0xf7, 0x66, 0xa4, 0x62, 0x6b, 0x39, 0xb3, 0xba, 0x65, 0xd3, 0x1c, 0xf8, 0x11, 0xaa, 0xbe, 0xdc, 0x80, 0x59, 0x87, 0xf5, 0x7b, 0xe5, 0xe3, 0xb3, 0x3e, 0x39, 0xda, 0xbe, 0x88, 0x09}}}, {{{0x8b, 0xf1, 0xa0, 0xf5, 0xdc, 0x29, 0xb4, 0xe2, 0x07, 0xc6, 0x7a, 0x00, 0xd0, 0x89, 0x17, 0x51, 0xd4, 0xbb, 0xd4, 0x22, 0xea, 0x7e, 0x7d, 0x7c, 0x24, 0xea, 0xf2, 0xe8, 0x22, 0x12, 0x95, 0x06}} , {{0xda, 0x7c, 0xa4, 0x0c, 0xf4, 0xba, 0x6e, 0xe1, 0x89, 0xb5, 0x59, 0xca, 0xf1, 0xc0, 0x29, 0x36, 0x09, 0x44, 0xe2, 0x7f, 0xd1, 0x63, 0x15, 0x99, 0xea, 0x25, 0xcf, 0x0c, 0x9d, 0xc0, 0x44, 0x6f}}}, {{{0x1d, 0x86, 0x4e, 0xcf, 0xf7, 0x37, 0x10, 0x25, 0x8f, 0x12, 0xfb, 0x19, 0xfb, 0xe0, 0xed, 0x10, 0xc8, 0xe2, 0xf5, 0x75, 0xb1, 0x33, 0xc0, 0x96, 0x0d, 0xfb, 0x15, 0x6c, 0x0d, 0x07, 0x5f, 0x05}} , {{0x69, 0x3e, 0x47, 0x97, 0x2c, 0xaf, 0x52, 0x7c, 0x78, 0x83, 0xad, 0x1b, 0x39, 0x82, 0x2f, 0x02, 0x6f, 0x47, 0xdb, 0x2a, 0xb0, 0xe1, 0x91, 0x99, 0x55, 0xb8, 0x99, 0x3a, 0xa0, 0x44, 0x11, 0x51}}} }; static void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) { fe25519_mul(&r->x, &p->x, &p->t); fe25519_mul(&r->y, &p->y, &p->z); fe25519_mul(&r->z, &p->z, &p->t); } static void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) { p1p1_to_p2((ge25519_p2 *)r, p); fe25519_mul(&r->t, &p->x, &p->y); } static void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) { fe25519 a,b,t1,t2,c,d,e,f,g,h,qt; fe25519_mul(&qt, &q->x, &q->y); fe25519_sub(&a, &r->y, &r->x); /* A = (Y1-X1)*(Y2-X2) */ fe25519_add(&b, &r->y, &r->x); /* B = (Y1+X1)*(Y2+X2) */ fe25519_sub(&t1, &q->y, &q->x); fe25519_add(&t2, &q->y, &q->x); fe25519_mul(&a, &a, &t1); fe25519_mul(&b, &b, &t2); fe25519_sub(&e, &b, &a); /* E = B-A */ fe25519_add(&h, &b, &a); /* H = B+A */ fe25519_mul(&c, &r->t, &qt); /* C = T1*k*T2 */ fe25519_mul(&c, &c, &ge25519_ec2d); fe25519_add(&d, &r->z, &r->z); /* D = Z1*2 */ fe25519_sub(&f, &d, &c); /* F = D-C */ fe25519_add(&g, &d, &c); /* G = D+C */ fe25519_mul(&r->x, &e, &f); fe25519_mul(&r->y, &h, &g); fe25519_mul(&r->z, &g, &f); fe25519_mul(&r->t, &e, &h); } static void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) { fe25519 a, b, c, d, t; fe25519_sub(&a, &p->y, &p->x); /* A = (Y1-X1)*(Y2-X2) */ fe25519_sub(&t, &q->y, &q->x); fe25519_mul(&a, &a, &t); fe25519_add(&b, &p->x, &p->y); /* B = (Y1+X1)*(Y2+X2) */ fe25519_add(&t, &q->x, &q->y); fe25519_mul(&b, &b, &t); fe25519_mul(&c, &p->t, &q->t); /* C = T1*k*T2 */ fe25519_mul(&c, &c, &ge25519_ec2d); fe25519_mul(&d, &p->z, &q->z); /* D = Z1*2*Z2 */ fe25519_add(&d, &d, &d); fe25519_sub(&r->x, &b, &a); /* E = B-A */ fe25519_sub(&r->t, &d, &c); /* F = D-C */ fe25519_add(&r->z, &d, &c); /* G = D+C */ fe25519_add(&r->y, &b, &a); /* H = B+A */ } /* See http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */ static void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) { fe25519 a,b,c,d; fe25519_square(&a, &p->x); fe25519_square(&b, &p->y); fe25519_square(&c, &p->z); fe25519_add(&c, &c, &c); fe25519_neg(&d, &a); fe25519_add(&r->x, &p->x, &p->y); fe25519_square(&r->x, &r->x); fe25519_sub(&r->x, &r->x, &a); fe25519_sub(&r->x, &r->x, &b); fe25519_add(&r->z, &d, &b); fe25519_sub(&r->t, &r->z, &c); fe25519_sub(&r->y, &d, &b); } /* Constant-time version of: if(b) r = p */ static void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) { fe25519_cmov(&r->x, &p->x, b); fe25519_cmov(&r->y, &p->y, b); } static unsigned char equal(signed char b,signed char c) { unsigned char ub = b; unsigned char uc = c; unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ crypto_uint32 y = x; /* 0: yes; 1..255: no */ y -= 1; /* 4294967295: yes; 0..254: no */ y >>= 31; /* 1: yes; 0: no */ return y; } static unsigned char negative(signed char b) { unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ return x; } static void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) { /* constant time */ fe25519 v; *t = ge25519_base_multiples_affine[5*pos+0]; cmov_aff(t, &ge25519_base_multiples_affine[5*pos+1],equal(b,1) | equal(b,-1)); cmov_aff(t, &ge25519_base_multiples_affine[5*pos+2],equal(b,2) | equal(b,-2)); cmov_aff(t, &ge25519_base_multiples_affine[5*pos+3],equal(b,3) | equal(b,-3)); cmov_aff(t, &ge25519_base_multiples_affine[5*pos+4],equal(b,-4)); fe25519_neg(&v, &t->x); fe25519_cmov(&t->x, &v, negative(b)); } static void setneutral(ge25519 *r) { fe25519_setzero(&r->x); fe25519_setone(&r->y); fe25519_setone(&r->z); fe25519_setzero(&r->t); } /* ******************************************************************** * EXPORTED FUNCTIONS ******************************************************************** */ /* return 0 on success, -1 otherwise */ int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) { unsigned char par; fe25519 t, chk, num, den, den2, den4, den6; fe25519_setone(&r->z); par = p[31] >> 7; fe25519_unpack(&r->y, p); fe25519_square(&num, &r->y); /* x = y^2 */ fe25519_mul(&den, &num, &ge25519_ecd); /* den = dy^2 */ fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */ fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */ /* Computation of sqrt(num/den) */ /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ fe25519_square(&den2, &den); fe25519_square(&den4, &den2); fe25519_mul(&den6, &den4, &den2); fe25519_mul(&t, &den6, &num); fe25519_mul(&t, &t, &den); fe25519_pow2523(&t, &t); /* 2. computation of r->x = t * num * den^3 */ fe25519_mul(&t, &t, &num); fe25519_mul(&t, &t, &den); fe25519_mul(&t, &t, &den); fe25519_mul(&r->x, &t, &den); /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */ fe25519_square(&chk, &r->x); fe25519_mul(&chk, &chk, &den); if (!fe25519_iseq_vartime(&chk, &num)) fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1); /* 4. Now we have one of the two square roots, except if input was not a square */ fe25519_square(&chk, &r->x); fe25519_mul(&chk, &chk, &den); if (!fe25519_iseq_vartime(&chk, &num)) return -1; /* 5. Choose the desired square root according to parity: */ if(fe25519_getparity(&r->x) != (1-par)) fe25519_neg(&r->x, &r->x); fe25519_mul(&r->t, &r->x, &r->y); return 0; } static void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) { fe25519 tx, ty, zi; fe25519_invert(&zi, &p->z); fe25519_mul(&tx, &p->x, &zi); fe25519_mul(&ty, &p->y, &zi); fe25519_pack(r, &ty); r[31] ^= fe25519_getparity(&tx) << 7; } int ge25519_isneutral_vartime(const ge25519_p3 *p) { int ret = 1; if(!fe25519_iszero(&p->x)) ret = 0; if(!fe25519_iseq_vartime(&p->y, &p->z)) ret = 0; return ret; } /* computes [s1]p1 + [s2]p2 */ static void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) { ge25519_p1p1 tp1p1; ge25519_p3 pre[16]; unsigned char b[127]; int i; /* precomputation s2 s1 */ setneutral(pre); /* 00 00 */ pre[1] = *p1; /* 00 01 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)p1); p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */ add_p1p1(&tp1p1,&pre[1], &pre[2]); p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */ pre[4] = *p2; /* 01 00 */ add_p1p1(&tp1p1,&pre[1], &pre[4]); p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */ add_p1p1(&tp1p1,&pre[2], &pre[4]); p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */ add_p1p1(&tp1p1,&pre[3], &pre[4]); p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)p2); p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */ add_p1p1(&tp1p1,&pre[1], &pre[8]); p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)&pre[5]); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */ add_p1p1(&tp1p1,&pre[3], &pre[8]); p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */ add_p1p1(&tp1p1,&pre[4], &pre[8]); p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */ add_p1p1(&tp1p1,&pre[1],&pre[12]); p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */ add_p1p1(&tp1p1,&pre[2],&pre[12]); p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */ add_p1p1(&tp1p1,&pre[3],&pre[12]); p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */ sc25519_2interleave2(b,s1,s2); /* scalar multiplication */ *r = pre[b[126]]; for(i=125;i>=0;i--) { dbl_p1p1(&tp1p1, (ge25519_p2 *)r); p1p1_to_p2((ge25519_p2 *) r, &tp1p1); dbl_p1p1(&tp1p1, (ge25519_p2 *)r); if(b[i]!=0) { p1p1_to_p3(r, &tp1p1); add_p1p1(&tp1p1, r, &pre[b[i]]); } if(i != 0) p1p1_to_p2((ge25519_p2 *)r, &tp1p1); else p1p1_to_p3(r, &tp1p1); } } static void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) { signed char b[85]; int i; ge25519_aff t; sc25519_window3(b,s); choose_t((ge25519_aff *)r, 0, b[0]); fe25519_setone(&r->z); fe25519_mul(&r->t, &r->x, &r->y); for(i=1;i<85;i++) { choose_t(&t, (unsigned long long) i, b[i]); ge25519_mixadd2(r, &t); } } /* from supercop-20221122/crypto_sign/ed25519/ref/keypair.c */ int crypto_sign_ed25519_keypair(unsigned char *pk,unsigned char *sk) { unsigned char az[64]; sc25519 scsk; ge25519 gepk; randombytes(sk,32); crypto_hash_sha512(az,sk,32); az[0] &= 248; az[31] &= 127; az[31] |= 64; sc25519_from32bytes(&scsk,az); ge25519_scalarmult_base(&gepk, &scsk); ge25519_pack(pk, &gepk); memmove(sk + 32,pk,32); return 0; } /* from supercop-20221122/crypto_sign/ed25519/ref/sign.c */ int crypto_sign_ed25519( unsigned char *sm,unsigned long long *smlen, const unsigned char *m,unsigned long long mlen, const unsigned char *sk ) { unsigned char pk[32]; unsigned char az[64]; unsigned char nonce[64]; unsigned char hram[64]; sc25519 sck, scs, scsk; ge25519 ger; memmove(pk,sk + 32,32); /* pk: 32-byte public key A */ crypto_hash_sha512(az,sk,32); az[0] &= 248; az[31] &= 127; az[31] |= 64; /* az: 32-byte scalar a, 32-byte randomizer z */ *smlen = mlen + 64; memmove(sm + 64,m,mlen); memmove(sm + 32,az + 32,32); /* sm: 32-byte uninit, 32-byte z, mlen-byte m */ crypto_hash_sha512(nonce, sm+32, mlen+32); /* nonce: 64-byte H(z,m) */ sc25519_from64bytes(&sck, nonce); ge25519_scalarmult_base(&ger, &sck); ge25519_pack(sm, &ger); /* sm: 32-byte R, 32-byte z, mlen-byte m */ memmove(sm + 32,pk,32); /* sm: 32-byte R, 32-byte A, mlen-byte m */ crypto_hash_sha512(hram,sm,mlen + 64); /* hram: 64-byte H(R,A,m) */ sc25519_from64bytes(&scs, hram); sc25519_from32bytes(&scsk, az); sc25519_mul(&scs, &scs, &scsk); sc25519_add(&scs, &scs, &sck); /* scs: S = nonce + H(R,A,m)a */ sc25519_to32bytes(sm + 32,&scs); /* sm: 32-byte R, 32-byte S, mlen-byte m */ return 0; } /* from supercop-20221122/crypto_sign/ed25519/ref/open.c */ int crypto_sign_ed25519_open( unsigned char *m,unsigned long long *mlen, const unsigned char *sm,unsigned long long smlen, const unsigned char *pk ) { unsigned char pkcopy[32]; unsigned char rcopy[32]; unsigned char hram[64]; unsigned char rcheck[32]; ge25519 get1, get2; sc25519 schram, scs; if (smlen < 64) goto badsig; if (sm[63] & 224) goto badsig; if (ge25519_unpackneg_vartime(&get1,pk)) goto badsig; memmove(pkcopy,pk,32); memmove(rcopy,sm,32); sc25519_from32bytes(&scs, sm+32); memmove(m,sm,smlen); memmove(m + 32,pkcopy,32); crypto_hash_sha512(hram,m,smlen); sc25519_from64bytes(&schram, hram); ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); ge25519_pack(rcheck, &get2); if (crypto_verify_32(rcopy,rcheck) == 0) { memmove(m,m + 64,smlen - 64); memset(m + smlen - 64,0,64); *mlen = smlen - 64; return 0; } badsig: *mlen = (unsigned long long) -1; memset(m,0,smlen); return -1; } openssh-10.0p1/PaxHeaders.10889/ed25519.sh100644 001750 001750 0000000003614775415623 0014506xustar0030 atime=1744182234.567211683 openssh-10.0p1/ed25519.sh010064400017500001750000000101021477541562300130630ustar00djmdjm#!/bin/sh # $OpenBSD: ed25519.sh,v 1.2 2024/05/17 02:39:11 jsg Exp $ # Placed in the Public Domain. # AUTHOR="supercop-20221122/crypto_sign/ed25519/ref/implementors" FILES=" supercop-20221122/crypto_verify/32/ref/verify.c supercop-20221122/crypto_sign/ed25519/ref/fe25519.h supercop-20221122/crypto_sign/ed25519/ref/fe25519.c supercop-20221122/crypto_sign/ed25519/ref/sc25519.h supercop-20221122/crypto_sign/ed25519/ref/sc25519.c supercop-20221122/crypto_sign/ed25519/ref/ge25519.h supercop-20221122/crypto_sign/ed25519/ref/ge25519.c supercop-20221122/crypto_sign/ed25519/ref/keypair.c supercop-20221122/crypto_sign/ed25519/ref/sign.c supercop-20221122/crypto_sign/ed25519/ref/open.c " ### DATA="supercop-20221122/crypto_sign/ed25519/ref/ge25519_base.data" set -e cd $1 echo -n '/* $' echo 'OpenBSD: $ */' echo echo '/*' echo ' * Public Domain, Authors:' sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR echo ' */' echo echo '#include ' echo echo '#include "crypto_api.h"' echo # Map the types used in this code to the ones in crypto_api.h. We use #define # instead of typedef since some systems have existing intXX types and do not # permit multiple typedefs even if they do not conflict. for t in int8 uint8 int16 uint16 int32 uint32 int64 uint64; do echo "#define $t crypto_${t}" done echo for i in $FILES; do echo "/* from $i */" # Changes to all files: # - inline ge25519_base.data where it is included # - expand CRYPTO_NAMESPACE() namespacing define # - remove all includes, we inline everything required. # - make functions not required elsewhere static. # - rename the functions we do use. sed \ -e "/#include \"ge25519_base.data\"/r $DATA" \ -e "/#include/d" \ -e "s/^void /static void /g" \ -e 's/CRYPTO_NAMESPACE[(]\([a-zA-Z0-9_]*\)[)]/crypto_sign_ed25519_ref_\1/g' \ $i | \ case "$i" in */crypto_verify/32/ref/verify.c) # rename crypto_verify() to the name that the ed25519 code expects. sed -e "/^#include.*/d" \ -e "s/crypto_verify/crypto_verify_32/g" \ -e "s/^int /static int /g" ;; */crypto_sign/ed25519/ref/sign.c) # rename signing function to the name OpenSSH expects sed -e "s/crypto_sign/crypto_sign_ed25519/g" ;; */crypto_sign/ed25519/ref/keypair.c) # rename key generation function to the name OpenSSH expects sed -e "s/crypto_sign_keypair/crypto_sign_ed25519_keypair/g" ;; */crypto_sign/ed25519/ref/open.c) # rename verification function to the name OpenSSH expects sed -e "s/crypto_sign_open/crypto_sign_ed25519_open/g" ;; */crypto_sign/ed25519/ref/fe25519.*) # avoid a couple of name collisions with other files sed -e "s/reduce_add_sub/fe25519_reduce_add_sub/g" \ -e "s/ equal[(]/ fe25519_equal(/g" \ -e "s/^int /static int /g" ;; */crypto_sign/ed25519/ref/sc25519.h) # Lots of unused prototypes to remove sed -e "s/^int /static int /g" \ -e '/shortsc25519_from16bytes/d' \ -e '/sc25519_iszero_vartime/d' \ -e '/sc25519_isshort_vartime/d' \ -e '/sc25519_lt_vartime/d' \ -e '/sc25519_sub_nored/d' \ -e '/sc25519_mul_shortsc/d' \ -e '/sc25519_from_shortsc/d' \ -e '/sc25519_window5/d' ;; */crypto_sign/ed25519/ref/sc25519.c) # Lots of unused code to remove, some name collisions to avoid sed -e "s/reduce_add_sub/sc25519_reduce_add_sub/g" \ -e "s/ equal[(]/ sc25519_equal(/g" \ -e "s/^int /static int /g" \ -e "s/m[[]/sc25519_m[/g" \ -e "s/mu[[]/sc25519_mu[/g" \ -e '/shortsc25519_from16bytes/,/^}$/d' \ -e '/sc25519_iszero_vartime/,/^}$/d' \ -e '/sc25519_isshort_vartime/,/^}$/d' \ -e '/sc25519_lt_vartime/,/^}$/d' \ -e '/sc25519_sub_nored/,/^}$/d' \ -e '/sc25519_mul_shortsc/,/^}$/d' \ -e '/sc25519_from_shortsc/,/^}$/d' \ -e '/sc25519_window5/,/^}$/d' ;; */crypto_sign/ed25519/ref//ge25519.*) sed -e "s/^int /static int /g" ;; # Default: pass through. *) cat ;; esac | \ sed -e 's/[ ]*$//' done openssh-10.0p1/PaxHeaders.10889/entropy.c100644 001750 001750 0000000003614775415623 0015020xustar0030 atime=1744182234.567211683 openssh-10.0p1/entropy.c010064400017500001750000000060211477541562300134020ustar00djmdjm/* * Copyright (c) 2001 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #define RANDOM_SEED_SIZE 48 #ifdef WITH_OPENSSL #include #include #include #include #include #include #include #include #include #include "openbsd-compat/openssl-compat.h" #include "ssh.h" #include "misc.h" #include "xmalloc.h" #include "atomicio.h" #include "pathnames.h" #include "log.h" #include "sshbuf.h" #include "ssherr.h" /* * Portable OpenSSH PRNG seeding: * If OpenSSL has not "internally seeded" itself (e.g. pulled data from * /dev/random), then collect RANDOM_SEED_SIZE bytes of randomness from * PRNGd. */ void seed_rng(void) { unsigned char buf[RANDOM_SEED_SIZE]; /* 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, OpenSSL_version_num()); #ifndef OPENSSL_PRNG_ONLY if (RAND_status() == 1) debug3("RNG is ready, skipping seeding"); else { if (seed_from_prngd(buf, sizeof(buf)) == -1) fatal("Could not obtain seed from PRNGd"); RAND_add(buf, sizeof(buf), 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 */ #include #include /* 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 */ openssh-10.0p1/PaxHeaders.10889/entropy.h100644 001750 001750 0000000003614775415623 0015025xustar0030 atime=1744182234.567211683 openssh-10.0p1/entropy.h010064400017500001750000000027451477541562300134200ustar00djmdjm/* * Copyright (c) 1999-2000 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. */ #ifndef _RANDOMS_H #define _RANDOMS_H struct sshbuf; void seed_rng(void); void rexec_send_rng_seed(struct sshbuf *); void rexec_recv_rng_seed(struct sshbuf *); #endif /* _RANDOMS_H */ openssh-10.0p1/PaxHeaders.10889/fatal.c100644 001750 001750 0000000003614775415623 0014407xustar0030 atime=1744182234.567211683 openssh-10.0p1/fatal.c010064400017500001750000000034021477541562300127710ustar00djmdjm/* $OpenBSD: fatal.c,v 1.11 2020/10/19 08:07:08 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include "log.h" /* Fatal messages. This function never returns. */ void sshfatal(const char *file, const char *func, int line, int showfunc, LogLevel level, const char *suffix, const char *fmt, ...) { va_list args; va_start(args, fmt); sshlogv(file, func, line, showfunc, level, suffix, fmt, args); va_end(args); cleanup_exit(255); } openssh-10.0p1/PaxHeaders.10889/fixalgorithms100755 001750 001750 0000000003614775415623 0015762xustar0030 atime=1744182234.567211683 openssh-10.0p1/fixalgorithms010075500017500001750000000006461477541562300143530ustar00djmdjm#!/bin/sh # # fixciphers - remove unsupported ciphers from man pages. # Usage: fixpaths /path/to/sed cipher1 [cipher2] outfile # # Author: Darren Tucker (dtucker at zip com.au). Placed in the public domain. die() { echo $* exit -1 } SED=$1 shift for c in $*; do subs="$subs -e /.Dq.$c.*$/d" subs="$subs -e s/$c,//g" done # now remove any entirely empty lines subs="$subs -e /^$/d" ${SED} $subs exit 0 openssh-10.0p1/PaxHeaders.10889/fixpaths100755 001750 001750 0000000003614775415623 0014730xustar0030 atime=1744182234.567211683 openssh-10.0p1/fixpaths010075500017500001750000000007631477541562300133210ustar00djmdjm#!/bin/sh # # fixpaths - substitute makefile variables into text files # Usage: fixpaths -Dsomething=somethingelse ... die() { echo $* exit -1 } test -n "`echo $1|grep -- -D`" || \ die $0: nothing to do - no substitutions listed! test -n "`echo $1|grep -- '-D[^=]\+=[^ ]\+'`" || \ die $0: error in command line arguments. test -n "`echo $*|grep -- ' [^-]'`" || \ die Usage: $0 '[-Dstring=replacement] [[infile] ...]' sed `echo $*|sed -e 's/-D\([^=]\+\)=\([^ ]*\)/-e s=\1=\2=g/g'` exit 0 openssh-10.0p1/PaxHeaders.10889/groupaccess.c100644 001750 001750 0000000003614775415623 0015636xustar0030 atime=1744182234.567211683 openssh-10.0p1/groupaccess.c010064400017500001750000000070101477541562300142170ustar00djmdjm/* $OpenBSD: groupaccess.c,v 1.18 2024/11/04 21:59:15 jca Exp $ */ /* * Copyright (c) 2001 Kevin Steves. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include "xmalloc.h" #include "groupaccess.h" #include "match.h" #include "log.h" static int ngroups; static char **groups_byname; /* * Initialize group access list for user with primary (base) and * supplementary groups. Return the number of groups in the list. */ int ga_init(const char *user, gid_t base) { gid_t *groups_bygid; int i, j, retry = 0; struct group *gr; if (ngroups > 0) ga_free(); ngroups = NGROUPS_MAX; #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX)); #endif groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid)); while (getgrouplist(user, base, groups_bygid, &ngroups) == -1) { if (retry++ > 0) fatal("getgrouplist: groups list too small"); groups_bygid = xreallocarray(groups_bygid, ngroups, sizeof(*groups_bygid)); } groups_byname = xcalloc(ngroups, sizeof(*groups_byname)); 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); } /* * Return 1 if one of user's groups is contained in groups. * Return 0 otherwise. Use match_pattern() for string comparison. */ int ga_match(char * const *groups, int n) { int i, j; for (i = 0; i < ngroups; i++) for (j = 0; j < n; j++) if (match_pattern(groups_byname[i], groups[j])) return 1; return 0; } /* * Return 1 if one of user's groups matches group_pattern list. * Return 0 on negated or no match. */ int ga_match_pattern_list(const char *group_pattern) { int i, found = 0; for (i = 0; i < ngroups; i++) { switch (match_usergroup_pattern_list(groups_byname[i], group_pattern)) { case -1: return 0; /* Negated match wins */ case 0: continue; case 1: found = 1; } } return found; } /* * Free memory allocated for group access list. */ void ga_free(void) { int i; if (ngroups > 0) { for (i = 0; i < ngroups; i++) free(groups_byname[i]); ngroups = 0; free(groups_byname); groups_byname = NULL; } } openssh-10.0p1/PaxHeaders.10889/groupaccess.h100644 001750 001750 0000000003514775415623 0015642xustar0029 atime=1744182234.56818801 openssh-10.0p1/groupaccess.h010064400017500001750000000030421477541562300142250ustar00djmdjm/* $OpenBSD: groupaccess.h,v 1.8 2008/07/04 03:44:59 djm Exp $ */ /* * Copyright (c) 2001 Kevin Steves. 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 GROUPACCESS_H #define GROUPACCESS_H int ga_init(const char *, gid_t); int ga_match(char * const *, int); int ga_match_pattern_list(const char *); void ga_free(void); #endif openssh-10.0p1/PaxHeaders.10889/gss-genr.c100644 001750 001750 0000000003514775415623 0015044xustar0029 atime=1744182234.56818801 openssh-10.0p1/gss-genr.c010064400017500001750000000175771477541562300134510ustar00djmdjm/* $OpenBSD: gss-genr.c,v 1.29 2024/02/01 02:37:33 djm Exp $ */ /* * Copyright (c) 2001-2007 Simon Wilkinson. 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 GSSAPI #include #include #include #include #include #include #include #include "xmalloc.h" #include "ssherr.h" #include "sshbuf.h" #include "log.h" #include "ssh2.h" #include "ssh-gss.h" /* 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) { return (ctx != NULL && ctx->oid != GSS_C_NO_OID && ctx->oid->length == len && memcmp(ctx->oid->elements, data, len) == 0); } /* Set the contexts OID from a data stream */ void ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len) { if (ctx->oid != GSS_C_NO_OID) { free(ctx->oid->elements); free(ctx->oid); } ctx->oid = xcalloc(1, sizeof(gss_OID_desc)); ctx->oid->length = len; ctx->oid->elements = xmalloc(len); memcpy(ctx->oid->elements, data, len); } /* Set the contexts OID */ void ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid) { ssh_gssapi_set_oid_data(ctx, oid->elements, oid->length); } /* All this effort to report an error ... */ void ssh_gssapi_error(Gssctxt *ctxt) { char *s; s = ssh_gssapi_last_error(ctxt, NULL, NULL); debug("%s", s); free(s); } char * ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, OM_uint32 *minor_status) { OM_uint32 lmin; gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; OM_uint32 ctx; struct sshbuf *b; char *ret; int r; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (major_status != NULL) *major_status = ctxt->major; if (minor_status != NULL) *minor_status = ctxt->minor; ctx = 0; /* The GSSAPI error */ do { gss_display_status(&lmin, ctxt->major, GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg); if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) fatal_fr(r, "assemble GSS_CODE"); gss_release_buffer(&lmin, &msg); } while (ctx != 0); /* The mechanism specific error */ do { gss_display_status(&lmin, ctxt->minor, GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg); if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) fatal_fr(r, "assemble MECH_CODE"); gss_release_buffer(&lmin, &msg); } while (ctx != 0); if ((r = sshbuf_put_u8(b, '\n')) != 0) fatal_fr(r, "assemble newline"); ret = xstrdup((const char *)sshbuf_ptr(b)); sshbuf_free(b); return (ret); } /* * Initialise our GSSAPI context. We use this opaque structure to contain all * of the data which both the client and server need to persist across * {accept,init}_sec_context calls, so that when we do it from the userauth * stuff life is a little easier */ void ssh_gssapi_build_ctx(Gssctxt **ctx) { *ctx = xcalloc(1, sizeof (Gssctxt)); (*ctx)->context = GSS_C_NO_CONTEXT; (*ctx)->name = GSS_C_NO_NAME; (*ctx)->oid = GSS_C_NO_OID; (*ctx)->creds = GSS_C_NO_CREDENTIAL; (*ctx)->client = GSS_C_NO_NAME; (*ctx)->client_creds = GSS_C_NO_CREDENTIAL; } /* Delete our context, providing it has been built correctly */ void ssh_gssapi_delete_ctx(Gssctxt **ctx) { OM_uint32 ms; if ((*ctx) == NULL) return; if ((*ctx)->context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER); if ((*ctx)->name != GSS_C_NO_NAME) gss_release_name(&ms, &(*ctx)->name); if ((*ctx)->oid != GSS_C_NO_OID) { free((*ctx)->oid->elements); free((*ctx)->oid); (*ctx)->oid = GSS_C_NO_OID; } if ((*ctx)->creds != GSS_C_NO_CREDENTIAL) gss_release_cred(&ms, &(*ctx)->creds); if ((*ctx)->client != GSS_C_NO_NAME) gss_release_name(&ms, &(*ctx)->client); if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) gss_release_cred(&ms, &(*ctx)->client_creds); free(*ctx); *ctx = NULL; } /* * Wrapper to init_sec_context * Requires that the context contains: * oid * server name (from ssh_gssapi_import_name) */ OM_uint32 ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, gss_buffer_desc* send_tok, OM_uint32 *flags) { int deleg_flag = 0; if (deleg_creds) { deleg_flag = GSS_C_DELEG_FLAG; debug("Delegating credentials"); } ctx->major = gss_init_sec_context(&ctx->minor, GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); if (GSS_ERROR(ctx->major)) ssh_gssapi_error(ctx); return (ctx->major); } /* Create a service name for the given host */ OM_uint32 ssh_gssapi_import_name(Gssctxt *ctx, const char *host) { gss_buffer_desc gssbuf; char *val; xasprintf(&val, "host@%s", host); gssbuf.value = val; gssbuf.length = strlen(gssbuf.value); if ((ctx->major = gss_import_name(&ctx->minor, &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) ssh_gssapi_error(ctx); free(gssbuf.value); return (ctx->major); } OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); return (ctx->major); } void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context, const struct sshbuf *session_id) { int r; sshbuf_reset(b); if ((r = sshbuf_put_stringb(b, session_id)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, user)) != 0 || (r = sshbuf_put_cstring(b, service)) != 0 || (r = sshbuf_put_cstring(b, context)) != 0) fatal_fr(r, "assemble buildmic"); } int ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) { gss_buffer_desc token = GSS_C_EMPTY_BUFFER; OM_uint32 major, minor; gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && (memcmp(oid->elements, spnego_oid.elements, oid->length) == 0)) return 0; /* false */ ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); gss_release_buffer(&minor, &token); if ((*ctx)->context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&minor, &(*ctx)->context, GSS_C_NO_BUFFER); } if (GSS_ERROR(major)) ssh_gssapi_delete_ctx(ctx); return (!GSS_ERROR(major)); } #endif /* GSSAPI */ openssh-10.0p1/PaxHeaders.10889/gss-serv-krb5.c100644 001750 001750 0000000003514775415623 0015731xustar0029 atime=1744182234.56818801 openssh-10.0p1/gss-serv-krb5.c010064400017500001750000000132001477541562300143110ustar00djmdjm/* $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. * * 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 GSSAPI #ifdef KRB5 #include #include #include #include "xmalloc.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "ssh-gss.h" extern ServerOptions options; #ifdef HEIMDAL # include #endif #ifdef HAVE_GSSAPI_KRB5_H # include #elif HAVE_GSSAPI_GSSAPI_KRB5_H # include #endif static krb5_context krb_context = NULL; /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ static int ssh_gssapi_krb5_init(void) { krb5_error_code problem; if (krb_context != NULL) return 1; problem = krb5_init_context(&krb_context); if (problem) { logit("Cannot initialize krb5 context"); return 0; } return 1; } /* Check if this user is OK to login. This only works with krb5 - other * GSSAPI mechanisms will need their own. * Returns true if the user is OK to log in, otherwise returns 0 */ static int ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) { krb5_principal princ; int retval; const char *errmsg; if (ssh_gssapi_krb5_init() == 0) return 0; if ((retval = krb5_parse_name(krb_context, client->exportedname.value, &princ))) { errmsg = krb5_get_error_message(krb_context, retval); logit("krb5_parse_name(): %.100s", errmsg); krb5_free_error_message(krb_context, errmsg); return 0; } if (krb5_kuserok(krb_context, princ, name)) { retval = 1; logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", name, (char *)client->displayname.value); } else retval = 0; krb5_free_principal(krb_context, princ); return retval; } /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ static void ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) { krb5_ccache ccache; krb5_error_code problem; krb5_principal princ; OM_uint32 maj_status, min_status; int len; const char *errmsg; if (client->creds == NULL) { debug("No credentials stored"); return; } if (ssh_gssapi_krb5_init() == 0) return; #ifdef HEIMDAL # ifdef HAVE_KRB5_CC_NEW_UNIQUE if ((problem = krb5_cc_new_unique(krb_context, krb5_fcc_ops.prefix, NULL, &ccache)) != 0) { errmsg = krb5_get_error_message(krb_context, problem); logit("krb5_cc_new_unique(): %.100s", errmsg); # else if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) { logit("krb5_cc_gen_new(): %.100s", krb5_get_err_text(krb_context, problem)); # endif krb5_free_error_message(krb_context, errmsg); return; } #else if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) { errmsg = krb5_get_error_message(krb_context, problem); logit("ssh_krb5_cc_gen(): %.100s", errmsg); krb5_free_error_message(krb_context, errmsg); return; } #endif /* #ifdef HEIMDAL */ if ((problem = krb5_parse_name(krb_context, client->exportedname.value, &princ))) { errmsg = krb5_get_error_message(krb_context, problem); logit("krb5_parse_name(): %.100s", errmsg); krb5_free_error_message(krb_context, errmsg); return; } if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { errmsg = krb5_get_error_message(krb_context, problem); logit("krb5_cc_initialize(): %.100s", errmsg); krb5_free_error_message(krb_context, errmsg); krb5_free_principal(krb_context, princ); krb5_cc_destroy(krb_context, ccache); return; } krb5_free_principal(krb_context, princ); if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ccache))) { logit("gss_krb5_copy_ccache() failed"); krb5_cc_destroy(krb_context, ccache); return; } client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); client->store.envvar = "KRB5CCNAME"; len = strlen(client->store.filename) + 6; client->store.envval = xmalloc(len); snprintf(client->store.envval, len, "FILE:%s", client->store.filename); #ifdef USE_PAM if (options.use_pam) do_pam_putenv(client->store.envvar, client->store.envval); #endif krb5_cc_close(krb_context, ccache); return; } ssh_gssapi_mech gssapi_kerberos_mech = { "toWM5Slw5Ew8Mqkay+al2g==", "Kerberos", {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, NULL, &ssh_gssapi_krb5_userok, NULL, &ssh_gssapi_krb5_storecreds }; #endif /* KRB5 */ #endif /* GSSAPI */ openssh-10.0p1/PaxHeaders.10889/gss-serv.c100644 001750 001750 0000000003514775415623 0015070xustar0029 atime=1744182234.56818801 openssh-10.0p1/gss-serv.c010064400017500001750000000245361477541562300134660ustar00djmdjm/* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. 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 GSSAPI #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.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}}; ssh_gssapi_mech gssapi_null_mech = { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; #endif ssh_gssapi_mech* supported_mechs[]= { #ifdef KRB5 &gssapi_kerberos_mech, #endif &gssapi_null_mech, }; /* * ssh_gssapi_supported_oids() can cause sandbox violations, so prepare the * list of supported mechanisms before privsep is set up. */ static gss_OID_set supported_oids; void ssh_gssapi_prepare_supported_oids(void) { ssh_gssapi_supported_oids(&supported_oids); } OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *ms, gss_OID member, int *present) { if (supported_oids == NULL) ssh_gssapi_prepare_supported_oids(); return gss_test_oid_set_member(ms, member, supported_oids, present); } /* * Acquire credentials for a server running on the current host. * Requires that the context structure contains a valid OID */ /* Returns a GSSAPI error code */ /* Privileged (called from ssh_gssapi_server_ctx) */ static OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx) { OM_uint32 status; char lname[NI_MAXHOST]; gss_OID_set 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, HOST_NAME_MAX)) { 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); gss_release_oid_set(&status, &oidset); return (ctx->major); } else { ctx->name = GSS_C_NO_NAME; ctx->creds = GSS_C_NO_CREDENTIAL; } return GSS_S_COMPLETE; } /* Privileged */ OM_uint32 ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) { if (*ctx) ssh_gssapi_delete_ctx(ctx); ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); return (ssh_gssapi_acquire_cred(*ctx)); } /* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) { int i = 0; OM_uint32 min_status; int present; gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); gss_indicate_mechs(&min_status, &supported); while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, &supported_mechs[i]->oid, supported, &present))) present = 0; if (present) gss_add_oid_set_member(&min_status, &supported_mechs[i]->oid, oidset); i++; } gss_release_oid_set(&min_status, &supported); } /* Wrapper around accept_sec_context * Requires that the context contains: * oid * credentials (from ssh_gssapi_acquire_cred) */ /* Privileged */ OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *recv_tok, gss_buffer_desc *send_tok, OM_uint32 *flags) { OM_uint32 status; gss_OID mech; ctx->major = gss_accept_sec_context(&ctx->minor, &ctx->context, ctx->creds, recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &ctx->client, &mech, send_tok, flags, NULL, &ctx->client_creds); if (GSS_ERROR(ctx->major)) ssh_gssapi_error(ctx); if (ctx->client_creds) debug("Received some client credentials"); else debug("Got no client credentials"); status = ctx->major; /* Now, if we're complete and we have the right flags, then * we flag the user as also having been authenticated */ if (((flags == NULL) || ((*flags & GSS_C_MUTUAL_FLAG) && (*flags & GSS_C_INTEG_FLAG))) && (ctx->major == GSS_S_COMPLETE)) { if (ssh_gssapi_getclient(ctx, &gssapi_client)) fatal("Couldn't convert client name"); } return (status); } /* * This parses an exported name, extracting the mechanism specific portion * to use for ACL checking. It verifies that the name belongs the mechanism * originally selected. */ static OM_uint32 ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name) { u_char *tok; OM_uint32 offset; OM_uint32 oidl; tok = ename->value; /* * Check that ename is long enough for all of the fixed length * header, and that the initial ID bytes are correct */ if (ename->length < 6 || memcmp(tok, "\x04\x01", 2) != 0) return GSS_S_FAILURE; /* * Extract the OID, and check it. Here GSSAPI breaks with tradition * and does use the OID type and length bytes. To confuse things * there are two lengths - the first including these, and the * second without. */ oidl = get_u16(tok+2); /* length including next two bytes */ oidl = oidl-2; /* turn it into the _real_ length of the variable OID */ /* * Check the BER encoding for correct type and length, that the * string is long enough and that the OID matches that in our context */ if (tok[4] != 0x06 || tok[5] != oidl || ename->length < oidl+6 || !ssh_gssapi_check_oid(ctx, tok+6, oidl)) return GSS_S_FAILURE; offset = oidl+6; if (ename->length < offset+4) return GSS_S_FAILURE; name->length = get_u32(tok+offset); offset += 4; if (UINT_MAX - offset < name->length) return GSS_S_FAILURE; if (ename->length < offset+name->length) return GSS_S_FAILURE; name->value = xmalloc(name->length+1); memcpy(name->value, tok+offset, name->length); ((char *)name->value)[name->length] = 0; return GSS_S_COMPLETE; } /* Extract the client details from a given context. This can only reliably * be called once for a context */ /* Privileged (called from accept_secure_ctx) */ OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) { int i = 0; gss_buffer_desc ename; client->mech = NULL; while (supported_mechs[i]->name != NULL) { if (supported_mechs[i]->oid.length == ctx->oid->length && (memcmp(supported_mechs[i]->oid.elements, ctx->oid->elements, ctx->oid->length) == 0)) client->mech = supported_mechs[i]; i++; } if (client->mech == NULL) return GSS_S_FAILURE; if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); return (ctx->major); } if ((ctx->major = gss_export_name(&ctx->minor, ctx->client, &ename))) { ssh_gssapi_error(ctx); return (ctx->major); } if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename, &client->exportedname))) { return (ctx->major); } /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; return (ctx->major); } /* As user - called on fatal/exit */ void ssh_gssapi_cleanup_creds(void) { if (gssapi_client.store.filename != NULL) { /* Unlink probably isn't sufficient */ debug("removing gssapi cred file\"%s\"", gssapi_client.store.filename); unlink(gssapi_client.store.filename); } } /* As user */ void ssh_gssapi_storecreds(void) { if (gssapi_client.mech && gssapi_client.mech->storecreds) { (*gssapi_client.mech->storecreds)(&gssapi_client); } else debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); } /* This allows GSSAPI methods to do things to the child's environment based * on the passed authentication process and credentials. */ /* As user */ void ssh_gssapi_do_child(char ***envp, u_int *envsizep) { if (gssapi_client.store.envvar != NULL && gssapi_client.store.envval != NULL) { debug("Setting %s to %s", gssapi_client.store.envvar, gssapi_client.store.envval); child_set_env(envp, envsizep, gssapi_client.store.envvar, gssapi_client.store.envval); } } /* Privileged */ int ssh_gssapi_userok(char *user) { OM_uint32 lmin; if (gssapi_client.exportedname.length == 0 || gssapi_client.exportedname.value == NULL) { debug("No suitable client data"); return 0; } if (gssapi_client.mech && gssapi_client.mech->userok) if ((*gssapi_client.mech->userok)(&gssapi_client, user)) return 1; else { /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); gss_release_cred(&lmin, &gssapi_client.creds); explicit_bzero(&gssapi_client, sizeof(ssh_gssapi_client)); return 0; } else debug("ssh_gssapi_userok: Unknown GSSAPI mechanism"); return (0); } /* Privileged */ OM_uint32 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) { ctx->major = gss_verify_mic(&ctx->minor, ctx->context, gssbuf, gssmic, NULL); 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 openssh-10.0p1/PaxHeaders.10889/hash.c100644 001750 001750 0000000003514775415623 0014242xustar0029 atime=1744182234.56818801 openssh-10.0p1/hash.c010064400017500001750000000014151477541562300126270ustar00djmdjm/* $OpenBSD: hash.c,v 1.6 2019/11/29 00:11:21 djm Exp $ */ /* * Public domain. Author: Christian Weisgerber * API compatible reimplementation of function from nacl */ #include "includes.h" #include "crypto_api.h" #include #ifdef WITH_OPENSSL #include int crypto_hash_sha512(unsigned char *out, const unsigned char *in, unsigned long long inlen) { if (!EVP_Digest(in, inlen, out, NULL, EVP_sha512(), NULL)) return -1; return 0; } #else # ifdef HAVE_SHA2_H # include # endif int crypto_hash_sha512(unsigned char *out, const unsigned char *in, unsigned long long inlen) { SHA2_CTX ctx; SHA512Init(&ctx); SHA512Update(&ctx, in, inlen); SHA512Final(out, &ctx); return 0; } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/hmac.c100644 001750 001750 0000000003514775415623 0014227xustar0029 atime=1744182234.56818801 openssh-10.0p1/hmac.c010064400017500001750000000121171477541562300126150ustar00djmdjm/* $OpenBSD: hmac.c,v 1.14 2020/02/26 13:40:09 jsg Exp $ */ /* * Copyright (c) 2014 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. */ #include "includes.h" #include #include #include #include "sshbuf.h" #include "digest.h" #include "hmac.h" struct ssh_hmac_ctx { int alg; struct ssh_digest_ctx *ictx; struct ssh_digest_ctx *octx; struct ssh_digest_ctx *digest; u_char *buf; size_t buf_len; }; size_t ssh_hmac_bytes(int alg) { return ssh_digest_bytes(alg); } struct ssh_hmac_ctx * ssh_hmac_start(int alg) { struct ssh_hmac_ctx *ret; if ((ret = calloc(1, sizeof(*ret))) == NULL) return NULL; ret->alg = alg; if ((ret->ictx = ssh_digest_start(alg)) == NULL || (ret->octx = ssh_digest_start(alg)) == NULL || (ret->digest = ssh_digest_start(alg)) == NULL) goto fail; ret->buf_len = ssh_digest_blocksize(ret->ictx); if ((ret->buf = calloc(1, ret->buf_len)) == NULL) goto fail; return ret; fail: ssh_hmac_free(ret); return NULL; } int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen) { size_t i; /* reset ictx and octx if no is key given */ if (key != NULL) { /* truncate long keys */ if (klen <= ctx->buf_len) memcpy(ctx->buf, key, klen); else if (ssh_digest_memory(ctx->alg, key, klen, ctx->buf, ctx->buf_len) < 0) return -1; for (i = 0; i < ctx->buf_len; i++) ctx->buf[i] ^= 0x36; if (ssh_digest_update(ctx->ictx, ctx->buf, ctx->buf_len) < 0) return -1; for (i = 0; i < ctx->buf_len; i++) ctx->buf[i] ^= 0x36 ^ 0x5c; if (ssh_digest_update(ctx->octx, ctx->buf, ctx->buf_len) < 0) return -1; explicit_bzero(ctx->buf, ctx->buf_len); } /* start with ictx */ if (ssh_digest_copy_state(ctx->ictx, ctx->digest) < 0) return -1; return 0; } int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen) { return ssh_digest_update(ctx->digest, m, mlen); } int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b) { return ssh_digest_update_buffer(ctx->digest, b); } int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen) { size_t len; len = ssh_digest_bytes(ctx->alg); if (dlen < len || ssh_digest_final(ctx->digest, ctx->buf, len)) return -1; /* switch to octx */ if (ssh_digest_copy_state(ctx->octx, ctx->digest) < 0 || ssh_digest_update(ctx->digest, ctx->buf, len) < 0 || ssh_digest_final(ctx->digest, d, dlen) < 0) return -1; return 0; } void ssh_hmac_free(struct ssh_hmac_ctx *ctx) { if (ctx != NULL) { ssh_digest_free(ctx->ictx); ssh_digest_free(ctx->octx); ssh_digest_free(ctx->digest); if (ctx->buf) { explicit_bzero(ctx->buf, ctx->buf_len); free(ctx->buf); } freezero(ctx, sizeof(*ctx)); } } #ifdef TEST /* cc -DTEST hmac.c digest.c buffer.c cleanup.c fatal.c log.c xmalloc.c -lcrypto */ static void hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen) { struct ssh_hmac_ctx *ctx; size_t i; u_char digest[16]; if ((ctx = ssh_hmac_start(SSH_DIGEST_MD5)) == NULL) printf("ssh_hmac_start failed"); if (ssh_hmac_init(ctx, key, klen) < 0 || ssh_hmac_update(ctx, m, mlen) < 0 || ssh_hmac_final(ctx, digest, sizeof(digest)) < 0) printf("ssh_hmac_xxx failed"); ssh_hmac_free(ctx); if (memcmp(e, digest, elen)) { for (i = 0; i < elen; i++) printf("[%zu] %2.2x %2.2x\n", i, e[i], digest[i]); printf("mismatch\n"); } else printf("ok\n"); } int main(int argc, char **argv) { /* try test vectors from RFC 2104 */ u_char key1[16] = { 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb }; u_char *data1 = "Hi There"; u_char dig1[16] = { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d }; u_char *key2 = "Jefe"; u_char *data2 = "what do ya want for nothing?"; u_char dig2[16] = { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }; u_char key3[16]; u_char data3[50]; u_char dig3[16] = { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }; memset(key3, 0xaa, sizeof(key3)); memset(data3, 0xdd, sizeof(data3)); hmac_test(key1, sizeof(key1), data1, strlen(data1), dig1, sizeof(dig1)); hmac_test(key2, strlen(key2), data2, strlen(data2), dig2, sizeof(dig2)); hmac_test(key3, sizeof(key3), data3, sizeof(data3), dig3, sizeof(dig3)); return 0; } #endif openssh-10.0p1/PaxHeaders.10889/hmac.h100644 001750 001750 0000000003514775415623 0014234xustar0029 atime=1744182234.56818801 openssh-10.0p1/hmac.h010064400017500001750000000031761477541562300126270ustar00djmdjm/* $OpenBSD: hmac.h,v 1.9 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2014 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. */ #ifndef _HMAC_H #define _HMAC_H /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ size_t ssh_hmac_bytes(int alg); struct sshbuf; struct ssh_hmac_ctx; struct ssh_hmac_ctx *ssh_hmac_start(int alg); /* Sets the state of the HMAC or resets the state if key == NULL */ int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen) __attribute__((__bounded__(__buffer__, 2, 3))); int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen) __attribute__((__bounded__(__buffer__, 2, 3))); int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b); int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 2, 3))); void ssh_hmac_free(struct ssh_hmac_ctx *ctx); #endif /* _HMAC_H */ openssh-10.0p1/PaxHeaders.10889/hostfile.c100644 001750 001750 0000000003614775415623 0015135xustar0030 atime=1744182234.569164907 openssh-10.0p1/hostfile.c010064400017500001750000000613261477541562300135300ustar00djmdjm/* $OpenBSD: hostfile.c,v 1.95 2023/02/21 06:48:18 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for manipulating the known hosts files. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * 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. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "match.h" #include "sshkey.h" #include "hostfile.h" #include "log.h" #include "misc.h" #include "pathnames.h" #include "ssherr.h" #include "digest.h" #include "hmac.h" #include "sshbuf.h" /* XXX hmac is too easy to dictionary attack; use bcrypt? */ static int extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len) { char *p, *b64salt; u_int b64len; int ret; if (l < sizeof(HASH_MAGIC) - 1) { debug2("extract_salt: string too short"); return (-1); } if (strncmp(s, HASH_MAGIC, sizeof(HASH_MAGIC) - 1) != 0) { debug2("extract_salt: invalid magic identifier"); return (-1); } s += sizeof(HASH_MAGIC) - 1; l -= sizeof(HASH_MAGIC) - 1; if ((p = memchr(s, HASH_DELIM, l)) == NULL) { debug2("extract_salt: missing salt termination character"); return (-1); } b64len = p - s; /* Sanity check */ if (b64len == 0 || b64len > 1024) { debug2("extract_salt: bad encoded salt length %u", b64len); return (-1); } b64salt = xmalloc(1 + b64len); memcpy(b64salt, s, b64len); b64salt[b64len] = '\0'; ret = __b64_pton(b64salt, salt, salt_len); free(b64salt); if (ret == -1) { debug2("extract_salt: salt decode error"); return (-1); } if (ret != (int)ssh_hmac_bytes(SSH_DIGEST_SHA1)) { debug2("extract_salt: expected salt len %zd, got %d", ssh_hmac_bytes(SSH_DIGEST_SHA1), ret); return (-1); } return (0); } char * host_hash(const char *host, const char *name_from_hostfile, u_int src_len) { struct ssh_hmac_ctx *ctx; u_char salt[256], result[256]; char uu_salt[512], uu_result[512]; char *encoded = NULL; u_int len; len = ssh_digest_bytes(SSH_DIGEST_SHA1); if (name_from_hostfile == NULL) { /* Create new salt */ arc4random_buf(salt, len); } else { /* Extract salt from known host entry */ if (extract_salt(name_from_hostfile, src_len, salt, sizeof(salt)) == -1) return (NULL); } if ((ctx = ssh_hmac_start(SSH_DIGEST_SHA1)) == NULL || ssh_hmac_init(ctx, salt, len) < 0 || ssh_hmac_update(ctx, host, strlen(host)) < 0 || ssh_hmac_final(ctx, result, sizeof(result))) fatal_f("ssh_hmac failed"); ssh_hmac_free(ctx); if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 || __b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1) fatal_f("__b64_ntop failed"); xasprintf(&encoded, "%s%s%c%s", HASH_MAGIC, uu_salt, HASH_DELIM, uu_result); return (encoded); } /* * Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the * pointer over the key. Skips any whitespace at the beginning and at end. */ int hostfile_read_key(char **cpp, u_int *bitsp, struct sshkey *ret) { char *cp; /* Skip leading whitespace. */ for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) ; if (sshkey_read(ret, &cp) != 0) return 0; /* Skip trailing whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; /* Return results. */ *cpp = cp; if (bitsp != NULL) *bitsp = sshkey_size(ret); return 1; } static HostkeyMarker check_markers(char **cpp) { char marker[32], *sp, *cp = *cpp; int ret = MRK_NONE; while (*cp == '@') { /* Only one marker is allowed */ if (ret != MRK_NONE) return MRK_ERROR; /* Markers are terminated by whitespace */ if ((sp = strchr(cp, ' ')) == NULL && (sp = strchr(cp, '\t')) == NULL) return MRK_ERROR; /* Extract marker for comparison */ if (sp <= cp + 1 || sp >= cp + sizeof(marker)) return MRK_ERROR; memcpy(marker, cp, sp - cp); marker[sp - cp] = '\0'; if (strcmp(marker, CA_MARKER) == 0) ret = MRK_CA; else if (strcmp(marker, REVOKE_MARKER) == 0) ret = MRK_REVOKE; else return MRK_ERROR; /* Skip past marker and any whitespace that follows it */ cp = sp; for (; *cp == ' ' || *cp == '\t'; cp++) ; } *cpp = cp; return ret; } struct hostkeys * init_hostkeys(void) { struct hostkeys *ret = xcalloc(1, sizeof(*ret)); ret->entries = NULL; return ret; } struct load_callback_ctx { const char *host; u_long num_loaded; struct hostkeys *hostkeys; }; static int record_hostkey(struct hostkey_foreach_line *l, void *_ctx) { struct load_callback_ctx *ctx = (struct load_callback_ctx *)_ctx; struct hostkeys *hostkeys = ctx->hostkeys; struct hostkey_entry *tmp; if (l->status == HKF_STATUS_INVALID) { /* XXX make this verbose() in the future */ debug("%s:%ld: parse error in hostkeys file", l->path, l->linenum); return 0; } debug3_f("found %skey type %s in file %s:%lu", l->marker == MRK_NONE ? "" : (l->marker == MRK_CA ? "ca " : "revoked "), sshkey_type(l->key), l->path, l->linenum); if ((tmp = recallocarray(hostkeys->entries, hostkeys->num_entries, hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL) return SSH_ERR_ALLOC_FAIL; hostkeys->entries = tmp; hostkeys->entries[hostkeys->num_entries].host = xstrdup(ctx->host); hostkeys->entries[hostkeys->num_entries].file = xstrdup(l->path); hostkeys->entries[hostkeys->num_entries].line = l->linenum; hostkeys->entries[hostkeys->num_entries].key = l->key; l->key = NULL; /* steal it */ hostkeys->entries[hostkeys->num_entries].marker = l->marker; hostkeys->entries[hostkeys->num_entries].note = l->note; hostkeys->num_entries++; ctx->num_loaded++; return 0; } void load_hostkeys_file(struct hostkeys *hostkeys, const char *host, const char *path, FILE *f, u_int note) { int r; struct load_callback_ctx ctx; ctx.host = host; ctx.num_loaded = 0; ctx.hostkeys = hostkeys; if ((r = hostkeys_foreach_file(path, f, record_hostkey, &ctx, host, NULL, HKF_WANT_MATCH|HKF_WANT_PARSE_KEY, note)) != 0) { if (r != SSH_ERR_SYSTEM_ERROR && errno != ENOENT) debug_fr(r, "hostkeys_foreach failed for %s", path); } if (ctx.num_loaded != 0) debug3_f("loaded %lu keys from %s", ctx.num_loaded, host); } void load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path, u_int note) { FILE *f; if ((f = fopen(path, "r")) == NULL) { debug_f("fopen %s: %s", path, strerror(errno)); return; } load_hostkeys_file(hostkeys, host, path, f, note); fclose(f); } void free_hostkeys(struct hostkeys *hostkeys) { u_int i; for (i = 0; i < hostkeys->num_entries; i++) { free(hostkeys->entries[i].host); free(hostkeys->entries[i].file); sshkey_free(hostkeys->entries[i].key); explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries)); } free(hostkeys->entries); freezero(hostkeys, sizeof(*hostkeys)); } static int check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k) { int is_cert = sshkey_is_cert(k); u_int i; for (i = 0; i < hostkeys->num_entries; i++) { if (hostkeys->entries[i].marker != MRK_REVOKE) continue; if (sshkey_equal_public(k, hostkeys->entries[i].key)) return -1; if (is_cert && k != NULL && sshkey_equal_public(k->cert->signature_key, hostkeys->entries[i].key)) return -1; } return 0; } /* * Match keys against a specified key, or look one up by key type. * * If looking for a keytype (key == NULL) and one is found then return * HOST_FOUND, otherwise HOST_NEW. * * If looking for a key (key != NULL): * 1. If the key is a cert and a matching CA is found, return HOST_OK * 2. If the key is not a cert and a matching key is found, return HOST_OK * 3. If no key matches but a key with a different type is found, then * return HOST_CHANGED * 4. If no matching keys are found, then return HOST_NEW. * * Finally, check any found key is not revoked. */ static HostStatus check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, struct sshkey *k, int keytype, int nid, const struct hostkey_entry **found) { u_int i; HostStatus end_return = HOST_NEW; int want_cert = sshkey_is_cert(k); HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE; if (found != NULL) *found = NULL; for (i = 0; i < hostkeys->num_entries; i++) { if (hostkeys->entries[i].marker != want_marker) continue; if (k == NULL) { if (hostkeys->entries[i].key->type != keytype) continue; if (nid != -1 && sshkey_type_plain(keytype) == KEY_ECDSA && hostkeys->entries[i].key->ecdsa_nid != nid) continue; end_return = HOST_FOUND; if (found != NULL) *found = hostkeys->entries + i; k = hostkeys->entries[i].key; break; } if (want_cert) { if (sshkey_equal_public(k->cert->signature_key, hostkeys->entries[i].key)) { /* A matching CA exists */ end_return = HOST_OK; if (found != NULL) *found = hostkeys->entries + i; break; } } else { if (sshkey_equal(k, hostkeys->entries[i].key)) { end_return = HOST_OK; if (found != NULL) *found = hostkeys->entries + i; break; } /* A non-matching key exists */ end_return = HOST_CHANGED; if (found != NULL) *found = hostkeys->entries + i; } } if (check_key_not_revoked(hostkeys, k) != 0) { end_return = HOST_REVOKED; if (found != NULL) *found = NULL; } return end_return; } HostStatus check_key_in_hostkeys(struct hostkeys *hostkeys, struct sshkey *key, const struct hostkey_entry **found) { if (key == NULL) fatal("no key to look up"); return check_hostkeys_by_key_or_type(hostkeys, key, 0, -1, found); } int lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype, int nid, const struct hostkey_entry **found) { return (check_hostkeys_by_key_or_type(hostkeys, NULL, keytype, nid, found) == HOST_FOUND); } int lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker) { u_int i; for (i = 0; i < hostkeys->num_entries; i++) { if (hostkeys->entries[i].marker == (HostkeyMarker)want_marker) return 1; } return 0; } static int write_host_entry(FILE *f, const char *host, const char *ip, const struct sshkey *key, int store_hash) { int r, success = 0; char *hashed_host = NULL, *lhost; lhost = xstrdup(host); lowercase(lhost); if (store_hash) { if ((hashed_host = host_hash(lhost, NULL, 0)) == NULL) { error_f("host_hash failed"); free(lhost); return 0; } fprintf(f, "%s ", hashed_host); } else if (ip != NULL) fprintf(f, "%s,%s ", lhost, ip); else { fprintf(f, "%s ", lhost); } free(hashed_host); free(lhost); if ((r = sshkey_write(key, f)) == 0) success = 1; else error_fr(r, "sshkey_write"); fputc('\n', f); /* If hashing is enabled, the IP address needs to go on its own line */ if (success && store_hash && ip != NULL) success = write_host_entry(f, ip, NULL, key, 1); return success; } /* * Create user ~/.ssh directory if it doesn't exist and we want to write to it. * If notify is set, a message will be emitted if the directory is created. */ void hostfile_create_user_ssh_dir(const char *filename, int notify) { char *dotsshdir = NULL, *p; size_t len; struct stat st; if ((p = strrchr(filename, '/')) == NULL) return; len = p - filename; dotsshdir = tilde_expand_filename("~/" _PATH_SSH_USER_DIR, getuid()); if (strlen(dotsshdir) > len || strncmp(filename, dotsshdir, len) != 0) goto out; /* not ~/.ssh prefixed */ if (stat(dotsshdir, &st) == 0) goto out; /* dir already exists */ else if (errno != ENOENT) error("Could not stat %s: %s", dotsshdir, strerror(errno)); else { #ifdef WITH_SELINUX ssh_selinux_setfscreatecon(dotsshdir); #endif if (mkdir(dotsshdir, 0700) == -1) error("Could not create directory '%.200s' (%s).", dotsshdir, strerror(errno)); else if (notify) logit("Created directory '%s'.", dotsshdir); #ifdef WITH_SELINUX ssh_selinux_setfscreatecon(NULL); #endif } out: free(dotsshdir); } /* * Appends an entry to the host file. Returns false if the entry could not * be appended. */ int add_host_to_hostfile(const char *filename, const char *host, const struct sshkey *key, int store_hash) { FILE *f; int success, addnl = 0; if (key == NULL) return 1; /* XXX ? */ hostfile_create_user_ssh_dir(filename, 0); f = fopen(filename, "a+"); if (!f) return 0; /* Make sure we have a terminating newline. */ if (fseek(f, -1L, SEEK_END) == 0 && fgetc(f) != '\n') addnl = 1; if (fseek(f, 0L, SEEK_END) != 0 || (addnl && fputc('\n', f) != '\n')) { error("Failed to add terminating newline to %s: %s", filename, strerror(errno)); fclose(f); return 0; } success = write_host_entry(f, host, NULL, key, store_hash); fclose(f); return success; } struct host_delete_ctx { FILE *out; int quiet; const char *host, *ip; u_int *match_keys; /* mask of HKF_MATCH_* for this key */ struct sshkey * const *keys; size_t nkeys; int modified; }; static int host_delete(struct hostkey_foreach_line *l, void *_ctx) { struct host_delete_ctx *ctx = (struct host_delete_ctx *)_ctx; int loglevel = ctx->quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; size_t i; /* Don't remove CA and revocation lines */ if (l->status == HKF_STATUS_MATCHED && l->marker == MRK_NONE) { /* * If this line contains one of the keys that we will be * adding later, then don't change it and mark the key for * skipping. */ for (i = 0; i < ctx->nkeys; i++) { if (!sshkey_equal(ctx->keys[i], l->key)) continue; ctx->match_keys[i] |= l->match; fprintf(ctx->out, "%s\n", l->line); debug3_f("%s key already at %s:%ld", sshkey_type(l->key), l->path, l->linenum); return 0; } /* * Hostname matches and has no CA/revoke marker, delete it * by *not* writing the line to ctx->out. */ do_log2(loglevel, "%s%s%s:%ld: Removed %s key for host %s", ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "", l->path, l->linenum, sshkey_type(l->key), ctx->host); ctx->modified = 1; return 0; } /* Retain non-matching hosts and invalid lines when deleting */ if (l->status == HKF_STATUS_INVALID) { do_log2(loglevel, "%s%s%s:%ld: invalid known_hosts entry", ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "", l->path, l->linenum); } fprintf(ctx->out, "%s\n", l->line); return 0; } int hostfile_replace_entries(const char *filename, const char *host, const char *ip, struct sshkey **keys, size_t nkeys, int store_hash, int quiet, int hash_alg) { int r, fd, oerrno = 0; int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; struct host_delete_ctx ctx; char *fp, *temp = NULL, *back = NULL; const char *what; mode_t omask; size_t i; u_int want; omask = umask(077); memset(&ctx, 0, sizeof(ctx)); ctx.host = host; ctx.ip = ip; ctx.quiet = quiet; if ((ctx.match_keys = calloc(nkeys, sizeof(*ctx.match_keys))) == NULL) return SSH_ERR_ALLOC_FAIL; ctx.keys = keys; ctx.nkeys = nkeys; ctx.modified = 0; /* * Prepare temporary file for in-place deletion. */ if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) == -1 || (r = asprintf(&back, "%s.old", filename)) == -1) { r = SSH_ERR_ALLOC_FAIL; goto fail; } if ((fd = mkstemp(temp)) == -1) { oerrno = errno; error_f("mkstemp: %s", strerror(oerrno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } if ((ctx.out = fdopen(fd, "w")) == NULL) { oerrno = errno; close(fd); error_f("fdopen: %s", strerror(oerrno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } /* Remove stale/mismatching entries for the specified host */ if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip, HKF_WANT_PARSE_KEY, 0)) != 0) { oerrno = errno; error_fr(r, "hostkeys_foreach"); goto fail; } /* Re-add the requested keys */ want = HKF_MATCH_HOST | (ip == NULL ? 0 : HKF_MATCH_IP); for (i = 0; i < nkeys; i++) { if (keys[i] == NULL || (want & ctx.match_keys[i]) == want) continue; if ((fp = sshkey_fingerprint(keys[i], hash_alg, SSH_FP_DEFAULT)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } /* write host/ip */ what = ""; if (ctx.match_keys[i] == 0) { what = "Adding new key"; if (!write_host_entry(ctx.out, host, ip, keys[i], store_hash)) { r = SSH_ERR_INTERNAL_ERROR; goto fail; } } else if ((want & ~ctx.match_keys[i]) == HKF_MATCH_HOST) { what = "Fixing match (hostname)"; if (!write_host_entry(ctx.out, host, NULL, keys[i], store_hash)) { r = SSH_ERR_INTERNAL_ERROR; goto fail; } } else if ((want & ~ctx.match_keys[i]) == HKF_MATCH_IP) { what = "Fixing match (address)"; if (!write_host_entry(ctx.out, ip, NULL, keys[i], store_hash)) { r = SSH_ERR_INTERNAL_ERROR; goto fail; } } do_log2(loglevel, "%s%s%s for %s%s%s to %s: %s %s", quiet ? __func__ : "", quiet ? ": " : "", what, host, ip == NULL ? "" : ",", ip == NULL ? "" : ip, filename, sshkey_ssh_name(keys[i]), fp); free(fp); ctx.modified = 1; } fclose(ctx.out); ctx.out = NULL; if (ctx.modified) { /* Backup the original file and replace it with the temporary */ if (unlink(back) == -1 && errno != ENOENT) { oerrno = errno; error_f("unlink %.100s: %s", back, strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } if (link(filename, back) == -1) { oerrno = errno; error_f("link %.100s to %.100s: %s", filename, back, strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } if (rename(temp, filename) == -1) { oerrno = errno; error_f("rename \"%s\" to \"%s\": %s", temp, filename, strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } } else { /* No changes made; just delete the temporary file */ if (unlink(temp) != 0) error_f("unlink \"%s\": %s", temp, strerror(errno)); } /* success */ r = 0; fail: if (temp != NULL && r != 0) unlink(temp); free(temp); free(back); if (ctx.out != NULL) fclose(ctx.out); free(ctx.match_keys); umask(omask); if (r == SSH_ERR_SYSTEM_ERROR) errno = oerrno; return r; } static int match_maybe_hashed(const char *host, const char *names, int *was_hashed) { int hashed = *names == HASH_DELIM, ret; char *hashed_host = NULL; size_t nlen = strlen(names); if (was_hashed != NULL) *was_hashed = hashed; if (hashed) { if ((hashed_host = host_hash(host, names, nlen)) == NULL) return -1; ret = (nlen == strlen(hashed_host) && strncmp(hashed_host, names, nlen) == 0); free(hashed_host); return ret; } return match_hostname(host, names) == 1; } int hostkeys_foreach_file(const char *path, FILE *f, hostkeys_foreach_fn *callback, void *ctx, const char *host, const char *ip, u_int options, u_int note) { 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 linesize = 0, l; memset(&lineinfo, 0, sizeof(lineinfo)); if (host == NULL && (options & HKF_WANT_MATCH) != 0) return SSH_ERR_INVALID_ARGUMENT; while (getline(&line, &linesize, f) != -1) { linenum++; line[strcspn(line, "\n")] = '\0'; free(lineinfo.line); sshkey_free(lineinfo.key); memset(&lineinfo, 0, sizeof(lineinfo)); lineinfo.path = path; lineinfo.linenum = linenum; lineinfo.line = xstrdup(line); lineinfo.marker = MRK_NONE; lineinfo.status = HKF_STATUS_OK; lineinfo.keytype = KEY_UNSPEC; lineinfo.note = note; /* Skip any leading whitespace, comments and empty lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') { if ((options & HKF_WANT_MATCH) == 0) { lineinfo.status = HKF_STATUS_COMMENT; if ((r = callback(&lineinfo, ctx)) != 0) break; } continue; } if ((lineinfo.marker = check_markers(&cp)) == MRK_ERROR) { verbose_f("invalid marker at %s:%lu", path, linenum); if ((options & HKF_WANT_MATCH) == 0) goto bad; continue; } /* Find the end of the host name portion. */ for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) ; lineinfo.hosts = cp; *cp2++ = '\0'; /* Check if the host name matches. */ if (host != NULL) { if ((s = match_maybe_hashed(host, lineinfo.hosts, &hashed)) == -1) { debug2_f("%s:%ld: bad host hash \"%.32s\"", path, linenum, lineinfo.hosts); goto bad; } if (s == 1) { lineinfo.status = HKF_STATUS_MATCHED; lineinfo.match |= HKF_MATCH_HOST | (hashed ? HKF_MATCH_HOST_HASHED : 0); } /* Try matching IP address if supplied */ if (ip != NULL) { if ((s = match_maybe_hashed(ip, lineinfo.hosts, &hashed)) == -1) { debug2_f("%s:%ld: bad ip hash " "\"%.32s\"", path, linenum, lineinfo.hosts); goto bad; } if (s == 1) { lineinfo.status = HKF_STATUS_MATCHED; lineinfo.match |= HKF_MATCH_IP | (hashed ? HKF_MATCH_IP_HASHED : 0); } } /* * Skip this line if host matching requested and * neither host nor address matched. */ if ((options & HKF_WANT_MATCH) != 0 && lineinfo.status != HKF_STATUS_MATCHED) continue; } /* Got a match. Skip host name and any following whitespace */ for (; *cp2 == ' ' || *cp2 == '\t'; cp2++) ; if (*cp2 == '\0' || *cp2 == '#') { debug2("%s:%ld: truncated before key type", path, linenum); goto bad; } lineinfo.rawkey = cp = cp2; if ((options & HKF_WANT_PARSE_KEY) != 0) { /* * Extract the key from the line. This will skip * any leading whitespace. Ignore badly formatted * lines. */ if ((lineinfo.key = sshkey_new(KEY_UNSPEC)) == NULL) { error_f("sshkey_new failed"); r = SSH_ERR_ALLOC_FAIL; break; } if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) { goto bad; } lineinfo.keytype = lineinfo.key->type; lineinfo.comment = cp; } else { /* Extract and parse key type */ l = strcspn(lineinfo.rawkey, " \t"); if (l <= 1 || l >= sizeof(ktype) || lineinfo.rawkey[l] == '\0') goto bad; memcpy(ktype, lineinfo.rawkey, l); ktype[l] = '\0'; lineinfo.keytype = sshkey_type_from_name(ktype); /* * Assume legacy RSA1 if the first component is a short * decimal number. */ if (lineinfo.keytype == KEY_UNSPEC && l < 8 && strspn(ktype, "0123456789") == l) goto bad; /* * Check that something other than whitespace follows * the key type. This won't catch all corruption, but * it does catch trivial truncation. */ cp2 += l; /* Skip past key type */ for (; *cp2 == ' ' || *cp2 == '\t'; cp2++) ; if (*cp2 == '\0' || *cp2 == '#') { debug2("%s:%ld: truncated after key type", path, linenum); lineinfo.keytype = KEY_UNSPEC; } if (lineinfo.keytype == KEY_UNSPEC) { bad: sshkey_free(lineinfo.key); lineinfo.key = NULL; lineinfo.status = HKF_STATUS_INVALID; if ((r = callback(&lineinfo, ctx)) != 0) break; continue; } } if ((r = callback(&lineinfo, ctx)) != 0) break; } sshkey_free(lineinfo.key); free(lineinfo.line); free(line); return r; } int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, const char *host, const char *ip, u_int options, u_int note) { FILE *f; int r, oerrno; if ((f = fopen(path, "r")) == NULL) return SSH_ERR_SYSTEM_ERROR; debug3_f("reading file \"%s\"", path); r = hostkeys_foreach_file(path, f, callback, ctx, host, ip, options, note); oerrno = errno; fclose(f); errno = oerrno; return r; } openssh-10.0p1/PaxHeaders.10889/hostfile.h100644 001750 001750 0000000003614775415623 0015142xustar0030 atime=1744182234.569164907 openssh-10.0p1/hostfile.h010064400017500001750000000105571477541562300135350ustar00djmdjm/* $OpenBSD: hostfile.h,v 1.29 2021/01/26 00:51:30 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef HOSTFILE_H #define HOSTFILE_H typedef enum { HOST_OK, HOST_NEW, HOST_CHANGED, HOST_REVOKED, HOST_FOUND } HostStatus; typedef enum { MRK_ERROR, MRK_NONE, MRK_REVOKE, MRK_CA } HostkeyMarker; struct hostkey_entry { char *host; char *file; u_long line; struct sshkey *key; HostkeyMarker marker; u_int note; /* caller-specific note/flag */ }; struct hostkeys { struct hostkey_entry *entries; u_int num_entries; }; struct hostkeys *init_hostkeys(void); void load_hostkeys(struct hostkeys *, const char *, const char *, u_int); void load_hostkeys_file(struct hostkeys *, const char *, const char *, FILE *, u_int note); void free_hostkeys(struct hostkeys *); HostStatus check_key_in_hostkeys(struct hostkeys *, struct sshkey *, const struct hostkey_entry **); int lookup_key_in_hostkeys_by_type(struct hostkeys *, int, int, const struct hostkey_entry **); int lookup_marker_in_hostkeys(struct hostkeys *, int); int hostfile_read_key(char **, u_int *, struct sshkey *); int add_host_to_hostfile(const char *, const char *, const struct sshkey *, int); int hostfile_replace_entries(const char *filename, const char *host, const char *ip, struct sshkey **keys, size_t nkeys, int store_hash, int quiet, int hash_alg); #define HASH_MAGIC "|1|" #define HASH_DELIM '|' #define CA_MARKER "@cert-authority" #define REVOKE_MARKER "@revoked" char *host_hash(const char *, const char *, u_int); /* * Iterate through a hostkeys file, optionally parsing keys and matching * hostnames. Allows access to the raw keyfile lines to allow * streaming edits to the file to take place. */ #define HKF_WANT_MATCH (1) /* return only matching hosts/addrs */ #define HKF_WANT_PARSE_KEY (1<<1) /* need key parsed */ #define HKF_STATUS_OK 0 /* Line parsed, didn't match host */ #define HKF_STATUS_INVALID 1 /* line had parse error */ #define HKF_STATUS_COMMENT 2 /* valid line contained no key */ #define HKF_STATUS_MATCHED 3 /* hostname or IP matched */ #define HKF_MATCH_HOST (1) /* hostname matched */ #define HKF_MATCH_IP (1<<1) /* address matched */ #define HKF_MATCH_HOST_HASHED (1<<2) /* hostname was hashed */ #define HKF_MATCH_IP_HASHED (1<<3) /* address was hashed */ /* XXX HKF_MATCH_KEY_TYPE? */ /* * The callback function receives this as an argument for each matching * hostkey line. The callback may "steal" the 'key' field by setting it to NULL. * If a parse error occurred, then "hosts" and subsequent options may be NULL. */ struct hostkey_foreach_line { const char *path; /* Path of file */ u_long linenum; /* Line number */ u_int status; /* One of HKF_STATUS_* */ u_int match; /* Zero or more of HKF_MATCH_* OR'd together */ char *line; /* Entire key line; mutable by callback */ int marker; /* CA/revocation markers; indicated by MRK_* value */ const char *hosts; /* Raw hosts text, may be hashed or list multiple */ const char *rawkey; /* Text of key and any comment following it */ int keytype; /* Type of key; KEY_UNSPEC for invalid/comment lines */ struct sshkey *key; /* Key, if parsed ok and HKF_WANT_MATCH_HOST set */ const char *comment; /* Any comment following the key */ u_int note; /* caller-specified note copied from arguments */ }; /* * Callback fires for each line (or matching line if a HKF_WANT_* option * is set). The foreach loop will terminate if the callback returns a non- * zero exit status. */ typedef int hostkeys_foreach_fn(struct hostkey_foreach_line *l, void *ctx); /* Iterate over a hostkeys file */ int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, const char *host, const char *ip, u_int options, u_int note); int hostkeys_foreach_file(const char *path, FILE *f, hostkeys_foreach_fn *callback, void *ctx, const char *host, const char *ip, u_int options, u_int note); void hostfile_create_user_ssh_dir(const char *, int); #endif openssh-10.0p1/PaxHeaders.10889/includes.h100644 001750 001750 0000000003614775415623 0015133xustar0030 atime=1744182234.569164907 openssh-10.0p1/includes.h010064400017500001750000000076241477541562300135270ustar00djmdjm/* $OpenBSD: includes.h,v 1.54 2006/07/22 20:48:23 stevesk Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * This file includes most of the needed system headers. * * 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 INCLUDES_H #define INCLUDES_H #include "config.h" #ifndef _GNU_SOURCE #define _GNU_SOURCE /* activate extra prototypes for glibc */ #endif #include #include /* For CMSG_* */ #ifdef HAVE_LIMITS_H # include /* For PATH_MAX, _POSIX_HOST_NAME_MAX */ #endif #ifdef HAVE_BSTRING_H # include #endif #ifdef HAVE_ENDIAN_H # include #endif #ifdef HAVE_TTYENT_H # include #endif #ifdef HAVE_UTIME_H # include #endif #ifdef HAVE_MAILLOCK_H # include /* For _PATH_MAILDIR */ #endif #ifdef HAVE_NEXT # include #endif #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_FCNTL_H # include /* For AT_FDCWD */ #endif /* *-*-nto-qnx needs these headers for strcasecmp and LASTLOG_FILE respectively */ #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_LOGIN_H # include #endif #ifdef HAVE_UTMP_H # include #endif #ifdef HAVE_UTMPX_H # include #endif #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_BSDTTY_H # include #endif #ifdef HAVE_STDINT_H # include #endif #include #ifdef HAVE_SYS_BITYPES_H # include /* For u_intXX_t */ #endif #ifdef HAVE_SYS_CDEFS_H # include /* For __P() */ #endif #ifdef HAVE_SYS_STAT_H # include /* For S_* constants and macros */ #endif #ifdef HAVE_SYS_SYSMACROS_H # include /* For MIN, MAX, etc */ #endif #ifdef HAVE_SYS_TIME_H # include /* for timespeccmp if present */ #endif #ifdef HAVE_SYS_MMAN_H #include /* for MAP_ANONYMOUS */ #endif #ifdef HAVE_SYS_STRTIO_H #include /* for TIOCCBRK on HP-UX */ #endif #if defined(HAVE_SYS_PTMS_H) && defined(HAVE_DEV_PTMX) # if defined(HAVE_SYS_STREAM_H) # include /* reqd for queue_t on Solaris 2.5.1 */ # endif #include /* for grantpt() and friends */ #endif #include #include /* For typedefs */ #ifdef HAVE_RPC_TYPES_H # include /* For INADDR_LOOPBACK */ #endif #ifdef USE_PAM #if defined(HAVE_SECURITY_PAM_APPL_H) # include #elif defined (HAVE_PAM_PAM_APPL_H) # include #endif #endif #ifdef HAVE_READPASSPHRASE_H # include #endif #ifdef HAVE_IA_H # include #endif #ifdef HAVE_IAF_H # include #endif #ifdef HAVE_TMPDIR_H # include #endif #if defined(HAVE_BSD_LIBUTIL_H) # include #elif defined(HAVE_LIBUTIL_H) # include #endif #if defined(KRB5) && defined(USE_AFS) # include # include #endif #if defined(HAVE_SYS_SYSLOG_H) # include #endif #include /* * On HP-UX 11.11, shadow.h and prot.h provide conflicting declarations * of getspnam when _INCLUDE__STDC__ is defined, so we unset it here. */ #ifdef GETSPNAM_CONFLICTING_DEFS # ifdef _INCLUDE__STDC__ # undef _INCLUDE__STDC__ # endif #endif #ifdef WITH_OPENSSL #include /* For OPENSSL_VERSION_NUMBER */ #endif #include "defines.h" #include "platform.h" #include "openbsd-compat/openbsd-compat.h" #include "openbsd-compat/bsd-nextstep.h" #include "entropy.h" #endif /* INCLUDES_H */ openssh-10.0p1/PaxHeaders.10889/install-sh100755 001750 001750 0000000003614775415623 0015160xustar0030 atime=1744182234.569164907 openssh-10.0p1/install-sh010075500017500001750000000357761477541562300135650ustar00djmdjm#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # 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. # # 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. # # # 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 # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # 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_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve 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. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi 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 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 if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi 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 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=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi 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. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # 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 posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/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. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # 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 oIFS=$IFS IFS=/ set -f set fnord $dstdir shift 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=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_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 && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $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` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # 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 "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$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 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: openssh-10.0p1/PaxHeaders.10889/kex-names.c100644 001750 001750 0000000003614775415623 0015210xustar0030 atime=1744182234.570140914 openssh-10.0p1/kex-names.c010064400017500001750000000205321477541562300135750ustar00djmdjm/* $OpenBSD: kex-names.c,v 1.4 2024/09/09 02:39:57 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #endif #include "kex.h" #include "log.h" #include "match.h" #include "digest.h" #include "misc.h" #include "ssherr.h" #include "xmalloc.h" struct kexalg { char *name; u_int type; int ec_nid; int hash_alg; }; static const struct kexalg kexalgs[] = { #ifdef WITH_OPENSSL { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 }, { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, #endif /* HAVE_EVP_SHA256 */ #ifdef OPENSSL_HAS_ECC { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, SSH_DIGEST_SHA384 }, # ifdef OPENSSL_HAS_NISTP521 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, SSH_DIGEST_SHA512 }, # endif /* OPENSSL_HAS_NISTP521 */ #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, #ifdef USE_SNTRUP761X25519 { KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0, SSH_DIGEST_SHA512 }, { KEX_SNTRUP761X25519_SHA512_OLD, KEX_KEM_SNTRUP761X25519_SHA512, 0, SSH_DIGEST_SHA512 }, #endif #ifdef USE_MLKEM768X25519 { KEX_MLKEM768X25519_SHA256, KEX_KEM_MLKEM768X25519_SHA256, 0, SSH_DIGEST_SHA256 }, #endif #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, 0, -1, -1}, }; char * kex_alg_list(char sep) { char *ret = NULL, *tmp; size_t nlen, rlen = 0; const struct kexalg *k; for (k = kexalgs; k->name != NULL; k++) { if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { free(ret); return NULL; } ret = tmp; memcpy(ret + rlen, k->name, nlen + 1); rlen += nlen; } return ret; } static const struct kexalg * kex_alg_by_name(const char *name) { const struct kexalg *k; for (k = kexalgs; k->name != NULL; k++) { if (strcmp(k->name, name) == 0) return k; } return NULL; } int kex_name_valid(const char *name) { return kex_alg_by_name(name) != NULL; } u_int kex_type_from_name(const char *name) { const struct kexalg *k; if ((k = kex_alg_by_name(name)) == NULL) return 0; return k->type; } int kex_hash_from_name(const char *name) { const struct kexalg *k; if ((k = kex_alg_by_name(name)) == NULL) return -1; return k->hash_alg; } int kex_nid_from_name(const char *name) { const struct kexalg *k; if ((k = kex_alg_by_name(name)) == NULL) return -1; return k->ec_nid; } /* Validate KEX method name list */ int kex_names_valid(const char *names) { char *s, *cp, *p; if (names == NULL || strcmp(names, "") == 0) return 0; if ((s = cp = strdup(names)) == NULL) return 0; for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (kex_alg_by_name(p) == NULL) { error("Unsupported KEX algorithm \"%.100s\"", p); free(s); return 0; } } debug3("kex names ok: [%s]", names); free(s); return 1; } /* returns non-zero if proposal contains any algorithm from algs */ int kex_has_any_alg(const char *proposal, const char *algs) { char *cp; if ((cp = match_list(proposal, algs, NULL)) == NULL) return 0; free(cp); return 1; } /* * Concatenate algorithm names, avoiding duplicates in the process. * Caller must free returned string. */ char * kex_names_cat(const char *a, const char *b) { char *ret = NULL, *tmp = NULL, *cp, *p; size_t len; if (a == NULL || *a == '\0') return strdup(b); if (b == NULL || *b == '\0') return strdup(a); if (strlen(b) > 1024*1024) return NULL; len = strlen(a) + strlen(b) + 2; if ((tmp = cp = strdup(b)) == NULL || (ret = calloc(1, len)) == NULL) { free(tmp); return NULL; } strlcpy(ret, a, len); for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (kex_has_any_alg(ret, p)) continue; /* Algorithm already present */ if (strlcat(ret, ",", len) >= len || strlcat(ret, p, len) >= len) { free(tmp); free(ret); return NULL; /* Shouldn't happen */ } } free(tmp); return ret; } /* * Assemble a list of algorithms from a default list and a string from a * configuration file. The user-provided string may begin with '+' to * indicate that it should be appended to the default, '-' that the * specified names should be removed, or '^' that they should be placed * at the head. */ int kex_assemble_names(char **listp, const char *def, const char *all) { char *cp, *tmp, *patterns; char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (listp == NULL || def == NULL || all == NULL) return SSH_ERR_INVALID_ARGUMENT; if (*listp == NULL || **listp == '\0') { if ((*listp = strdup(def)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } list = *listp; *listp = NULL; if (*list == '+') { /* Append names to default list */ if ((tmp = kex_names_cat(def, list + 1)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(list); list = tmp; } else if (*list == '-') { /* Remove names from default list */ if ((*listp = match_filter_denylist(def, list + 1)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(list); /* filtering has already been done */ return 0; } else if (*list == '^') { /* Place names at head of default list */ if ((tmp = kex_names_cat(list + 1, def)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(list); list = tmp; } else { /* Explicit list, overrides default - just use "list" as is */ } /* * The supplied names may be a pattern-list. For the -list case, * the patterns are applied above. For the +list and explicit list * cases we need to do it now. */ ret = NULL; if ((patterns = opatterns = strdup(list)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } /* Apply positive (i.e. non-negated) patterns from the list */ while ((cp = strsep(&patterns, ",")) != NULL) { if (*cp == '!') { /* negated matches are not supported here */ r = SSH_ERR_INVALID_ARGUMENT; goto fail; } free(matching); if ((matching = match_filter_allowlist(all, cp)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } if ((tmp = kex_names_cat(ret, matching)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(ret); ret = tmp; } if (ret == NULL || *ret == '\0') { /* An empty name-list is an error */ /* XXX better error code? */ r = SSH_ERR_INVALID_ARGUMENT; goto fail; } /* success */ *listp = ret; ret = NULL; r = 0; fail: free(matching); free(opatterns); free(list); free(ret); return r; } openssh-10.0p1/PaxHeaders.10889/kex.c100644 001750 001750 0000000003614775415623 0014107xustar0030 atime=1744182234.571119053 openssh-10.0p1/kex.c010064400017500001750000001136161477541562300125020ustar00djmdjm/* $OpenBSD: kex.c,v 1.187 2024/08/23 04:51:00 deraadt Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #ifdef HAVE_POLL_H #include #endif #ifdef WITH_OPENSSL #include #include #endif #include "ssh.h" #include "ssh2.h" #include "atomicio.h" #include "version.h" #include "packet.h" #include "compat.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "log.h" #include "mac.h" #include "match.h" #include "misc.h" #include "dispatch.h" #include "monitor.h" #include "myproposal.h" #include "ssherr.h" #include "sshbuf.h" #include "digest.h" #include "xmalloc.h" /* prototype */ static int kex_choose_conf(struct ssh *, uint32_t seq); static int kex_input_newkeys(int, u_int32_t, struct ssh *); static const char * const proposal_names[PROPOSAL_MAX] = { "KEX algorithms", "host key algorithms", "ciphers ctos", "ciphers stoc", "MACs ctos", "MACs stoc", "compression ctos", "compression stoc", "languages ctos", "languages stoc", }; /* * Fill out a proposal array with dynamically allocated values, which may * be modified as required for compatibility reasons. * Any of the options may be NULL, in which case the default is used. * Array contents must be freed by calling kex_proposal_free_entries. */ void kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX], const char *kexalgos, const char *ciphers, const char *macs, const char *comp, const char *hkalgs) { const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER }; const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT }; const char **defprop = ssh->kex->server ? defpropserver : defpropclient; u_int i; char *cp; if (prop == NULL) fatal_f("proposal missing"); /* Append EXT_INFO signalling to KexAlgorithms */ if (kexalgos == NULL) kexalgos = defprop[PROPOSAL_KEX_ALGS]; if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? "ext-info-s,kex-strict-s-v00@openssh.com" : "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) fatal_f("kex_names_cat"); for (i = 0; i < PROPOSAL_MAX; i++) { switch(i) { case PROPOSAL_KEX_ALGS: prop[i] = compat_kex_proposal(ssh, cp); break; case PROPOSAL_ENC_ALGS_CTOS: case PROPOSAL_ENC_ALGS_STOC: prop[i] = xstrdup(ciphers ? ciphers : defprop[i]); break; case PROPOSAL_MAC_ALGS_CTOS: case PROPOSAL_MAC_ALGS_STOC: prop[i] = xstrdup(macs ? macs : defprop[i]); break; case PROPOSAL_COMP_ALGS_CTOS: case PROPOSAL_COMP_ALGS_STOC: prop[i] = xstrdup(comp ? comp : defprop[i]); break; case PROPOSAL_SERVER_HOST_KEY_ALGS: prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]); break; default: prop[i] = xstrdup(defprop[i]); } } free(cp); } void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]) { u_int i; for (i = 0; i < PROPOSAL_MAX; i++) free(prop[i]); } /* put algorithm proposal into buffer */ int kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) { u_int i; int r; sshbuf_reset(b); /* * add a dummy cookie, the cookie will be overwritten by * kex_send_kexinit(), each time a kexinit is set */ for (i = 0; i < KEX_COOKIE_LEN; i++) { if ((r = sshbuf_put_u8(b, 0)) != 0) return r; } for (i = 0; i < PROPOSAL_MAX; i++) { if ((r = sshbuf_put_cstring(b, proposal[i])) != 0) return r; } if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */ (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */ return r; return 0; } /* parse buffer and return algorithm proposal */ int kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp) { struct sshbuf *b = NULL; u_char v; u_int i; char **proposal = NULL; int r; *propp = NULL; if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL) return SSH_ERR_ALLOC_FAIL; if ((b = sshbuf_fromb(raw)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */ error_fr(r, "consume cookie"); goto out; } /* extract kex init proposal strings */ for (i = 0; i < PROPOSAL_MAX; i++) { if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) { error_fr(r, "parse proposal %u", i); goto out; } debug2("%s: %s", proposal_names[i], proposal[i]); } /* first kex follows / reserved */ if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */ error_fr(r, "parse"); goto out; } if (first_kex_follows != NULL) *first_kex_follows = v; debug2("first_kex_follows %d ", v); debug2("reserved %u ", i); r = 0; *propp = proposal; out: if (r != 0 && proposal != NULL) kex_prop_free(proposal); sshbuf_free(b); return r; } void kex_prop_free(char **proposal) { u_int i; if (proposal == NULL) return; for (i = 0; i < PROPOSAL_MAX; i++) free(proposal[i]); free(proposal); } int kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { int r; /* If in strict mode, any unexpected message is an error */ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) { ssh_packet_disconnect(ssh, "strict KEX violation: " "unexpected packet type %u (seqnr %u)", type, seq); } error_f("type %u seq %u", type, seq); if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || (r = sshpkt_put_u32(ssh, seq)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; return 0; } static void kex_reset_dispatch(struct ssh *ssh) { ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN, SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); } void kex_set_server_sig_algs(struct ssh *ssh, const char *allowed_algs) { char *alg, *oalgs, *algs, *sigalgs; const char *sigalg; /* * NB. allowed algorithms may contain certificate algorithms that * map to a specific plain signature type, e.g. * rsa-sha2-512-cert-v01@openssh.com => rsa-sha2-512 * We need to be careful here to match these, retain the mapping * and only add each signature algorithm once. */ if ((sigalgs = sshkey_alg_list(0, 1, 1, ',')) == NULL) fatal_f("sshkey_alg_list failed"); oalgs = algs = xstrdup(allowed_algs); free(ssh->kex->server_sig_algs); ssh->kex->server_sig_algs = NULL; for ((alg = strsep(&algs, ",")); alg != NULL && *alg != '\0'; (alg = strsep(&algs, ","))) { if ((sigalg = sshkey_sigalg_by_name(alg)) == NULL) continue; if (!kex_has_any_alg(sigalg, sigalgs)) continue; /* Don't add an algorithm twice. */ if (ssh->kex->server_sig_algs != NULL && kex_has_any_alg(sigalg, ssh->kex->server_sig_algs)) continue; xextendf(&ssh->kex->server_sig_algs, ",", "%s", sigalg); } free(oalgs); free(sigalgs); if (ssh->kex->server_sig_algs == NULL) ssh->kex->server_sig_algs = xstrdup(""); } static int kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) { int r; if (ssh->kex->server_sig_algs == NULL && (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u32(m, 3)) != 0 || (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 || (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 || (r = sshbuf_put_cstring(m, "publickey-hostbound@openssh.com")) != 0 || (r = sshbuf_put_cstring(m, "0")) != 0 || (r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 || (r = sshbuf_put_cstring(m, "0")) != 0) { error_fr(r, "compose"); return r; } return 0; } static int kex_compose_ext_info_client(struct ssh *ssh, struct sshbuf *m) { int r; if ((r = sshbuf_put_u32(m, 1)) != 0 || (r = sshbuf_put_cstring(m, "ext-info-in-auth@openssh.com")) != 0 || (r = sshbuf_put_cstring(m, "0")) != 0) { error_fr(r, "compose"); goto out; } /* success */ r = 0; out: return r; } static int kex_maybe_send_ext_info(struct ssh *ssh) { int r; struct sshbuf *m = NULL; if ((ssh->kex->flags & KEX_INITIAL) == 0) return 0; if (!ssh->kex->ext_info_c && !ssh->kex->ext_info_s) return 0; /* Compose EXT_INFO packet. */ if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (ssh->kex->ext_info_c && (r = kex_compose_ext_info_server(ssh, m)) != 0) goto fail; if (ssh->kex->ext_info_s && (r = kex_compose_ext_info_client(ssh, m)) != 0) goto fail; /* Send the actual KEX_INFO packet */ debug("Sending SSH2_MSG_EXT_INFO"); if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || (r = sshpkt_putb(ssh, m)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_f("send EXT_INFO"); goto fail; } r = 0; fail: sshbuf_free(m); return r; } int kex_server_update_ext_info(struct ssh *ssh) { int r; if ((ssh->kex->flags & KEX_HAS_EXT_INFO_IN_AUTH) == 0) return 0; debug_f("Sending SSH2_MSG_EXT_INFO"); if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || (r = sshpkt_put_u32(ssh, 1)) != 0 || (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || (r = sshpkt_put_cstring(ssh, ssh->kex->server_sig_algs)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_f("send EXT_INFO"); return r; } return 0; } int kex_send_newkeys(struct ssh *ssh) { int r; kex_reset_dispatch(ssh); if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; debug("SSH2_MSG_NEWKEYS sent"); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); if ((r = kex_maybe_send_ext_info(ssh)) != 0) return r; debug("expecting SSH2_MSG_NEWKEYS"); return 0; } /* Check whether an ext_info value contains the expected version string */ static int kex_ext_info_check_ver(struct kex *kex, const char *name, const u_char *val, size_t len, const char *want_ver, u_int flag) { if (memchr(val, '\0', len) != NULL) { error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name); return SSH_ERR_INVALID_FORMAT; } debug_f("%s=<%s>", name, val); if (strcmp(val, want_ver) == 0) kex->flags |= flag; else debug_f("unsupported version of %s extension", name); return 0; } static int kex_ext_info_client_parse(struct ssh *ssh, const char *name, const u_char *value, size_t vlen) { int r; /* NB. some messages are only accepted in the initial EXT_INFO */ if (strcmp(name, "server-sig-algs") == 0) { /* Ensure no \0 lurking in value */ if (memchr(value, '\0', vlen) != NULL) { error_f("nul byte in %s", name); return SSH_ERR_INVALID_FORMAT; } debug_f("%s=<%s>", name, value); free(ssh->kex->server_sig_algs); ssh->kex->server_sig_algs = xstrdup((const char *)value); } else if (ssh->kex->ext_info_received == 1 && strcmp(name, "publickey-hostbound@openssh.com") == 0) { if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) { return r; } } else if (ssh->kex->ext_info_received == 1 && strcmp(name, "ping@openssh.com") == 0) { if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, "0", KEX_HAS_PING)) != 0) { return r; } } else debug_f("%s (unrecognised)", name); return 0; } static int kex_ext_info_server_parse(struct ssh *ssh, const char *name, const u_char *value, size_t vlen) { int r; if (strcmp(name, "ext-info-in-auth@openssh.com") == 0) { if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, "0", KEX_HAS_EXT_INFO_IN_AUTH)) != 0) { return r; } } else debug_f("%s (unrecognised)", name); return 0; } int kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; const int max_ext_info = kex->server ? 1 : 2; u_int32_t i, ninfo; char *name; u_char *val; size_t vlen; int r; debug("SSH2_MSG_EXT_INFO received"); if (++kex->ext_info_received > max_ext_info) { error("too many SSH2_MSG_EXT_INFO messages sent by peer"); return dispatch_protocol_error(type, seq, ssh); } ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) return r; if (ninfo >= 1024) { error("SSH2_MSG_EXT_INFO with too many entries, expected " "<=1024, received %u", ninfo); return dispatch_protocol_error(type, seq, ssh); } for (i = 0; i < ninfo; i++) { if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) return r; if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) { free(name); return r; } debug3_f("extension %s", name); if (kex->server) { if ((r = kex_ext_info_server_parse(ssh, name, val, vlen)) != 0) return r; } else { if ((r = kex_ext_info_client_parse(ssh, name, val, vlen)) != 0) return r; } free(name); free(val); } return sshpkt_get_end(ssh); } static int kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; int r, initial = (kex->flags & KEX_INITIAL) != 0; char *cp, **prop; debug("SSH2_MSG_NEWKEYS received"); if (kex->ext_info_c && initial) ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error); ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); if ((r = sshpkt_get_end(ssh)) != 0) return r; if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0) return r; if (initial) { /* Remove initial KEX signalling from proposal for rekeying */ if ((r = kex_buf2prop(kex->my, NULL, &prop)) != 0) return r; if ((cp = match_filter_denylist(prop[PROPOSAL_KEX_ALGS], kex->server ? "ext-info-s,kex-strict-s-v00@openssh.com" : "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) { error_f("match_filter_denylist failed"); goto fail; } free(prop[PROPOSAL_KEX_ALGS]); prop[PROPOSAL_KEX_ALGS] = cp; if ((r = kex_prop2buf(ssh->kex->my, prop)) != 0) { error_f("kex_prop2buf failed"); fail: kex_proposal_free_entries(prop); free(prop); return SSH_ERR_INTERNAL_ERROR; } kex_proposal_free_entries(prop); free(prop); } kex->done = 1; kex->flags &= ~KEX_INITIAL; sshbuf_reset(kex->peer); kex->flags &= ~KEX_INIT_SENT; free(kex->name); kex->name = NULL; return 0; } int kex_send_kexinit(struct ssh *ssh) { u_char *cookie; struct kex *kex = ssh->kex; int r; if (kex == NULL) { error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } if (kex->flags & KEX_INIT_SENT) return 0; kex->done = 0; /* generate a random cookie */ if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) { error_f("bad kex length: %zu < %d", sshbuf_len(kex->my), KEX_COOKIE_LEN); return SSH_ERR_INVALID_FORMAT; } if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) { error_f("buffer error"); return SSH_ERR_INTERNAL_ERROR; } arc4random_buf(cookie, KEX_COOKIE_LEN); if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || (r = sshpkt_putb(ssh, kex->my)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_fr(r, "compose reply"); return r; } debug("SSH2_MSG_KEXINIT sent"); kex->flags |= KEX_INIT_SENT; return 0; } int kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; const u_char *ptr; u_int i; size_t dlen; int r; debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) { error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) { if ((r = sshpkt_get_u8(ssh, NULL)) != 0) { error_fr(r, "discard cookie"); return r; } } for (i = 0; i < PROPOSAL_MAX; i++) { if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { error_fr(r, "discard proposal"); return r; } } /* * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported * KEX method has the server move first, but a server might be using * a custom method or one that we otherwise don't support. We should * be prepared to remember first_kex_follows here so we can eat a * packet later. * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means * for cases where the server *doesn't* go first. I guess we should * ignore it when it is set for these cases, which is what we do now. */ if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */ (r = sshpkt_get_end(ssh)) != 0) return r; if (!(kex->flags & KEX_INIT_SENT)) if ((r = kex_send_kexinit(ssh)) != 0) return r; if ((r = kex_choose_conf(ssh, seq)) != 0) return r; if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) return (kex->kex[kex->kex_type])(ssh); error_f("unknown kex type %u", kex->kex_type); return SSH_ERR_INTERNAL_ERROR; } struct kex * kex_new(void) { struct kex *kex; if ((kex = calloc(1, sizeof(*kex))) == NULL || (kex->peer = sshbuf_new()) == NULL || (kex->my = sshbuf_new()) == NULL || (kex->client_version = sshbuf_new()) == NULL || (kex->server_version = sshbuf_new()) == NULL || (kex->session_id = sshbuf_new()) == NULL) { kex_free(kex); return NULL; } return kex; } void kex_free_newkeys(struct newkeys *newkeys) { if (newkeys == NULL) return; if (newkeys->enc.key) { explicit_bzero(newkeys->enc.key, newkeys->enc.key_len); free(newkeys->enc.key); newkeys->enc.key = NULL; } if (newkeys->enc.iv) { explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len); free(newkeys->enc.iv); newkeys->enc.iv = NULL; } free(newkeys->enc.name); explicit_bzero(&newkeys->enc, sizeof(newkeys->enc)); free(newkeys->comp.name); explicit_bzero(&newkeys->comp, sizeof(newkeys->comp)); mac_clear(&newkeys->mac); if (newkeys->mac.key) { explicit_bzero(newkeys->mac.key, newkeys->mac.key_len); free(newkeys->mac.key); newkeys->mac.key = NULL; } free(newkeys->mac.name); explicit_bzero(&newkeys->mac, sizeof(newkeys->mac)); freezero(newkeys, sizeof(*newkeys)); } void kex_free(struct kex *kex) { u_int mode; if (kex == NULL) return; #ifdef WITH_OPENSSL DH_free(kex->dh); #ifdef OPENSSL_HAS_ECC EC_KEY_free(kex->ec_client_key); #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(kex->newkeys[mode]); kex->newkeys[mode] = NULL; } sshbuf_free(kex->peer); sshbuf_free(kex->my); sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); sshbuf_free(kex->initial_sig); sshkey_free(kex->initial_hostkey); free(kex->failed_choice); free(kex->hostkey_alg); free(kex->name); free(kex); } int kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) { int r; if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0) return r; ssh->kex->flags = KEX_INITIAL; kex_reset_dispatch(ssh); ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); return 0; } int kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) { int r; if ((r = kex_ready(ssh, proposal)) != 0) return r; if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ kex_free(ssh->kex); ssh->kex = NULL; return r; } return 0; } /* * Request key re-exchange, returns 0 on success or a ssherr.h error * code otherwise. Must not be called if KEX is incomplete or in-progress. */ int kex_start_rekex(struct ssh *ssh) { if (ssh->kex == NULL) { error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } if (ssh->kex->done == 0) { error_f("requested twice"); return SSH_ERR_INTERNAL_ERROR; } ssh->kex->done = 0; return kex_send_kexinit(ssh); } static int choose_enc(struct sshenc *enc, char *client, char *server) { char *name = match_list(client, server, NULL); if (name == NULL) return SSH_ERR_NO_CIPHER_ALG_MATCH; if ((enc->cipher = cipher_by_name(name)) == NULL) { error_f("unsupported cipher %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } enc->name = name; enc->enabled = 0; enc->iv = NULL; enc->iv_len = cipher_ivlen(enc->cipher); enc->key = NULL; enc->key_len = cipher_keylen(enc->cipher); enc->block_size = cipher_blocksize(enc->cipher); return 0; } static int choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) { char *name = match_list(client, server, NULL); if (name == NULL) return SSH_ERR_NO_MAC_ALG_MATCH; if (mac_setup(mac, name) < 0) { error_f("unsupported MAC %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } mac->name = name; mac->key = NULL; mac->enabled = 0; return 0; } static int choose_comp(struct sshcomp *comp, char *client, char *server) { char *name = match_list(client, server, NULL); if (name == NULL) return SSH_ERR_NO_COMPRESS_ALG_MATCH; #ifdef WITH_ZLIB if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; } else #endif /* WITH_ZLIB */ if (strcmp(name, "none") == 0) { comp->type = COMP_NONE; } else { error_f("unsupported compression scheme %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } comp->name = name; return 0; } static int choose_kex(struct kex *k, char *client, char *server) { 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 (!kex_name_valid(k->name)) { error_f("unsupported KEX method %s", k->name); return SSH_ERR_INTERNAL_ERROR; } k->kex_type = kex_type_from_name(k->name); k->hash_alg = kex_hash_from_name(k->name); k->ec_nid = kex_nid_from_name(k->name); return 0; } static int choose_hostkeyalg(struct kex *k, char *client, char *server) { free(k->hostkey_alg); k->hostkey_alg = match_list(client, server, NULL); debug("kex: host key algorithm: %s", k->hostkey_alg ? k->hostkey_alg : "(no match)"); if (k->hostkey_alg == NULL) return SSH_ERR_NO_HOSTKEY_ALG_MATCH; k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); if (k->hostkey_type == KEY_UNSPEC) { error_f("unsupported hostkey algorithm %s", k->hostkey_alg); return SSH_ERR_INTERNAL_ERROR; } k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); return 0; } static int proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) { static int check[] = { PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 }; int *idx; char *p; for (idx = &check[0]; *idx != -1; idx++) { if ((p = strchr(my[*idx], ',')) != NULL) *p = '\0'; if ((p = strchr(peer[*idx], ',')) != NULL) *p = '\0'; if (strcmp(my[*idx], peer[*idx]) != 0) { debug2("proposal mismatch: my %s peer %s", my[*idx], peer[*idx]); return (0); } } debug2("proposals match"); return (1); } static int kexalgs_contains(char **peer, const char *ext) { return kex_has_any_alg(peer[PROPOSAL_KEX_ALGS], ext); } static int kex_choose_conf(struct ssh *ssh, uint32_t seq) { struct kex *kex = ssh->kex; struct newkeys *newkeys; char **my = NULL, **peer = NULL; char **cprop, **sprop; int nenc, nmac, ncomp; u_int mode, ctos, need, dh_need, authlen; int r, first_kex_follows; debug2("local %s KEXINIT proposal", kex->server ? "server" : "client"); if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0) goto out; debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server"); if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0) goto out; if (kex->server) { cprop=peer; sprop=my; } else { cprop=my; sprop=peer; } /* Check whether peer supports ext_info/kex_strict */ if ((kex->flags & KEX_INITIAL) != 0) { if (kex->server) { kex->ext_info_c = kexalgs_contains(peer, "ext-info-c"); kex->kex_strict = kexalgs_contains(peer, "kex-strict-c-v00@openssh.com"); } else { kex->ext_info_s = kexalgs_contains(peer, "ext-info-s"); kex->kex_strict = kexalgs_contains(peer, "kex-strict-s-v00@openssh.com"); } if (kex->kex_strict) { debug3_f("will use strict KEX ordering"); if (seq != 0) ssh_packet_disconnect(ssh, "strict KEX violation: " "KEXINIT was not the first packet"); } } /* Check whether client supports rsa-sha2 algorithms */ if (kex->server && (kex->flags & KEX_INITIAL)) { if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com")) kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com")) kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; } /* Algorithm Negotiation */ if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS])) != 0) { kex->failed_choice = peer[PROPOSAL_KEX_ALGS]; peer[PROPOSAL_KEX_ALGS] = NULL; goto out; } if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) { kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS]; peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL; goto out; } for (mode = 0; mode < MODE_MAX; mode++) { if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } kex->newkeys[mode] = newkeys; ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; if ((r = choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc])) != 0) { kex->failed_choice = peer[nenc]; peer[nenc] = NULL; goto out; } authlen = cipher_authlen(newkeys->enc.cipher); /* ignore mac for authenticated encryption */ if (authlen == 0 && (r = choose_mac(ssh, &newkeys->mac, cprop[nmac], sprop[nmac])) != 0) { kex->failed_choice = peer[nmac]; peer[nmac] = NULL; goto out; } if ((r = choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp])) != 0) { kex->failed_choice = peer[ncomp]; peer[ncomp] = NULL; goto out; } debug("kex: %s cipher: %s MAC: %s compression: %s", ctos ? "client->server" : "server->client", newkeys->enc.name, authlen == 0 ? newkeys->mac.name : "", newkeys->comp.name); } need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; need = MAXIMUM(need, newkeys->enc.key_len); need = MAXIMUM(need, newkeys->enc.block_size); need = MAXIMUM(need, newkeys->enc.iv_len); need = MAXIMUM(need, newkeys->mac.key_len); dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher)); dh_need = MAXIMUM(dh_need, newkeys->enc.block_size); dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len); dh_need = MAXIMUM(dh_need, newkeys->mac.key_len); } /* XXX need runden? */ kex->we_need = need; kex->dh_need = dh_need; /* ignore the next message if the proposals do not match */ if (first_kex_follows && !proposals_match(my, peer)) ssh->dispatch_skip_packets = 1; r = 0; out: kex_prop_free(my); kex_prop_free(peer); return r; } static int derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, const struct sshbuf *shared_secret, u_char **keyp) { struct kex *kex = ssh->kex; struct ssh_digest_ctx *hashctx = NULL; char c = id; u_int have; size_t mdsz; u_char *digest; int r; if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) return SSH_ERR_INVALID_ARGUMENT; if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* K1 = HASH(K || H || "A" || session_id) */ if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || ssh_digest_update_buffer(hashctx, shared_secret) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, &c, 1) != 0 || ssh_digest_update_buffer(hashctx, kex->session_id) != 0 || ssh_digest_final(hashctx, digest, mdsz) != 0) { r = SSH_ERR_LIBCRYPTO_ERROR; error_f("KEX hash failed"); goto out; } ssh_digest_free(hashctx); hashctx = NULL; /* * expand key: * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) * Key = K1 || K2 || ... || Kn */ for (have = mdsz; need > have; have += mdsz) { if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || ssh_digest_update_buffer(hashctx, shared_secret) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, digest, have) != 0 || ssh_digest_final(hashctx, digest + have, mdsz) != 0) { error_f("KDF failed"); r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ssh_digest_free(hashctx); hashctx = NULL; } #ifdef DEBUG_KEX fprintf(stderr, "key '%c'== ", c); dump_digest("key", digest, need); #endif *keyp = digest; digest = NULL; r = 0; out: free(digest); ssh_digest_free(hashctx); return r; } #define NKEYS 6 int kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, const struct sshbuf *shared_secret) { struct kex *kex = ssh->kex; u_char *keys[NKEYS]; u_int i, j, mode, ctos; int r; /* save initial hash as session id */ if ((kex->flags & KEX_INITIAL) != 0) { if (sshbuf_len(kex->session_id) != 0) { error_f("already have session ID at kex"); return SSH_ERR_INTERNAL_ERROR; } if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0) return r; } else if (sshbuf_len(kex->session_id) == 0) { error_f("no session ID in rekex"); return SSH_ERR_INTERNAL_ERROR; } for (i = 0; i < NKEYS; i++) { if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen, shared_secret, &keys[i])) != 0) { for (j = 0; j < i; j++) free(keys[j]); return r; } } for (mode = 0; mode < MODE_MAX; mode++) { ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1]; kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; } return 0; } int kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp) { struct kex *kex = ssh->kex; *pubp = NULL; *prvp = NULL; if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { error_f("missing hostkey loader"); return SSH_ERR_INVALID_ARGUMENT; } *pubp = kex->load_host_public_key(kex->hostkey_type, kex->hostkey_nid, ssh); *prvp = kex->load_host_private_key(kex->hostkey_type, kex->hostkey_nid, ssh); if (*pubp == NULL) return SSH_ERR_NO_HOSTKEY_LOADED; return 0; } int kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) { struct kex *kex = ssh->kex; if (kex->verify_host_key == NULL) { error_f("missing hostkey verifier"); return SSH_ERR_INVALID_ARGUMENT; } if (server_host_key->type != kex->hostkey_type || (kex->hostkey_type == KEY_ECDSA && server_host_key->ecdsa_nid != kex->hostkey_nid)) return SSH_ERR_KEY_TYPE_MISMATCH; if (kex->verify_host_key(server_host_key, ssh) == -1) return SSH_ERR_SIGNATURE_INVALID; return 0; } #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(const char *msg, const u_char *digest, int len) { fprintf(stderr, "%s\n", msg); sshbuf_dump_data(digest, len, stderr); } #endif /* * Send a plaintext error message to the peer, suffixed by \r\n. * Only used during banner exchange, and there only for the server. */ static void send_error(struct ssh *ssh, char *msg) { char *crnl = "\r\n"; if (!ssh->kex->server) return; if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), msg, strlen(msg)) != strlen(msg) || atomicio(vwrite, ssh_packet_get_connection_out(ssh), crnl, strlen(crnl)) != strlen(crnl)) error_f("write: %.100s", strerror(errno)); } /* * Sends our identification string and waits for the peer's. Will block for * up to timeout_ms (or indefinitely if timeout_ms <= 0). * Returns on 0 success or a ssherr.h code on failure. */ int kex_exchange_identification(struct ssh *ssh, int timeout_ms, const char *version_addendum) { int remote_major, remote_minor, mismatch, oerrno = 0; size_t len, n; int r, expect_nl; u_char c; struct sshbuf *our_version = ssh->kex->server ? ssh->kex->server_version : ssh->kex->client_version; struct sshbuf *peer_version = ssh->kex->server ? ssh->kex->client_version : ssh->kex->server_version; char *our_version_string = NULL, *peer_version_string = NULL; char *cp, *remote_version = NULL; /* Prepare and send our banner */ sshbuf_reset(our_version); if (version_addendum != NULL && *version_addendum == '\0') version_addendum = NULL; if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n", PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, version_addendum == NULL ? "" : " ", version_addendum == NULL ? "" : version_addendum)) != 0) { oerrno = errno; error_fr(r, "sshbuf_putf"); goto out; } if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), sshbuf_mutable_ptr(our_version), sshbuf_len(our_version)) != sshbuf_len(our_version)) { oerrno = errno; debug_f("write: %.100s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto out; } if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */ oerrno = errno; error_fr(r, "sshbuf_consume_end"); goto out; } our_version_string = sshbuf_dup_string(our_version); if (our_version_string == NULL) { error_f("sshbuf_dup_string failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } debug("Local version string %.100s", our_version_string); /* Read other side's version identification. */ for (n = 0; ; n++) { if (n >= SSH_MAX_PRE_BANNER_LINES) { send_error(ssh, "No SSH identification string " "received."); error_f("No SSH version received in first %u lines " "from server", SSH_MAX_PRE_BANNER_LINES); r = SSH_ERR_INVALID_FORMAT; goto out; } sshbuf_reset(peer_version); expect_nl = 0; for (;;) { if (timeout_ms > 0) { r = waitrfd(ssh_packet_get_connection_in(ssh), &timeout_ms, NULL); if (r == -1 && errno == ETIMEDOUT) { send_error(ssh, "Timed out waiting " "for SSH identification string."); error("Connection timed out during " "banner exchange"); r = SSH_ERR_CONN_TIMEOUT; goto out; } else if (r == -1) { oerrno = errno; error_f("%s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto out; } } len = atomicio(read, ssh_packet_get_connection_in(ssh), &c, 1); if (len != 1 && errno == EPIPE) { verbose_f("Connection closed by remote host"); r = SSH_ERR_CONN_CLOSED; goto out; } else if (len != 1) { oerrno = errno; error_f("read: %.100s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto out; } if (c == '\r') { expect_nl = 1; continue; } if (c == '\n') break; if (c == '\0' || expect_nl) { verbose_f("banner line contains invalid " "characters"); goto invalid; } if ((r = sshbuf_put_u8(peer_version, c)) != 0) { oerrno = errno; error_fr(r, "sshbuf_put"); goto out; } if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) { verbose_f("banner line too long"); goto invalid; } } /* Is this an actual protocol banner? */ if (sshbuf_len(peer_version) > 4 && memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0) break; /* If not, then just log the line and continue */ if ((cp = sshbuf_dup_string(peer_version)) == NULL) { error_f("sshbuf_dup_string failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } /* Do not accept lines before the SSH ident from a client */ if (ssh->kex->server) { verbose_f("client sent invalid protocol identifier " "\"%.256s\"", cp); free(cp); goto invalid; } debug_f("banner line %zu: %s", n, cp); free(cp); } peer_version_string = sshbuf_dup_string(peer_version); if (peer_version_string == NULL) fatal_f("sshbuf_dup_string failed"); /* XXX must be same size for sscanf */ if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) { error_f("calloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } /* * Check that the versions match. In future this might accept * several versions and set appropriate flags to handle them. */ if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) != 3) { error("Bad remote protocol version identification: '%.100s'", peer_version_string); invalid: send_error(ssh, "Invalid SSH identification string."); r = SSH_ERR_INVALID_FORMAT; goto out; } debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); compat_banner(ssh, remote_version); mismatch = 0; switch (remote_major) { case 2: break; case 1: if (remote_minor != 99) mismatch = 1; break; default: mismatch = 1; break; } if (mismatch) { error("Protocol major versions differ: %d vs. %d", PROTOCOL_MAJOR_2, remote_major); send_error(ssh, "Protocol major versions differ."); r = SSH_ERR_NO_PROTOCOL_VERSION; goto out; } if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) { logit("probed from %s port %d with %s. Don't panic.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), peer_version_string); r = SSH_ERR_CONN_CLOSED; /* XXX */ goto out; } if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) { logit("scanned from %s port %d with %s. Don't panic.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), peer_version_string); r = SSH_ERR_CONN_CLOSED; /* XXX */ goto out; } /* success */ r = 0; out: free(our_version_string); free(peer_version_string); free(remote_version); if (r == SSH_ERR_SYSTEM_ERROR) errno = oerrno; return r; } openssh-10.0p1/PaxHeaders.10889/kex.h100644 001750 001750 0000000003614775415623 0014114xustar0030 atime=1744182234.571119053 openssh-10.0p1/kex.h010064400017500001750000000231121477541562300124760ustar00djmdjm/* $OpenBSD: kex.h,v 1.126 2024/09/02 12:13:56 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef KEX_H #define KEX_H #include "mac.h" #include "crypto_api.h" #ifdef WITH_OPENSSL # include # include # include # ifdef OPENSSL_HAS_ECC # include # else /* OPENSSL_HAS_ECC */ # define EC_KEY void # define EC_GROUP void # define EC_POINT void # endif /* OPENSSL_HAS_ECC */ #else /* WITH_OPENSSL */ # define DH void # define BIGNUM void # define EC_KEY void # define EC_GROUP void # define EC_POINT void #endif /* WITH_OPENSSL */ #define KEX_COOKIE_LEN 16 #define KEX_DH1 "diffie-hellman-group1-sha1" #define KEX_DH14_SHA1 "diffie-hellman-group14-sha1" #define KEX_DH14_SHA256 "diffie-hellman-group14-sha256" #define KEX_DH16_SHA512 "diffie-hellman-group16-sha512" #define KEX_DH18_SHA512 "diffie-hellman-group18-sha512" #define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" #define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256" #define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384" #define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" #define KEX_CURVE25519_SHA256 "curve25519-sha256" #define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org" #define KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512" #define KEX_SNTRUP761X25519_SHA512_OLD "sntrup761x25519-sha512@openssh.com" #define KEX_MLKEM768X25519_SHA256 "mlkem768x25519-sha256" #define COMP_NONE 0 #define COMP_DELAYED 2 #define CURVE25519_SIZE 32 enum kex_init_proposals { PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, PROPOSAL_ENC_ALGS_CTOS, PROPOSAL_ENC_ALGS_STOC, PROPOSAL_MAC_ALGS_CTOS, PROPOSAL_MAC_ALGS_STOC, PROPOSAL_COMP_ALGS_CTOS, PROPOSAL_COMP_ALGS_STOC, PROPOSAL_LANG_CTOS, PROPOSAL_LANG_STOC, PROPOSAL_MAX }; enum kex_modes { MODE_IN, MODE_OUT, MODE_MAX }; enum kex_exchange { KEX_DH_GRP1_SHA1 = 1, KEX_DH_GRP14_SHA1, KEX_DH_GRP14_SHA256, KEX_DH_GRP16_SHA512, KEX_DH_GRP18_SHA512, KEX_DH_GEX_SHA1, KEX_DH_GEX_SHA256, KEX_ECDH_SHA2, KEX_C25519_SHA256, KEX_KEM_SNTRUP761X25519_SHA512, KEX_KEM_MLKEM768X25519_SHA256, KEX_MAX }; /* kex->flags */ #define KEX_INIT_SENT 0x0001 #define KEX_INITIAL 0x0002 #define KEX_HAS_PUBKEY_HOSTBOUND 0x0004 #define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */ #define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */ #define KEX_HAS_PING 0x0020 #define KEX_HAS_EXT_INFO_IN_AUTH 0x0040 struct sshenc { char *name; const struct sshcipher *cipher; int enabled; u_int key_len; u_int iv_len; u_int block_size; u_char *key; u_char *iv; }; struct sshcomp { u_int type; int enabled; char *name; }; struct newkeys { struct sshenc enc; struct sshmac mac; struct sshcomp comp; }; struct ssh; struct sshbuf; struct kex { struct newkeys *newkeys[MODE_MAX]; u_int we_need; u_int dh_need; int server; char *name; char *hostkey_alg; int hostkey_type; int hostkey_nid; u_int kex_type; char *server_sig_algs; int ext_info_c; int ext_info_s; int kex_strict; int ext_info_received; struct sshbuf *my; struct sshbuf *peer; struct sshbuf *client_version; struct sshbuf *server_version; struct sshbuf *session_id; struct sshbuf *initial_sig; struct sshkey *initial_hostkey; sig_atomic_t done; u_int flags; int hash_alg; int ec_nid; char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); struct sshkey *(*load_host_private_key)(int, int, struct ssh *); int (*host_key_index)(struct sshkey *, int, struct ssh *); int (*sign)(struct ssh *, struct sshkey *, struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *); int (*kex[KEX_MAX])(struct ssh *); /* kex specific state */ DH *dh; /* DH */ u_int min, max, nbits; /* GEX */ EC_KEY *ec_client_key; /* ECDH */ const EC_GROUP *ec_group; /* ECDH */ u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */ u_char mlkem768_client_key[crypto_kem_mlkem768_SECRETKEYBYTES]; /* KEM */ struct sshbuf *client_pub; }; int kex_name_valid(const char *); u_int kex_type_from_name(const char *); int kex_hash_from_name(const char *); int kex_nid_from_name(const char *); int kex_names_valid(const char *); char *kex_alg_list(char); char *kex_names_cat(const char *, const char *); int kex_has_any_alg(const char *, const char *); int kex_assemble_names(char **, const char *, const char *); void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], const char *, const char *, const char *, const char *, const char *); void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]); int kex_exchange_identification(struct ssh *, int, const char *); struct kex *kex_new(void); int kex_ready(struct ssh *, char *[PROPOSAL_MAX]); int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); void kex_free_newkeys(struct newkeys *); void kex_free(struct kex *); int kex_buf2prop(struct sshbuf *, int *, char ***); int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); void kex_prop_free(char **); int kex_load_hostkey(struct ssh *, struct sshkey **, struct sshkey **); int kex_verify_host_key(struct ssh *, struct sshkey *); int kex_send_kexinit(struct ssh *); int kex_input_kexinit(int, u_int32_t, struct ssh *); int kex_input_ext_info(int, u_int32_t, struct ssh *); int kex_protocol_error(int, u_int32_t, struct ssh *); int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); int kex_send_newkeys(struct ssh *); int kex_start_rekex(struct ssh *); int kex_server_update_ext_info(struct ssh *); void kex_set_server_sig_algs(struct ssh *, const char *); int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); int kex_gen_client(struct ssh *); int kex_gen_server(struct ssh *); int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_dh_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_ecdh_keypair(struct kex *); int kex_ecdh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_ecdh_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_c25519_keypair(struct kex *); int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_kem_sntrup761x25519_keypair(struct kex *); int kex_kem_sntrup761x25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_kem_sntrup761x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_kem_mlkem768x25519_keypair(struct kex *); int kex_kem_mlkem768x25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_kem_mlkem768x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_dh_keygen(struct kex *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const struct sshbuf *, const struct sshbuf *, const struct sshbuf *, int, int, int, const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(const char *, const u_char *, int); #endif #if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC) # undef EC_KEY # undef EC_GROUP # undef EC_POINT #endif #endif openssh-10.0p1/PaxHeaders.10889/kexc25519.c100644 001750 001750 0000000003614775415623 0014660xustar0030 atime=1744182234.571119053 openssh-10.0p1/kexc25519.c010064400017500001750000000134031477541562300132440ustar00djmdjm/* $OpenBSD: kexc25519.c,v 1.18 2024/09/02 12:13:56 djm Exp $ */ /* * Copyright (c) 2019 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 #include #include #include #include "sshkey.h" #include "kex.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]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE))); void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) { static const u_char basepoint[CURVE25519_SIZE] = {9}; arc4random_buf(key, CURVE25519_SIZE); crypto_scalarmult_curve25519(pub, key, basepoint); } int 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 25519", shared_key, CURVE25519_SIZE); #endif 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 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 *buf = NULL; u_char *cp = NULL; int r; if ((buf = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; 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; } server_pub = sshbuf_ptr(server_blob); #ifdef DEBUG_KEXECDH dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE); #endif /* shared secret */ if ((buf = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } 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 *shared_secretp = buf; buf = NULL; out: sshbuf_free(buf); return r; } openssh-10.0p1/PaxHeaders.10889/kexdh.c100644 001750 001750 0000000003614775415623 0014423xustar0030 atime=1744182234.571119053 openssh-10.0p1/kexdh.c010064400017500001750000000117771477541562300130230ustar00djmdjm/* $OpenBSD: kexdh.c,v 1.34 2020/12/04 02:29:25 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" #ifdef WITH_OPENSSL #include #include #include #include #include "openbsd-compat/openssl-compat.h" #include #include "sshkey.h" #include "kex.h" #include "sshbuf.h" #include "digest.h" #include "ssherr.h" #include "dh.h" #include "log.h" int kex_dh_keygen(struct kex *kex) { 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 (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 (!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; } #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 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: BN_free(dh_pub); DH_free(kex->dh); kex->dh = NULL; sshbuf_free(buf); return r; } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/kexecdh.c100644 001750 001750 0000000003614775415623 0014733xustar0030 atime=1744182234.571119053 openssh-10.0p1/kexecdh.c010064400017500001750000000141421477541562300133200ustar00djmdjm/* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */ /* * 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 * 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 #include #include #include #include #include "sshkey.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_keypair(struct kex *kex) { EC_KEY *client_key = NULL; const EC_GROUP *group; const EC_POINT *public_key; struct sshbuf *buf = NULL; 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 ((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 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; } 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 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) */ openssh-10.0p1/PaxHeaders.10889/kexgen.c100644 001750 001750 0000000003614775415623 0014601xustar0030 atime=1744182234.572094859 openssh-10.0p1/kexgen.c010064400017500001750000000254641477541562300131770ustar00djmdjm/* $OpenBSD: kexgen.c,v 1.10 2024/09/09 02:39:57 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 #include #include #include #include #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_SNTRUP761X25519_SHA512: r = kex_kem_sntrup761x25519_keypair(kex); break; case KEX_KEM_MLKEM768X25519_SHA256: r = kex_kem_mlkem768x25519_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; debug("SSH2_MSG_KEX_ECDH_REPLY received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &kex_protocol_error); /* hostkey */ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) goto out; /* 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_SNTRUP761X25519_SHA512: r = kex_kem_sntrup761x25519_dec(kex, server_blob, &shared_secret); break; case KEX_KEM_MLKEM768X25519_SHA256: r = kex_kem_mlkem768x25519_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)) != 0) goto out; /* save initial signature and hostkey */ if ((kex->flags & KEX_INITIAL) != 0) { if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if ((kex->initial_sig = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0) goto out; kex->initial_hostkey = server_host_key; server_host_key = NULL; } /* success */ out: explicit_bzero(hash, sizeof(hash)); explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); explicit_bzero(kex->sntrup761_client_key, sizeof(kex->sntrup761_client_key)); explicit_bzero(kex->mlkem768_client_key, sizeof(kex->mlkem768_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; debug("SSH2_MSG_KEX_ECDH_INIT received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &kex_protocol_error); if ((r = kex_load_hostkey(ssh, &server_host_private, &server_host_public)) != 0) goto out; 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_SNTRUP761X25519_SHA512: r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; case KEX_KEM_MLKEM768X25519_SHA256: r = kex_kem_mlkem768x25519_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)) != 0) goto out; /* retain copy of hostkey used at initial KEX */ if (kex->initial_hostkey == NULL && (r = sshkey_from_private(server_host_public, &kex->initial_hostkey)) != 0) goto out; /* success */ 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; } openssh-10.0p1/PaxHeaders.10889/kexgex.c100644 001750 001750 0000000003614775415623 0014613xustar0030 atime=1744182234.572094859 openssh-10.0p1/kexgex.c010064400017500001750000000072601477541562300132030ustar00djmdjm/* $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. * * 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 #include #include #include "openbsd-compat/openssl-compat.h" #include "sshkey.h" #include "cipher.h" #include "kex.h" #include "ssh2.h" #include "ssherr.h" #include "sshbuf.h" #include "digest.h" int kexgex_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, int min, int wantbits, int max, const BIGNUM *prime, const BIGNUM *gen, const BIGNUM *client_dh_pub, const BIGNUM *server_dh_pub, const u_char *shared_secret, size_t secretlen, u_char *hash, size_t *hashlen) { struct sshbuf *b; int r; if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1)) 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 || (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) || (r = sshbuf_put_bignum2(b, prime)) != 0 || (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(b, shared_secret, secretlen)) != 0) { sshbuf_free(b); return r; } #ifdef DEBUG_KEXDH 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_KEXDH dump_digest("hash", hash, *hashlen); #endif return 0; } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/kexgexc.c100644 001750 001750 0000000003614775415623 0014756xustar0030 atime=1744182234.572094859 openssh-10.0p1/kexgexc.c010064400017500001750000000160341477541562300133450ustar00djmdjm/* $OpenBSD: kexgexc.c,v 1.38 2021/12/19 22:08:06 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * 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 #include #include #include #include #include #include "openbsd-compat/openssl-compat.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 "compat.h" #include "dispatch.h" #include "ssherr.h" #include "sshbuf.h" #include "misc.h" 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) { struct kex *kex = ssh->kex; int r; u_int nbits; nbits = dh_estimate(kex->dh_need * 8); kex->min = DH_GRP_MIN; kex->max = DH_GRP_MAX; kex->nbits = nbits; if (ssh->compat & SSH_BUG_DHGEX_LARGE) kex->nbits = MINIMUM(kex->nbits, 4096); /* New GEX request */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 || (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); #endif debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &input_kex_dh_gex_group); r = 0; out: return r; } static int input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; BIGNUM *p = NULL, *g = NULL; const BIGNUM *pub_key; int r, bits; debug("SSH2_MSG_KEX_DH_GEX_GROUP received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &kex_protocol_error); if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || (r = sshpkt_get_bignum2(ssh, &g)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; if ((bits = BN_num_bits(p)) < 0 || (u_int)bits < kex->min || (u_int)bits > kex->max) { r = SSH_ERR_DH_GEX_OUT_OF_RANGE; goto out; } if ((kex->dh = dh_new_group(g, p)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } 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) 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, pub_key); fprintf(stderr, "\n"); #endif debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply); r = 0; out: BN_clear_free(p); BN_clear_free(g); return r; } static int input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; 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 *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, hashlen; int r; debug("SSH2_MSG_KEX_DH_GEX_REPLY received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &kex_protocol_error); /* key, cert */ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) goto out; /* 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 || (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; if ((shared_secret = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) goto out; 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, kex->server_version, kex->my, kex->peer, server_host_key_blob, kex->min, kex->nbits, kex->max, dh_p, dh_g, pub_key, dh_server_pub, sshbuf_ptr(shared_secret), sshbuf_len(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)) != 0) goto out; /* save initial signature and hostkey */ if ((kex->flags & KEX_INITIAL) != 0) { if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if ((kex->initial_sig = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0) goto out; kex->initial_hostkey = server_host_key; server_host_key = NULL; } /* success */ out: explicit_bzero(hash, sizeof(hash)); DH_free(kex->dh); kex->dh = NULL; BN_clear_free(dh_server_pub); sshbuf_free(shared_secret); sshkey_free(server_host_key); sshbuf_free(tmp); sshbuf_free(server_host_key_blob); free(signature); return r; } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/kexgexs.c100644 001750 001750 0000000003614775415623 0014776xustar0030 atime=1744182234.572094859 openssh-10.0p1/kexgexs.c010064400017500001750000000145341477541562300133700ustar00djmdjm/* $OpenBSD: kexgexs.c,v 1.47 2024/05/17 00:30:23 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * 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 #include #include #include #include #include "openbsd-compat/openssl-compat.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" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "dispatch.h" #include "ssherr.h" #include "sshbuf.h" #include "misc.h" 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, &input_kex_dh_gex_request); debug("expecting SSH2_MSG_KEX_DH_GEX_REQUEST"); return 0; } static int input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; int r; u_int min = 0, max = 0, nbits = 0; const BIGNUM *dh_p, *dh_g; debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, &kex_protocol_error); if ((r = sshpkt_get_u32(ssh, &min)) != 0 || (r = sshpkt_get_u32(ssh, &nbits)) != 0 || (r = sshpkt_get_u32(ssh, &max)) != 0 || (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 < DH_GRP_MIN) { r = SSH_ERR_DH_GEX_OUT_OF_RANGE; goto out; } /* Contact privileged parent */ kex->dh = mm_choose_dh(min, nbits, max); if (kex->dh == NULL) { (void)sshpkt_disconnect(ssh, "no matching DH grp found"); r = SSH_ERR_ALLOC_FAIL; 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, dh_p)) != 0 || (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; /* Compute our exchange value in parallel with the client */ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) goto out; 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; out: return r; } static int input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; 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 *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, hashlen; int r; debug("SSH2_MSG_KEX_DH_GEX_INIT received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &kex_protocol_error); if ((r = kex_load_hostkey(ssh, &server_host_private, &server_host_public)) != 0) goto out; /* key, cert */ if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; if ((shared_secret = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } 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 ((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, kex->server_version, kex->peer, kex->my, server_host_key_blob, kex->min, kex->nbits, kex->max, dh_p, dh_g, dh_client_pub, pub_key, sshbuf_ptr(shared_secret), sshbuf_len(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, DH pubkey 'f' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || (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(ssh, hash, hashlen, shared_secret)) != 0 || (r = kex_send_newkeys(ssh)) != 0) goto out; /* retain copy of hostkey used at initial KEX */ if (kex->initial_hostkey == NULL && (r = sshkey_from_private(server_host_public, &kex->initial_hostkey)) != 0) goto out; /* success */ out: explicit_bzero(hash, sizeof(hash)); DH_free(kex->dh); kex->dh = NULL; BN_clear_free(dh_client_pub); sshbuf_free(shared_secret); sshbuf_free(server_host_key_blob); free(signature); return r; } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/kexmlkem768x25519.c100644 001750 001750 0000000003614775415623 0016200xustar0030 atime=1744182234.573071046 openssh-10.0p1/kexmlkem768x25519.c010064400017500001750000000217561477541562300145760ustar00djmdjm/* $OpenBSD: kexmlkem768x25519.c,v 1.2 2024/10/27 02:06:59 djm Exp $ */ /* * Copyright (c) 2023 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include #ifdef HAVE_ENDIAN_H # include #endif #include "sshkey.h" #include "kex.h" #include "sshbuf.h" #include "digest.h" #include "ssherr.h" #include "log.h" #ifdef USE_MLKEM768X25519 #include "libcrux_mlkem768_sha3.h" int kex_kem_mlkem768x25519_keypair(struct kex *kex) { struct sshbuf *buf = NULL; u_char rnd[LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN], *cp = NULL; size_t need; int r = SSH_ERR_INTERNAL_ERROR; struct libcrux_mlkem768_keypair keypair; if ((buf = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; need = crypto_kem_mlkem768_PUBLICKEYBYTES + CURVE25519_SIZE; if ((r = sshbuf_reserve(buf, need, &cp)) != 0) goto out; arc4random_buf(rnd, sizeof(rnd)); keypair = libcrux_ml_kem_mlkem768_portable_generate_key_pair(rnd); memcpy(cp, keypair.pk.value, crypto_kem_mlkem768_PUBLICKEYBYTES); memcpy(kex->mlkem768_client_key, keypair.sk.value, sizeof(kex->mlkem768_client_key)); #ifdef DEBUG_KEXECDH dump_digest("client public key mlkem768:", cp, crypto_kem_mlkem768_PUBLICKEYBYTES); #endif cp += crypto_kem_mlkem768_PUBLICKEYBYTES; kexc25519_keygen(kex->c25519_client_key, cp); #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); #endif /* success */ r = 0; kex->client_pub = buf; buf = NULL; out: explicit_bzero(&keypair, sizeof(keypair)); explicit_bzero(rnd, sizeof(rnd)); sshbuf_free(buf); return r; } int kex_kem_mlkem768x25519_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 rnd[LIBCRUX_ML_KEM_ENC_PRNG_LEN]; u_char server_pub[CURVE25519_SIZE], server_key[CURVE25519_SIZE]; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t need; int r = SSH_ERR_INTERNAL_ERROR; struct libcrux_mlkem768_enc_result enc; struct libcrux_mlkem768_pk mlkem_pub; *server_blobp = NULL; *shared_secretp = NULL; memset(&mlkem_pub, 0, sizeof(mlkem_pub)); /* client_blob contains both KEM and ECDH client pubkeys */ need = crypto_kem_mlkem768_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 mlkem768:", client_pub, crypto_kem_mlkem768_PUBLICKEYBYTES); dump_digest("client public key 25519:", client_pub + crypto_kem_mlkem768_PUBLICKEYBYTES, CURVE25519_SIZE); #endif /* check public key validity */ memcpy(mlkem_pub.value, client_pub, crypto_kem_mlkem768_PUBLICKEYBYTES); if (!libcrux_ml_kem_mlkem768_portable_validate_public_key(&mlkem_pub)) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } /* 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; } /* allocate space for encrypted KEM key and ECDH pub key */ if ((server_blob = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* generate and encrypt KEM key with client key */ arc4random_buf(rnd, sizeof(rnd)); enc = libcrux_ml_kem_mlkem768_portable_encapsulate(&mlkem_pub, rnd); /* generate ECDH key pair, store server pubkey after ciphertext */ kexc25519_keygen(server_key, server_pub); if ((r = sshbuf_put(buf, enc.snd, sizeof(enc.snd))) != 0 || (r = sshbuf_put(server_blob, enc.fst.value, sizeof(enc.fst.value))) != 0 || (r = sshbuf_put(server_blob, server_pub, sizeof(server_pub))) != 0) goto out; /* append ECDH shared key */ client_pub += crypto_kem_mlkem768_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:", enc.fst.value, sizeof(enc.fst.value)); dump_digest("server kem key:", enc.snd, sizeof(enc.snd)); 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 /* success */ r = 0; *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)); explicit_bzero(rnd, sizeof(rnd)); explicit_bzero(&enc, sizeof(enc)); sshbuf_free(server_blob); sshbuf_free(buf); return r; } int kex_kem_mlkem768x25519_dec(struct kex *kex, const struct sshbuf *server_blob, struct sshbuf **shared_secretp) { struct sshbuf *buf = NULL; u_char mlkem_key[crypto_kem_mlkem768_BYTES]; const u_char *ciphertext, *server_pub; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t need; int r; struct libcrux_mlkem768_sk mlkem_priv; struct libcrux_mlkem768_ciphertext mlkem_ciphertext; *shared_secretp = NULL; memset(&mlkem_priv, 0, sizeof(mlkem_priv)); memset(&mlkem_ciphertext, 0, sizeof(mlkem_ciphertext)); need = crypto_kem_mlkem768_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_mlkem768_CIPHERTEXTBYTES; /* hash concatenation of KEM key and ECDH shared key */ if ((buf = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(mlkem_priv.value, kex->mlkem768_client_key, sizeof(kex->mlkem768_client_key)); memcpy(mlkem_ciphertext.value, ciphertext, sizeof(mlkem_ciphertext.value)); #ifdef DEBUG_KEXECDH dump_digest("server cipher text:", mlkem_ciphertext.value, sizeof(mlkem_ciphertext.value)); dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE); #endif libcrux_ml_kem_mlkem768_portable_decapsulate(&mlkem_priv, &mlkem_ciphertext, mlkem_key); if ((r = sshbuf_put(buf, mlkem_key, sizeof(mlkem_key))) != 0) goto out; 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:", mlkem_key, sizeof(mlkem_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 /* success */ r = 0; *shared_secretp = buf; buf = NULL; out: explicit_bzero(hash, sizeof(hash)); explicit_bzero(&mlkem_priv, sizeof(mlkem_priv)); explicit_bzero(&mlkem_ciphertext, sizeof(mlkem_ciphertext)); explicit_bzero(mlkem_key, sizeof(mlkem_key)); sshbuf_free(buf); return r; } #else /* USE_MLKEM768X25519 */ int kex_kem_mlkem768x25519_keypair(struct kex *kex) { return SSH_ERR_SIGN_ALG_UNSUPPORTED; } int kex_kem_mlkem768x25519_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { return SSH_ERR_SIGN_ALG_UNSUPPORTED; } int kex_kem_mlkem768x25519_dec(struct kex *kex, const struct sshbuf *server_blob, struct sshbuf **shared_secretp) { return SSH_ERR_SIGN_ALG_UNSUPPORTED; } #endif /* USE_MLKEM768X25519 */ openssh-10.0p1/PaxHeaders.10889/kexsntrup761x25519.c100644 001750 001750 0000000003614775415623 0016417xustar0030 atime=1744182234.573071046 openssh-10.0p1/kexsntrup761x25519.c010064400017500001750000000173301477541562300150060ustar00djmdjm/* $OpenBSD: kexsntrup761x25519.c,v 1.3 2024/09/15 02:20:51 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" #ifdef USE_SNTRUP761X25519 #include #include #include #include #include "sshkey.h" #include "kex.h" #include "sshbuf.h" #include "digest.h" #include "ssherr.h" volatile crypto_int16 crypto_int16_optblocker = 0; volatile crypto_int32 crypto_int32_optblocker = 0; volatile crypto_int64 crypto_int64_optblocker = 0; int kex_kem_sntrup761x25519_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_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE; if ((r = sshbuf_reserve(buf, need, &cp)) != 0) goto out; crypto_kem_sntrup761_keypair(cp, kex->sntrup761_client_key); #ifdef DEBUG_KEXECDH dump_digest("client public key sntrup761:", cp, crypto_kem_sntrup761_PUBLICKEYBYTES); #endif cp += crypto_kem_sntrup761_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_sntrup761x25519_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_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE; if (sshbuf_len(client_blob) != need) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } client_pub = sshbuf_ptr(client_blob); #ifdef DEBUG_KEXECDH dump_digest("client public key sntrup761:", client_pub, crypto_kem_sntrup761_PUBLICKEYBYTES); dump_digest("client public key 25519:", client_pub + crypto_kem_sntrup761_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_sntrup761_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_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE; if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0) goto out; /* generate and encrypt KEM key with client key */ crypto_kem_sntrup761_enc(ciphertext, kem_key, client_pub); /* generate ECDH key pair, store server pubkey after ciphertext */ server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES; kexc25519_keygen(server_key, server_pub); /* append ECDH shared key */ client_pub += crypto_kem_sntrup761_PUBLICKEYBYTES; if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0) goto out; if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) goto out; #ifdef DEBUG_KEXECDH dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); dump_digest("server cipher text:", ciphertext, crypto_kem_sntrup761_CIPHERTEXTBYTES); dump_digest("server kem key:", kem_key, crypto_kem_sntrup761_BYTES); dump_digest("concatenation of KEM key and ECDH shared key:", sshbuf_ptr(buf), sshbuf_len(buf)); #endif /* 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_sntrup761x25519_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_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE; if (sshbuf_len(server_blob) != need) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } ciphertext = sshbuf_ptr(server_blob); server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES; #ifdef DEBUG_KEXECDH dump_digest("server cipher text:", ciphertext, crypto_kem_sntrup761_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_sntrup761_BYTES, &kem_key)) != 0) goto out; decoded = crypto_kem_sntrup761_dec(kem_key, ciphertext, kex->sntrup761_client_key); if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub, buf, 1)) < 0) goto out; if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) goto out; #ifdef DEBUG_KEXECDH dump_digest("client kem key:", kem_key, crypto_kem_sntrup761_BYTES); 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; } #else #include "ssherr.h" struct kex; struct sshbuf; struct sshkey; int kex_kem_sntrup761x25519_keypair(struct kex *kex) { return SSH_ERR_SIGN_ALG_UNSUPPORTED; } int kex_kem_sntrup761x25519_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { return SSH_ERR_SIGN_ALG_UNSUPPORTED; } int kex_kem_sntrup761x25519_dec(struct kex *kex, const struct sshbuf *server_blob, struct sshbuf **shared_secretp) { return SSH_ERR_SIGN_ALG_UNSUPPORTED; } #endif /* USE_SNTRUP761X25519 */ openssh-10.0p1/PaxHeaders.10889/krl.c100644 001750 001750 0000000003614775415623 0014110xustar0030 atime=1744182234.573071046 openssh-10.0p1/krl.c010064400017500001750000001072161477541562300125020ustar00djmdjm/* $OpenBSD: krl.c,v 1.60 2025/02/18 08:02:48 djm Exp $ */ /* * Copyright (c) 2012 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include "sshbuf.h" #include "ssherr.h" #include "sshkey.h" #include "authfile.h" #include "misc.h" #include "log.h" #include "digest.h" #include "bitmap.h" #include "utf8.h" #include "krl.h" /* #define DEBUG_KRL */ #ifdef DEBUG_KRL # define KRL_DBG(x) debug3_f x #else # define KRL_DBG(x) #endif /* * Trees of revoked serial numbers, key IDs and keys. This allows * quick searching, querying and producing lists in canonical order. */ /* Tree of serial numbers. XXX make smarter: really need a real sparse bitmap */ struct revoked_serial { u_int64_t lo, hi; RB_ENTRY(revoked_serial) tree_entry; }; static int serial_cmp(struct revoked_serial *a, struct revoked_serial *b); RB_HEAD(revoked_serial_tree, revoked_serial); RB_GENERATE_STATIC(revoked_serial_tree, revoked_serial, tree_entry, serial_cmp) /* Tree of key IDs */ struct revoked_key_id { char *key_id; RB_ENTRY(revoked_key_id) tree_entry; }; static int key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b); RB_HEAD(revoked_key_id_tree, revoked_key_id); RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp) /* Tree of blobs (used for keys and fingerprints) */ struct revoked_blob { u_char *blob; size_t len; RB_ENTRY(revoked_blob) tree_entry; }; static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b); RB_HEAD(revoked_blob_tree, revoked_blob); RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp) /* Tracks revoked certs for a single CA */ struct revoked_certs { struct sshkey *ca_key; struct revoked_serial_tree revoked_serials; struct revoked_key_id_tree revoked_key_ids; TAILQ_ENTRY(revoked_certs) entry; }; TAILQ_HEAD(revoked_certs_list, revoked_certs); struct ssh_krl { u_int64_t krl_version; u_int64_t generated_date; u_int64_t flags; 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; }; /* Return equal if a and b overlap */ static int serial_cmp(struct revoked_serial *a, struct revoked_serial *b) { if (a->hi >= b->lo && a->lo <= b->hi) return 0; return a->lo < b->lo ? -1 : 1; } static int key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b) { return strcmp(a->key_id, b->key_id); } static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b) { int r; if (a->len != b->len) { if ((r = memcmp(a->blob, b->blob, MINIMUM(a->len, b->len))) != 0) return r; return a->len > b->len ? 1 : -1; } else return memcmp(a->blob, b->blob, a->len); } struct ssh_krl * ssh_krl_init(void) { struct ssh_krl *krl; if ((krl = calloc(1, sizeof(*krl))) == NULL) return NULL; RB_INIT(&krl->revoked_keys); RB_INIT(&krl->revoked_sha1s); RB_INIT(&krl->revoked_sha256s); TAILQ_INIT(&krl->revoked_certs); return krl; } static void revoked_certs_free(struct revoked_certs *rc) { struct revoked_serial *rs, *trs; struct revoked_key_id *rki, *trki; RB_FOREACH_SAFE(rs, revoked_serial_tree, &rc->revoked_serials, trs) { RB_REMOVE(revoked_serial_tree, &rc->revoked_serials, rs); free(rs); } RB_FOREACH_SAFE(rki, revoked_key_id_tree, &rc->revoked_key_ids, trki) { RB_REMOVE(revoked_key_id_tree, &rc->revoked_key_ids, rki); free(rki->key_id); free(rki); } sshkey_free(rc->ca_key); } void ssh_krl_free(struct ssh_krl *krl) { struct revoked_blob *rb, *trb; struct revoked_certs *rc, *trc; if (krl == NULL) return; free(krl->comment); RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_keys, trb) { RB_REMOVE(revoked_blob_tree, &krl->revoked_keys, rb); free(rb->blob); free(rb); } RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha1s, trb) { RB_REMOVE(revoked_blob_tree, &krl->revoked_sha1s, rb); 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); } free(krl); } void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version) { krl->krl_version = version; } int ssh_krl_set_comment(struct ssh_krl *krl, const char *comment) { free(krl->comment); if ((krl->comment = strdup(comment)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } /* * Find the revoked_certs struct for a CA key. If allow_create is set then * create a new one in the tree if one did not exist already. */ static int revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key, struct revoked_certs **rcp, int allow_create) { struct revoked_certs *rc; int r; *rcp = NULL; TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { if ((ca_key == NULL && rc->ca_key == NULL) || sshkey_equal(rc->ca_key, ca_key)) { *rcp = rc; return 0; } } if (!allow_create) return 0; /* If this CA doesn't exist in the list then add it now */ if ((rc = calloc(1, sizeof(*rc))) == NULL) return SSH_ERR_ALLOC_FAIL; if (ca_key == NULL) rc->ca_key = NULL; else if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) { free(rc); return r; } RB_INIT(&rc->revoked_serials); RB_INIT(&rc->revoked_key_ids); TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry); KRL_DBG(("new CA %s", ca_key == NULL ? "*" : sshkey_type(ca_key))); *rcp = rc; return 0; } static int insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) { struct revoked_serial rs, *ers, *crs, *irs; KRL_DBG(("insert %llu:%llu", lo, hi)); memset(&rs, 0, sizeof(rs)); rs.lo = lo; rs.hi = hi; ers = RB_NFIND(revoked_serial_tree, rt, &rs); if (ers == NULL || serial_cmp(ers, &rs) != 0) { /* No entry matches. Just insert */ if ((irs = malloc(sizeof(rs))) == NULL) return SSH_ERR_ALLOC_FAIL; memcpy(irs, &rs, sizeof(*irs)); ers = RB_INSERT(revoked_serial_tree, rt, irs); if (ers != NULL) { KRL_DBG(("bad: ers != NULL")); /* Shouldn't happen */ free(irs); return SSH_ERR_INTERNAL_ERROR; } ers = irs; } else { KRL_DBG(("overlap found %llu:%llu", ers->lo, ers->hi)); /* * The inserted entry overlaps an existing one. Grow the * existing entry. */ if (ers->lo > lo) ers->lo = lo; if (ers->hi < hi) ers->hi = hi; } /* * The inserted or revised range might overlap or abut adjacent ones; * coalesce as necessary. */ /* Check predecessors */ while ((crs = RB_PREV(revoked_serial_tree, rt, ers)) != NULL) { KRL_DBG(("pred %llu:%llu", crs->lo, crs->hi)); if (ers->lo != 0 && crs->hi < ers->lo - 1) break; /* This entry overlaps. */ if (crs->lo < ers->lo) { ers->lo = crs->lo; KRL_DBG(("pred extend %llu:%llu", ers->lo, ers->hi)); } RB_REMOVE(revoked_serial_tree, rt, crs); free(crs); } /* Check successors */ while ((crs = RB_NEXT(revoked_serial_tree, rt, ers)) != NULL) { KRL_DBG(("succ %llu:%llu", crs->lo, crs->hi)); if (ers->hi != (u_int64_t)-1 && crs->lo > ers->hi + 1) break; /* This entry overlaps. */ if (crs->hi > ers->hi) { ers->hi = crs->hi; KRL_DBG(("succ extend %llu:%llu", ers->lo, ers->hi)); } RB_REMOVE(revoked_serial_tree, rt, crs); free(crs); } KRL_DBG(("done, final %llu:%llu", ers->lo, ers->hi)); return 0; } int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const struct sshkey *ca_key, u_int64_t serial) { return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial); } int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const struct sshkey *ca_key, u_int64_t lo, u_int64_t hi) { struct revoked_certs *rc; int r; if (lo > hi || lo == 0) return SSH_ERR_INVALID_ARGUMENT; if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0) return r; return insert_serial_range(&rc->revoked_serials, lo, hi); } int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const struct sshkey *ca_key, const char *key_id) { struct revoked_key_id *rki, *erki; struct revoked_certs *rc; int r; if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0) return r; KRL_DBG(("revoke %s", key_id)); if ((rki = calloc(1, sizeof(*rki))) == NULL || (rki->key_id = strdup(key_id)) == NULL) { free(rki); return SSH_ERR_ALLOC_FAIL; } erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki); if (erki != NULL) { free(rki->key_id); free(rki); } return 0; } /* Convert "key" to a public key blob without any certificate information */ static int plain_key_blob(const struct sshkey *key, u_char **blob, size_t *blen) { struct sshkey *kcopy; int r; if ((r = sshkey_from_private(key, &kcopy)) != 0) return r; if (sshkey_is_cert(kcopy)) { if ((r = sshkey_drop_cert(kcopy)) != 0) { sshkey_free(kcopy); return r; } } r = sshkey_to_blob(kcopy, blob, blen); sshkey_free(kcopy); return r; } /* Revoke a key blob. Ownership of blob is transferred to the tree */ static int revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, size_t len) { struct revoked_blob *rb, *erb; if ((rb = calloc(1, sizeof(*rb))) == NULL) return SSH_ERR_ALLOC_FAIL; rb->blob = blob; rb->len = len; erb = RB_INSERT(revoked_blob_tree, rbt, rb); if (erb != NULL) { free(rb->blob); free(rb); } return 0; } int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key) { u_char *blob; size_t len; int r; debug3_f("revoke type %s", sshkey_type(key)); if ((r = plain_key_blob(key, &blob, &len)) != 0) return r; return revoke_blob(&krl->revoked_keys, blob, len); } static int revoke_by_hash(struct revoked_blob_tree *target, const u_char *p, size_t len) { u_char *blob; int r; /* 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 0; } int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len) { debug3_f("revoke by sha1"); 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_f("revoke by sha256"); 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_explicit(krl, key); if (key->cert->serial == 0) { return ssh_krl_revoke_cert_by_key_id(krl, key->cert->signature_key, key->cert->key_id); } else { return ssh_krl_revoke_cert_by_serial(krl, key->cert->signature_key, key->cert->serial); } } /* * Select the most compact section type to emit next in a KRL based on * the current section type, the run length of contiguous revoked serial * numbers and the gaps from the last and to the next revoked serial. * Applies a mostly-accurate bit cost model to select the section type * that will minimise the size of the resultant KRL. */ static int choose_next_state(int current_state, u_int64_t contig, int final, u_int64_t last_gap, u_int64_t next_gap, int *force_new_section) { int new_state; u_int64_t cost, cost_list, cost_range, cost_bitmap, cost_bitmap_restart; /* * Avoid unsigned overflows. * The limits are high enough to avoid confusing the calculations. */ 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. * NB. range sections only ever contain a single range, so their * switching cost is independent of the current_state. */ cost_list = cost_bitmap = cost_bitmap_restart = 0; cost_range = 8; switch (current_state) { case KRL_SECTION_CERT_SERIAL_LIST: cost_bitmap_restart = cost_bitmap = 8 + 64; break; case KRL_SECTION_CERT_SERIAL_BITMAP: cost_list = 8; cost_bitmap_restart = 8 + 64; break; case KRL_SECTION_CERT_SERIAL_RANGE: case 0: cost_bitmap_restart = cost_bitmap = 8 + 64; cost_list = 8; } /* 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 : 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; cost_bitmap = (cost_bitmap + 7) / 8; cost_bitmap_restart = (cost_bitmap_restart + 7) / 8; cost_range = (cost_range + 7) / 8; /* Now pick the best choice */ *force_new_section = 0; new_state = KRL_SECTION_CERT_SERIAL_BITMAP; cost = cost_bitmap; if (cost_range < cost) { new_state = KRL_SECTION_CERT_SERIAL_RANGE; cost = cost_range; } if (cost_list < cost) { new_state = KRL_SECTION_CERT_SERIAL_LIST; cost = cost_list; } if (cost_bitmap_restart < cost) { new_state = KRL_SECTION_CERT_SERIAL_BITMAP; *force_new_section = 1; cost = cost_bitmap_restart; } KRL_DBG(("contig %llu last_gap %llu next_gap %llu final %d, costs:" "list %llu range %llu bitmap %llu new bitmap %llu, " "selected 0x%02x%s", (long long unsigned)contig, (long long unsigned)last_gap, (long long unsigned)next_gap, final, (long long unsigned)cost_list, (long long unsigned)cost_range, (long long unsigned)cost_bitmap, (long long unsigned)cost_bitmap_restart, new_state, *force_new_section ? " restart" : "")); return new_state; } static int put_bitmap(struct sshbuf *buf, struct bitmap *bitmap) { size_t len; u_char *blob; int r; len = bitmap_nbytes(bitmap); if ((blob = malloc(len)) == NULL) return SSH_ERR_ALLOC_FAIL; if (bitmap_to_string(bitmap, blob, len) != 0) { free(blob); return SSH_ERR_INTERNAL_ERROR; } r = sshbuf_put_bignum2_bytes(buf, blob, len); free(blob); return r; } /* Generate a KRL_SECTION_CERTIFICATES KRL section */ static int revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) { int final, force_new_sect, r = SSH_ERR_INTERNAL_ERROR; u_int64_t i, contig, gap, last = 0, bitmap_start = 0; struct revoked_serial *rs, *nrs; struct revoked_key_id *rki; int next_state, state = 0; struct sshbuf *sect; struct bitmap *bitmap = NULL; if ((sect = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* Store the header: optional CA scope key, reserved */ if (rc->ca_key == NULL) { if ((r = sshbuf_put_string(buf, NULL, 0)) != 0) goto out; } else { if ((r = sshkey_puts(rc->ca_key, buf)) != 0) goto out; } if ((r = sshbuf_put_string(buf, NULL, 0)) != 0) goto out; /* Store the revoked serials. */ for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials); rs != NULL; rs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs)) { KRL_DBG(("serial %llu:%llu state 0x%02x", (long long unsigned)rs->lo, (long long unsigned)rs->hi, state)); /* Check contiguous length and gap to next section (if any) */ nrs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs); final = nrs == NULL; gap = nrs == NULL ? 0 : nrs->lo - rs->hi; contig = 1 + (rs->hi - rs->lo); /* Choose next state based on these */ next_state = choose_next_state(state, contig, final, state == 0 ? 0 : rs->lo - last, gap, &force_new_sect); /* * If the current section is a range section or has a different * type to the next section, then finish it off now. */ if (state != 0 && (force_new_sect || next_state != state || state == KRL_SECTION_CERT_SERIAL_RANGE)) { KRL_DBG(("finish state 0x%02x", state)); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: break; case KRL_SECTION_CERT_SERIAL_BITMAP: if ((r = put_bitmap(sect, bitmap)) != 0) goto out; bitmap_free(bitmap); bitmap = NULL; break; } if ((r = sshbuf_put_u8(buf, state)) != 0 || (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; sshbuf_reset(sect); } /* If we are starting a new section then prepare it now */ if (next_state != state || force_new_sect) { KRL_DBG(("start state 0x%02x", next_state)); state = next_state; sshbuf_reset(sect); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: break; case KRL_SECTION_CERT_SERIAL_BITMAP: if ((bitmap = bitmap_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } bitmap_start = rs->lo; if ((r = sshbuf_put_u64(sect, bitmap_start)) != 0) goto out; break; } } /* Perform section-specific processing */ switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: for (i = 0; i < contig; i++) { if ((r = sshbuf_put_u64(sect, rs->lo + i)) != 0) goto out; } break; case KRL_SECTION_CERT_SERIAL_RANGE: if ((r = sshbuf_put_u64(sect, rs->lo)) != 0 || (r = sshbuf_put_u64(sect, rs->hi)) != 0) goto out; break; case KRL_SECTION_CERT_SERIAL_BITMAP: if (rs->lo - bitmap_start > INT_MAX) { r = SSH_ERR_INVALID_FORMAT; error_f("insane bitmap gap"); goto out; } for (i = 0; i < contig; i++) { if (bitmap_set_bit(bitmap, rs->lo + i - bitmap_start) != 0) { r = SSH_ERR_ALLOC_FAIL; goto out; } } break; } last = rs->hi; } /* Flush the remaining section, if any */ if (state != 0) { KRL_DBG(("serial final flush for state 0x%02x", state)); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: break; case KRL_SECTION_CERT_SERIAL_BITMAP: if ((r = put_bitmap(sect, bitmap)) != 0) goto out; bitmap_free(bitmap); bitmap = NULL; break; } if ((r = sshbuf_put_u8(buf, state)) != 0 || (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } KRL_DBG(("serial done ")); /* Now output a section for any revocations by key ID */ sshbuf_reset(sect); RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { KRL_DBG(("key ID %s", rki->key_id)); if ((r = sshbuf_put_cstring(sect, rki->key_id)) != 0) goto out; } if (sshbuf_len(sect) != 0) { if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERT_KEY_ID)) != 0 || (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } r = 0; out: bitmap_free(bitmap); sshbuf_free(sect); return r; } int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf) { int r = SSH_ERR_INTERNAL_ERROR; struct revoked_certs *rc; struct revoked_blob *rb; struct sshbuf *sect; u_char *sblob = NULL; if (krl->generated_date == 0) krl->generated_date = time(NULL); if ((sect = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* Store the header */ 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->flags)) != 0 || (r = sshbuf_put_string(buf, NULL, 0)) != 0 || (r = sshbuf_put_cstring(buf, krl->comment)) != 0) goto out; /* Store sections for revoked certificates */ TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { sshbuf_reset(sect); if ((r = revoked_certs_generate(rc, sect)) != 0) goto out; if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERTIFICATES)) != 0 || (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } /* Finally, output sections for revocations by public key/hash */ sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { KRL_DBG(("key len %zu ", 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_EXPLICIT_KEY)) != 0 || (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { KRL_DBG(("hash len %zu ", 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_SHA1)) != 0 || (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) { KRL_DBG(("hash len %zu ", 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; } /* success */ r = 0; out: free(sblob); sshbuf_free(sect); return r; } static void format_timestamp(u_int64_t timestamp, char *ts, size_t nts) { time_t t; struct tm *tm; t = timestamp; tm = localtime(&t); if (tm == NULL) strlcpy(ts, "", nts); else { *ts = '\0'; strftime(ts, nts, "%Y%m%dT%H%M%S", tm); } } static int cert_extension_subsection(struct sshbuf *subsect, struct ssh_krl *krl) { int r = SSH_ERR_INTERNAL_ERROR; u_char critical = 1; struct sshbuf *value = NULL; char *name = NULL; if ((r = sshbuf_get_cstring(subsect, &name, NULL)) != 0 || (r = sshbuf_get_u8(subsect, &critical)) != 0 || (r = sshbuf_froms(subsect, &value)) != 0) { debug_fr(r, "parse"); error("KRL has invalid certificate extension subsection"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(subsect) != 0) { error("KRL has invalid certificate extension subsection: " "trailing data"); r = SSH_ERR_INVALID_FORMAT; goto out; } debug_f("cert extension %s critical %u len %zu", name, critical, sshbuf_len(value)); /* no extensions are currently supported */ if (critical) { error("KRL contains unsupported critical certificate " "subsection \"%s\"", name); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } /* success */ r = 0; out: free(name); sshbuf_free(value); return r; } static int parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl) { int r = SSH_ERR_INTERNAL_ERROR; u_char type; const u_char *blob; size_t blen, nbits; struct sshbuf *subsect = NULL; u_int64_t serial, serial_lo, serial_hi; struct bitmap *bitmap = NULL; char *key_id = NULL; struct sshkey *ca_key = NULL; if ((subsect = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* Header: key, reserved */ if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 || (r = sshbuf_skip_string(buf)) != 0) goto out; if (blen != 0 && (r = sshkey_from_blob(blob, blen, &ca_key)) != 0) goto out; while (sshbuf_len(buf) > 0) { sshbuf_free(subsect); subsect = NULL; if ((r = sshbuf_get_u8(buf, &type)) != 0 || (r = sshbuf_froms(buf, &subsect)) != 0) goto out; KRL_DBG(("subsection type 0x%02x", type)); /* sshbuf_dump(subsect, stderr); */ switch (type) { case KRL_SECTION_CERT_SERIAL_LIST: while (sshbuf_len(subsect) > 0) { if ((r = sshbuf_get_u64(subsect, &serial)) != 0) goto out; if ((r = ssh_krl_revoke_cert_by_serial(krl, ca_key, serial)) != 0) goto out; } break; case KRL_SECTION_CERT_SERIAL_RANGE: if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 || (r = sshbuf_get_u64(subsect, &serial_hi)) != 0) goto out; if ((r = ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial_lo, serial_hi)) != 0) goto out; break; case KRL_SECTION_CERT_SERIAL_BITMAP: if ((bitmap = bitmap_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 || (r = sshbuf_get_bignum2_bytes_direct(subsect, &blob, &blen)) != 0) goto out; if (bitmap_from_string(bitmap, blob, blen) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } nbits = bitmap_nbits(bitmap); for (serial = 0; serial < (u_int64_t)nbits; serial++) { if (serial > 0 && serial_lo + serial == 0) { error_f("bitmap wraps u64"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (!bitmap_test_bit(bitmap, serial)) continue; if ((r = ssh_krl_revoke_cert_by_serial(krl, ca_key, serial_lo + serial)) != 0) goto out; } bitmap_free(bitmap); bitmap = NULL; break; case KRL_SECTION_CERT_KEY_ID: while (sshbuf_len(subsect) > 0) { if ((r = sshbuf_get_cstring(subsect, &key_id, NULL)) != 0) goto out; if ((r = ssh_krl_revoke_cert_by_key_id(krl, ca_key, key_id)) != 0) goto out; free(key_id); key_id = NULL; } break; case KRL_SECTION_CERT_EXTENSION: if ((r = cert_extension_subsection(subsect, krl)) != 0) goto out; break; default: error("Unsupported KRL certificate section %u", type); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(subsect) > 0) { error("KRL certificate section contains unparsed data"); r = SSH_ERR_INVALID_FORMAT; goto out; } } r = 0; out: if (bitmap != NULL) bitmap_free(bitmap); free(key_id); sshkey_free(ca_key); sshbuf_free(subsect); 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_f("bad length"); free(rdata); return SSH_ERR_INVALID_FORMAT; } if ((r = revoke_blob(target_tree, rdata, rlen)) != 0) { free(rdata); return r; } } return 0; } static int extension_section(struct sshbuf *sect, struct ssh_krl *krl) { int r = SSH_ERR_INTERNAL_ERROR; u_char critical = 1; struct sshbuf *value = NULL; char *name = NULL; if ((r = sshbuf_get_cstring(sect, &name, NULL)) != 0 || (r = sshbuf_get_u8(sect, &critical)) != 0 || (r = sshbuf_froms(sect, &value)) != 0) { debug_fr(r, "parse"); error("KRL has invalid extension section"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(sect) != 0) { error("KRL has invalid extension section: trailing data"); r = SSH_ERR_INVALID_FORMAT; goto out; } debug_f("extension %s critical %u len %zu", name, critical, sshbuf_len(value)); /* no extensions are currently supported */ if (critical) { error("KRL contains unsupported critical section \"%s\"", name); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } /* success */ r = 0; out: free(name); sshbuf_free(value); return r; } /* Attempt to parse a KRL */ int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp) { struct sshbuf *copy = NULL, *sect = NULL; struct ssh_krl *krl = NULL; char timestamp[64]; int r = SSH_ERR_INTERNAL_ERROR; u_char type; u_int format_version; *krlp = NULL; /* KRL must begin with magic string */ if ((r = sshbuf_cmp(buf, 0, KRL_MAGIC, sizeof(KRL_MAGIC) - 1)) != 0) { debug2_f("bad KRL magic header"); return SSH_ERR_KRL_BAD_MAGIC; } if ((krl = ssh_krl_init()) == NULL) { r = SSH_ERR_ALLOC_FAIL; error_f("alloc failed"); goto out; } /* Don't modify buffer */ if ((copy = sshbuf_fromb(buf)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_consume(copy, sizeof(KRL_MAGIC) - 1)) != 0 || (r = sshbuf_get_u32(copy, &format_version)) != 0) goto out; if (format_version != KRL_FORMAT_VERSION) { error_f("unsupported KRL format version %u", format_version); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_u64(copy, &krl->krl_version)) != 0 || (r = sshbuf_get_u64(copy, &krl->generated_date)) != 0 || (r = sshbuf_get_u64(copy, &krl->flags)) != 0 || (r = sshbuf_skip_string(copy)) != 0 || (r = sshbuf_get_cstring(copy, &krl->comment, NULL)) != 0) { error_fr(r, "parse KRL header"); goto out; } format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); debug("KRL version %llu generated at %s%s%s", (long long unsigned)krl->krl_version, timestamp, *krl->comment ? ": " : "", krl->comment); /* Parse and load the KRL sections. */ while (sshbuf_len(copy) > 0) { sshbuf_free(sect); sect = NULL; if ((r = sshbuf_get_u8(copy, &type)) != 0 || (r = sshbuf_froms(copy, §)) != 0) goto out; KRL_DBG(("section 0x%02x", type)); switch (type) { case KRL_SECTION_CERTIFICATES: if ((r = parse_revoked_certs(sect, krl)) != 0) 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: 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_EXTENSION: if ((r = extension_section(sect, krl)) != 0) goto out; break; case KRL_SECTION_SIGNATURE: /* Handled above, but still need to stay in synch */ sshbuf_free(sect); sect = NULL; if ((r = sshbuf_skip_string(copy)) != 0) goto out; break; default: error("Unsupported KRL section %u", type); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sect != NULL && sshbuf_len(sect) > 0) { error("KRL section contains unparsed data"); r = SSH_ERR_INVALID_FORMAT; goto out; } } /* Success */ *krlp = krl; r = 0; out: if (r != 0) ssh_krl_free(krl); sshbuf_free(copy); sshbuf_free(sect); return r; } /* Checks certificate serial number and key ID revocation */ static int is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc) { struct revoked_serial rs, *ers; struct revoked_key_id rki, *erki; /* Check revocation by cert key ID */ memset(&rki, 0, sizeof(rki)); rki.key_id = key->cert->key_id; erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki); if (erki != NULL) { KRL_DBG(("revoked by key ID")); return SSH_ERR_KEY_REVOKED; } /* * Zero serials numbers are ignored (it's the default when the * CA doesn't specify one). */ if (key->cert->serial == 0) return 0; memset(&rs, 0, sizeof(rs)); rs.lo = rs.hi = key->cert->serial; ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs); if (ers != NULL) { KRL_DBG(("revoked serial %llu matched %llu:%llu", key->cert->serial, ers->lo, ers->hi)); return SSH_ERR_KEY_REVOKED; } return 0; } /* Checks whether a given key/cert is revoked. Does not check its CA */ static int is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) { struct revoked_blob rb, *erb; struct revoked_certs *rc; int r; /* Check explicitly revoked hashes first */ memset(&rb, 0, sizeof(rb)); if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, &rb.blob, &rb.len)) != 0) return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); free(rb.blob); if (erb != NULL) { KRL_DBG(("revoked by key SHA1")); 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(("revoked by key SHA256")); return SSH_ERR_KEY_REVOKED; } /* Next, explicit keys */ memset(&rb, 0, sizeof(rb)); if ((r = plain_key_blob(key, &rb.blob, &rb.len)) != 0) return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); free(rb.blob); if (erb != NULL) { KRL_DBG(("revoked by explicit key")); return SSH_ERR_KEY_REVOKED; } if (!sshkey_is_cert(key)) return 0; /* Check cert revocation for the specified CA */ if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key, &rc, 0)) != 0) return r; if (rc != NULL) { if ((r = is_cert_revoked(key, rc)) != 0) return r; } /* Check cert revocation for the wildcard CA */ if ((r = revoked_certs_for_ca_key(krl, NULL, &rc, 0)) != 0) return r; if (rc != NULL) { if ((r = is_cert_revoked(key, rc)) != 0) return r; } KRL_DBG(("%llu no match", key->cert->serial)); return 0; } int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key) { int r; KRL_DBG(("checking key")); if ((r = is_key_revoked(krl, key)) != 0) return r; if (sshkey_is_cert(key)) { debug2_f("checking CA key"); if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0) return r; } KRL_DBG(("key okay")); return 0; } int 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; if (path == NULL) return 0; if ((r = sshbuf_load_file(path, &krlbuf)) != 0) { oerrno = errno; goto out; } if ((r = ssh_krl_from_blob(krlbuf, &krl)) != 0) goto out; debug2_f("checking KRL %s", path); r = ssh_krl_check_key(krl, key); out: sshbuf_free(krlbuf); ssh_krl_free(krl); if (r != 0) errno = oerrno; return r; } int krl_dump(struct ssh_krl *krl, FILE *f) { struct sshkey *key = NULL; struct revoked_blob *rb; struct revoked_certs *rc; struct revoked_serial *rs; struct revoked_key_id *rki; int r, ret = 0; char *fp, timestamp[64]; /* Try to print in a KRL spec-compatible format */ format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); fprintf(f, "# KRL version %llu\n", (unsigned long long)krl->krl_version); fprintf(f, "# Generated at %s\n", timestamp); if (krl->comment != NULL && *krl->comment != '\0') { r = INT_MAX; asmprintf(&fp, INT_MAX, &r, "%s", krl->comment); fprintf(f, "# Comment: %s\n", fp); free(fp); } fputc('\n', f); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { if ((r = sshkey_from_blob(rb->blob, rb->len, &key)) != 0) { ret = SSH_ERR_INVALID_FORMAT; error_r(r, "parse KRL key"); continue; } if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) { ret = SSH_ERR_INVALID_FORMAT; error("sshkey_fingerprint failed"); continue; } fprintf(f, "hash: %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; } openssh-10.0p1/PaxHeaders.10889/krl.h100644 001750 001750 0000000003614775415623 0014115xustar0030 atime=1744182234.573071046 openssh-10.0p1/krl.h010064400017500001750000000052601477541562300125030ustar00djmdjm/* * Copyright (c) 2012 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* $OpenBSD: krl.h,v 1.10 2023/07/17 04:01:10 djm Exp $ */ #ifndef _KRL_H #define _KRL_H /* Functions to manage key revocation lists */ #define KRL_MAGIC "SSHKRL\n\0" #define KRL_FORMAT_VERSION 1 /* KRL section types */ #define KRL_SECTION_CERTIFICATES 1 #define KRL_SECTION_EXPLICIT_KEY 2 #define KRL_SECTION_FINGERPRINT_SHA1 3 #define KRL_SECTION_SIGNATURE 4 #define KRL_SECTION_FINGERPRINT_SHA256 5 #define KRL_SECTION_EXTENSION 255 /* KRL_SECTION_CERTIFICATES subsection types */ #define KRL_SECTION_CERT_SERIAL_LIST 0x20 #define KRL_SECTION_CERT_SERIAL_RANGE 0x21 #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 #define KRL_SECTION_CERT_KEY_ID 0x23 #define KRL_SECTION_CERT_EXTENSION 0x39 struct sshkey; struct sshbuf; 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); 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); int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const struct sshkey *ca_key, u_int64_t lo, u_int64_t hi); 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 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); int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp); 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 */ openssh-10.0p1/PaxHeaders.10889/libcrux_mlkem768_sha3.h100644 001750 001750 0000000003614775415623 0017345xustar0030 atime=1744182234.578929748 openssh-10.0p1/libcrux_mlkem768_sha3.h010064400017500001750000016052261477541562300157440ustar00djmdjm/* $OpenBSD: libcrux_mlkem768_sha3.h,v 1.2 2024/10/27 02:06:01 djm Exp $ */ /* Extracted from libcrux revision 84c5d87b3092c59294345aa269ceefe0eb97cc35 */ /* * MIT License * * Copyright (c) 2024 Cryspen * * 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 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #if !defined(__GNUC__) || (__GNUC__ < 2) # define __attribute__(x) #endif #define KRML_MUSTINLINE inline #define KRML_NOINLINE __attribute__((noinline, unused)) #define KRML_HOST_EPRINTF(...) #define KRML_HOST_EXIT(x) fatal_f("internal error") /* from libcrux/libcrux-ml-kem/cg/eurydice_glue.h */ /* * SPDX-FileCopyrightText: 2024 Eurydice Contributors * SPDX-FileCopyrightText: 2024 Cryspen Sarl * * SPDX-License-Identifier: MIT or Apache-2.0 */ #pragma once #if defined(__cplusplus) extern "C" { #endif // SLICES, ARRAYS, ETC. // The MSVC C++ compiler does not support compound literals. // This CLITERAL is used to turn `(type){...}` into `type{...}` when using a C++ // compiler. #if defined(__cplusplus) #define CLITERAL(type) type #else #define CLITERAL(type) (type) #endif // We represent a slice as a pair of an (untyped) pointer, along with the length // of the slice, i.e. the number of elements in the slice (this is NOT the // number of bytes). This design choice has two important consequences. // - if you need to use `ptr`, you MUST cast it to a proper type *before* // performing pointer // arithmetic on it (remember that C desugars pointer arithmetic based on the // type of the address) // - if you need to use `len` for a C style function (e.g. memcpy, memcmp), you // need to multiply it // by sizeof t, where t is the type of the elements. // // Empty slices have `len == 0` and `ptr` always needs to be valid pointer that // is not NULL (otherwise the construction in EURYDICE_SLICE computes `NULL + // start`). typedef struct { void *ptr; size_t len; } Eurydice_slice; // Helper macro to create a slice out of a pointer x, a start index in x // (included), and an end index in x (excluded). The argument x must be suitably // cast to something that can decay (see remark above about how pointer // arithmetic works in C), meaning either pointer or array type. #define EURYDICE_SLICE(x, start, end) \ (CLITERAL(Eurydice_slice){.ptr = (void *)(x + start), .len = end - start}) #define EURYDICE_SLICE_LEN(s, _) s.len // This macro is a pain because in case the dereferenced element type is an // array, you cannot simply write `t x` as it would yield `int[4] x` instead, // which is NOT correct C syntax, so we add a dedicated phase in Eurydice that // adds an extra argument to this macro at the last minute so that we have the // correct type of *pointers* to elements. #define Eurydice_slice_index(s, i, t, t_ptr_t) (((t_ptr_t)s.ptr)[i]) #define Eurydice_slice_subslice(s, r, t, _) \ EURYDICE_SLICE((t *)s.ptr, r.start, r.end) // Variant for when the start and end indices are statically known (i.e., the // range argument `r` is a literal). #define Eurydice_slice_subslice2(s, start, end, t) \ EURYDICE_SLICE((t *)s.ptr, start, end) #define Eurydice_slice_subslice_to(s, subslice_end_pos, t, _) \ EURYDICE_SLICE((t *)s.ptr, 0, subslice_end_pos) #define Eurydice_slice_subslice_from(s, subslice_start_pos, t, _) \ EURYDICE_SLICE((t *)s.ptr, subslice_start_pos, s.len) #define Eurydice_array_to_slice(end, x, t) \ EURYDICE_SLICE(x, 0, \ end) /* x is already at an array type, no need for cast */ #define Eurydice_array_to_subslice(_arraylen, x, r, t, _) \ EURYDICE_SLICE((t *)x, r.start, r.end) // Same as above, variant for when start and end are statically known #define Eurydice_array_to_subslice2(x, start, end, t) \ EURYDICE_SLICE((t *)x, start, end) #define Eurydice_array_to_subslice_to(_size, x, r, t, _range_t) \ EURYDICE_SLICE((t *)x, 0, r) #define Eurydice_array_to_subslice_from(size, x, r, t, _range_t) \ EURYDICE_SLICE((t *)x, r, size) #define Eurydice_slice_len(s, t) EURYDICE_SLICE_LEN(s, t) #define Eurydice_slice_copy(dst, src, t) \ memcpy(dst.ptr, src.ptr, dst.len * sizeof(t)) #define core_array___Array_T__N__23__as_slice(len_, ptr_, t, _ret_t) \ ((Eurydice_slice){.ptr = ptr_, .len = len_}) #define core_array___core__clone__Clone_for__Array_T__N___20__clone( \ len, src, dst, elem_type, _ret_t) \ (memcpy(dst, src, len * sizeof(elem_type))) #define TryFromSliceError uint8_t #define Eurydice_array_eq(sz, a1, a2, t, _) \ (memcmp(a1, a2, sz * sizeof(t)) == 0) #define core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( \ sz, a1, a2, t, _, _ret_t) \ Eurydice_array_eq(sz, a1, a2, t, _) #define core_array_equality___core__cmp__PartialEq__0___Slice_U____for__Array_T__N___3__eq( \ sz, a1, a2, t, _, _ret_t) \ Eurydice_array_eq(sz, a1, ((a2)->ptr), t, _) #define Eurydice_slice_split_at(slice, mid, element_type, ret_t) \ (CLITERAL(ret_t){ \ .fst = EURYDICE_SLICE((element_type *)slice.ptr, 0, mid), \ .snd = EURYDICE_SLICE((element_type *)slice.ptr, mid, slice.len)}) #define Eurydice_slice_split_at_mut(slice, mid, element_type, ret_t) \ (CLITERAL(ret_t){ \ .fst = {.ptr = slice.ptr, .len = mid}, \ .snd = {.ptr = (char *)slice.ptr + mid * sizeof(element_type), \ .len = slice.len - mid}}) // Conversion of slice to an array, rewritten (by Eurydice) to name the // destination array, since arrays are not values in C. // N.B.: see note in karamel/lib/Inlining.ml if you change this. #define Eurydice_slice_to_array2(dst, src, _, t_arr) \ Eurydice_slice_to_array3(&(dst)->tag, (char *)&(dst)->val.case_Ok, src, \ sizeof(t_arr)) static inline void Eurydice_slice_to_array3(uint8_t *dst_tag, char *dst_ok, Eurydice_slice src, size_t sz) { *dst_tag = 0; memcpy(dst_ok, src.ptr, sz); } // CORE STUFF (conversions, endianness, ...) static inline void core_num__u64_9__to_le_bytes(uint64_t v, uint8_t buf[8]) { v = htole64(v); memcpy(buf, &v, sizeof(v)); } static inline uint64_t core_num__u64_9__from_le_bytes(uint8_t buf[8]) { uint64_t v; memcpy(&v, buf, sizeof(v)); return le64toh(v); } static inline uint32_t core_num__u32_8__from_le_bytes(uint8_t buf[4]) { uint32_t v; memcpy(&v, buf, sizeof(v)); return le32toh(v); } static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) { #if defined(_MSC_VER) return __popcnt(x0); #elif !defined(MISSING_BUILTIN_POPCOUNT) return __builtin_popcount(x0); #else const uint8_t v[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; return v[x0 & 0xf] + v[(x0 >> 4) & 0xf]; #endif } // unsigned overflow wraparound semantics in C static inline uint16_t core_num__u16_7__wrapping_add(uint16_t x, uint16_t y) { return x + y; } static inline uint8_t core_num__u8_6__wrapping_sub(uint8_t x, uint8_t y) { return x - y; } // ITERATORS #define Eurydice_range_iter_next(iter_ptr, t, ret_t) \ (((iter_ptr)->start == (iter_ptr)->end) \ ? (CLITERAL(ret_t){.tag = None}) \ : (CLITERAL(ret_t){.tag = Some, .f0 = (iter_ptr)->start++})) #define core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next \ Eurydice_range_iter_next // See note in karamel/lib/Inlining.ml if you change this #define Eurydice_into_iter(x, t, _ret_t) (x) #define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter \ Eurydice_into_iter #if defined(__cplusplus) } #endif /* from libcrux/libcrux-ml-kem/cg/libcrux_core.h */ /* * SPDX-FileCopyrightText: 2024 Cryspen Sarl * * SPDX-License-Identifier: MIT or Apache-2.0 * * This code was generated with the following revisions: * Charon: 6b5e110342a771a3e1c739b10294b1778e4be8b4 * Eurydice: 31be7d65ca5d6acdacfb33652e478d24dd85c1cb * Karamel: 3205d3365ea2790b02368f79fcee38e38d0b5908 * F*: a32b316e521fa4f239b610ec8f1d15e78d62cbe8-dirty * Libcrux: 4ad532b206174114dd4140b718e7794a28fc59ee */ #ifndef __libcrux_core_H #define __libcrux_core_H #if defined(__cplusplus) extern "C" { #endif /** A monomorphic instance of core.ops.range.Range with types size_t */ typedef struct core_ops_range_Range_b3_s { size_t start; size_t end; } core_ops_range_Range_b3; #define Ok 0 #define Err 1 typedef uint8_t Result_86_tags; #define None 0 #define Some 1 typedef uint8_t Option_ef_tags; /** A monomorphic instance of core.option.Option with types size_t */ typedef struct Option_b3_s { Option_ef_tags tag; size_t f0; } Option_b3; static inline uint16_t core_num__u16_7__wrapping_add(uint16_t x0, uint16_t x1); #define CORE_NUM__U32_8__BITS (32U) static inline uint64_t core_num__u64_9__from_le_bytes(uint8_t x0[8U]); static inline void core_num__u64_9__to_le_bytes(uint64_t x0, uint8_t x1[8U]); static inline uint32_t core_num__u8_6__count_ones(uint8_t x0); static inline uint8_t core_num__u8_6__wrapping_sub(uint8_t x0, uint8_t x1); #define LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE ((size_t)32U) #define LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT ((size_t)12U) #define LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT ((size_t)256U) #define LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_RING_ELEMENT \ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)12U) #define LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT \ (LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_RING_ELEMENT / (size_t)8U) #define LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE ((size_t)32U) #define LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE ((size_t)32U) typedef struct libcrux_ml_kem_utils_extraction_helper_Keypair768_s { uint8_t fst[1152U]; uint8_t snd[1184U]; } libcrux_ml_kem_utils_extraction_helper_Keypair768; /** A monomorphic instance of core.result.Result with types uint8_t[24size_t], core_array_TryFromSliceError */ typedef struct Result_6f_s { Result_86_tags tag; union { uint8_t case_Ok[24U]; TryFromSliceError case_Err; } val; } Result_6f; /** This function found in impl {core::result::Result} */ /** A monomorphic instance of core.result.unwrap_41 with types uint8_t[24size_t], core_array_TryFromSliceError */ static inline void unwrap_41_1c(Result_6f self, uint8_t ret[24U]) { if (self.tag == Ok) { uint8_t f0[24U]; memcpy(f0, self.val.case_Ok, (size_t)24U * sizeof(uint8_t)); memcpy(ret, f0, (size_t)24U * sizeof(uint8_t)); } else { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "unwrap not Ok"); KRML_HOST_EXIT(255U); } } /** A monomorphic instance of core.result.Result with types uint8_t[20size_t], core_array_TryFromSliceError */ typedef struct Result_7a_s { Result_86_tags tag; union { uint8_t case_Ok[20U]; TryFromSliceError case_Err; } val; } Result_7a; /** This function found in impl {core::result::Result} */ /** A monomorphic instance of core.result.unwrap_41 with types uint8_t[20size_t], core_array_TryFromSliceError */ static inline void unwrap_41_34(Result_7a self, uint8_t ret[20U]) { if (self.tag == Ok) { uint8_t f0[20U]; memcpy(f0, self.val.case_Ok, (size_t)20U * sizeof(uint8_t)); memcpy(ret, f0, (size_t)20U * sizeof(uint8_t)); } else { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "unwrap not Ok"); KRML_HOST_EXIT(255U); } } /** A monomorphic instance of core.result.Result with types uint8_t[10size_t], core_array_TryFromSliceError */ typedef struct Result_cd_s { Result_86_tags tag; union { uint8_t case_Ok[10U]; TryFromSliceError case_Err; } val; } Result_cd; /** This function found in impl {core::result::Result} */ /** A monomorphic instance of core.result.unwrap_41 with types uint8_t[10size_t], core_array_TryFromSliceError */ static inline void unwrap_41_e8(Result_cd self, uint8_t ret[10U]) { if (self.tag == Ok) { uint8_t f0[10U]; memcpy(f0, self.val.case_Ok, (size_t)10U * sizeof(uint8_t)); memcpy(ret, f0, (size_t)10U * sizeof(uint8_t)); } else { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "unwrap not Ok"); KRML_HOST_EXIT(255U); } } typedef struct Eurydice_slice_uint8_t_4size_t__x2_s { Eurydice_slice fst[4U]; Eurydice_slice snd[4U]; } Eurydice_slice_uint8_t_4size_t__x2; typedef struct libcrux_ml_kem_mlkem768_MlKem768Ciphertext_s { uint8_t value[1088U]; } libcrux_ml_kem_mlkem768_MlKem768Ciphertext; /** A reference to the raw byte slice. */ /** This function found in impl {libcrux_ml_kem::types::MlKemCiphertext#6} */ /** A monomorphic instance of libcrux_ml_kem.types.as_slice_d4 with const generics - SIZE= 1088 */ static inline uint8_t *libcrux_ml_kem_types_as_slice_d4_1d( libcrux_ml_kem_mlkem768_MlKem768Ciphertext *self) { return self->value; } /** A monomorphic instance of libcrux_ml_kem.types.MlKemPublicKey with const generics - $1184size_t */ typedef struct libcrux_ml_kem_types_MlKemPublicKey_15_s { uint8_t value[1184U]; } libcrux_ml_kem_types_MlKemPublicKey_15; /** This function found in impl {(core::convert::From<@Array> for libcrux_ml_kem::types::MlKemPublicKey)#14} */ /** A monomorphic instance of libcrux_ml_kem.types.from_b6 with const generics - SIZE= 1184 */ static inline libcrux_ml_kem_types_MlKemPublicKey_15 libcrux_ml_kem_types_from_b6_da(uint8_t value[1184U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_value[1184U]; memcpy(copy_of_value, value, (size_t)1184U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPublicKey_15 lit; memcpy(lit.value, copy_of_value, (size_t)1184U * sizeof(uint8_t)); return lit; } /** A monomorphic instance of libcrux_ml_kem.types.MlKemPrivateKey with const generics - $2400size_t */ typedef struct libcrux_ml_kem_types_MlKemPrivateKey_55_s { uint8_t value[2400U]; } libcrux_ml_kem_types_MlKemPrivateKey_55; typedef struct libcrux_ml_kem_mlkem768_MlKem768KeyPair_s { libcrux_ml_kem_types_MlKemPrivateKey_55 sk; libcrux_ml_kem_types_MlKemPublicKey_15 pk; } libcrux_ml_kem_mlkem768_MlKem768KeyPair; /** Create a new [`MlKemKeyPair`] from the secret and public key. */ /** This function found in impl {libcrux_ml_kem::types::MlKemKeyPair} */ /** A monomorphic instance of libcrux_ml_kem.types.from_17 with const generics - PRIVATE_KEY_SIZE= 2400 - PUBLIC_KEY_SIZE= 1184 */ static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_types_from_17_35(libcrux_ml_kem_types_MlKemPrivateKey_55 sk, libcrux_ml_kem_types_MlKemPublicKey_15 pk) { return ( CLITERAL(libcrux_ml_kem_mlkem768_MlKem768KeyPair){.sk = sk, .pk = pk}); } /** This function found in impl {(core::convert::From<@Array> for libcrux_ml_kem::types::MlKemPrivateKey)#8} */ /** A monomorphic instance of libcrux_ml_kem.types.from_05 with const generics - SIZE= 2400 */ static inline libcrux_ml_kem_types_MlKemPrivateKey_55 libcrux_ml_kem_types_from_05_f2(uint8_t value[2400U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_value[2400U]; memcpy(copy_of_value, value, (size_t)2400U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey_55 lit; memcpy(lit.value, copy_of_value, (size_t)2400U * sizeof(uint8_t)); return lit; } /** A monomorphic instance of core.result.Result with types uint8_t[32size_t], core_array_TryFromSliceError */ typedef struct Result_00_s { Result_86_tags tag; union { uint8_t case_Ok[32U]; TryFromSliceError case_Err; } val; } Result_00; /** This function found in impl {core::result::Result} */ /** A monomorphic instance of core.result.unwrap_41 with types uint8_t[32size_t], core_array_TryFromSliceError */ static inline void unwrap_41_83(Result_00 self, uint8_t ret[32U]) { if (self.tag == Ok) { uint8_t f0[32U]; memcpy(f0, self.val.case_Ok, (size_t)32U * sizeof(uint8_t)); memcpy(ret, f0, (size_t)32U * sizeof(uint8_t)); } else { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "unwrap not Ok"); KRML_HOST_EXIT(255U); } } /** A monomorphic instance of K. with types libcrux_ml_kem_types_MlKemCiphertext[[$1088size_t]], uint8_t[32size_t] */ typedef struct tuple_3c_s { libcrux_ml_kem_mlkem768_MlKem768Ciphertext fst; uint8_t snd[32U]; } tuple_3c; /** This function found in impl {(core::convert::From<@Array> for libcrux_ml_kem::types::MlKemCiphertext)#2} */ /** A monomorphic instance of libcrux_ml_kem.types.from_01 with const generics - SIZE= 1088 */ static inline libcrux_ml_kem_mlkem768_MlKem768Ciphertext libcrux_ml_kem_types_from_01_9f(uint8_t value[1088U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_value[1088U]; memcpy(copy_of_value, value, (size_t)1088U * sizeof(uint8_t)); libcrux_ml_kem_mlkem768_MlKem768Ciphertext lit; memcpy(lit.value, copy_of_value, (size_t)1088U * sizeof(uint8_t)); return lit; } /** A reference to the raw byte slice. */ /** This function found in impl {libcrux_ml_kem::types::MlKemPublicKey#18} */ /** A monomorphic instance of libcrux_ml_kem.types.as_slice_cb with const generics - SIZE= 1184 */ static inline uint8_t *libcrux_ml_kem_types_as_slice_cb_50( libcrux_ml_kem_types_MlKemPublicKey_15 *self) { return self->value; } /** Pad the `slice` with `0`s at the end. */ /** A monomorphic instance of libcrux_ml_kem.utils.into_padded_array with const generics - LEN= 33 */ static KRML_MUSTINLINE void libcrux_ml_kem_utils_into_padded_array_ea2( Eurydice_slice slice, uint8_t ret[33U]) { uint8_t out[33U] = {0U}; uint8_t *uu____0 = out; Eurydice_slice_copy( Eurydice_array_to_subslice2(uu____0, (size_t)0U, Eurydice_slice_len(slice, uint8_t), uint8_t), slice, uint8_t); memcpy(ret, out, (size_t)33U * sizeof(uint8_t)); } /** Pad the `slice` with `0`s at the end. */ /** A monomorphic instance of libcrux_ml_kem.utils.into_padded_array with const generics - LEN= 34 */ static KRML_MUSTINLINE void libcrux_ml_kem_utils_into_padded_array_ea1( Eurydice_slice slice, uint8_t ret[34U]) { uint8_t out[34U] = {0U}; uint8_t *uu____0 = out; Eurydice_slice_copy( Eurydice_array_to_subslice2(uu____0, (size_t)0U, Eurydice_slice_len(slice, uint8_t), uint8_t), slice, uint8_t); memcpy(ret, out, (size_t)34U * sizeof(uint8_t)); } /** This function found in impl {(core::convert::AsRef<@Slice> for libcrux_ml_kem::types::MlKemCiphertext)#1} */ /** A monomorphic instance of libcrux_ml_kem.types.as_ref_00 with const generics - SIZE= 1088 */ static inline Eurydice_slice libcrux_ml_kem_types_as_ref_00_24( libcrux_ml_kem_mlkem768_MlKem768Ciphertext *self) { return Eurydice_array_to_slice((size_t)1088U, self->value, uint8_t); } /** Pad the `slice` with `0`s at the end. */ /** A monomorphic instance of libcrux_ml_kem.utils.into_padded_array with const generics - LEN= 1120 */ static KRML_MUSTINLINE void libcrux_ml_kem_utils_into_padded_array_ea0( Eurydice_slice slice, uint8_t ret[1120U]) { uint8_t out[1120U] = {0U}; uint8_t *uu____0 = out; Eurydice_slice_copy( Eurydice_array_to_subslice2(uu____0, (size_t)0U, Eurydice_slice_len(slice, uint8_t), uint8_t), slice, uint8_t); memcpy(ret, out, (size_t)1120U * sizeof(uint8_t)); } /** Pad the `slice` with `0`s at the end. */ /** A monomorphic instance of libcrux_ml_kem.utils.into_padded_array with const generics - LEN= 64 */ static KRML_MUSTINLINE void libcrux_ml_kem_utils_into_padded_array_ea( Eurydice_slice slice, uint8_t ret[64U]) { uint8_t out[64U] = {0U}; uint8_t *uu____0 = out; Eurydice_slice_copy( Eurydice_array_to_subslice2(uu____0, (size_t)0U, Eurydice_slice_len(slice, uint8_t), uint8_t), slice, uint8_t); memcpy(ret, out, (size_t)64U * sizeof(uint8_t)); } /** A monomorphic instance of core.result.Result with types int16_t[16size_t], core_array_TryFromSliceError */ typedef struct Result_c0_s { Result_86_tags tag; union { int16_t case_Ok[16U]; TryFromSliceError case_Err; } val; } Result_c0; /** This function found in impl {core::result::Result} */ /** A monomorphic instance of core.result.unwrap_41 with types int16_t[16size_t], core_array_TryFromSliceError */ static inline void unwrap_41_f9(Result_c0 self, int16_t ret[16U]) { if (self.tag == Ok) { int16_t f0[16U]; memcpy(f0, self.val.case_Ok, (size_t)16U * sizeof(int16_t)); memcpy(ret, f0, (size_t)16U * sizeof(int16_t)); } else { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "unwrap not Ok"); KRML_HOST_EXIT(255U); } } /** A monomorphic instance of core.result.Result with types uint8_t[8size_t], core_array_TryFromSliceError */ typedef struct Result_56_s { Result_86_tags tag; union { uint8_t case_Ok[8U]; TryFromSliceError case_Err; } val; } Result_56; /** This function found in impl {core::result::Result} */ /** A monomorphic instance of core.result.unwrap_41 with types uint8_t[8size_t], core_array_TryFromSliceError */ static inline void unwrap_41_ac(Result_56 self, uint8_t ret[8U]) { if (self.tag == Ok) { uint8_t f0[8U]; memcpy(f0, self.val.case_Ok, (size_t)8U * sizeof(uint8_t)); memcpy(ret, f0, (size_t)8U * sizeof(uint8_t)); } else { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "unwrap not Ok"); KRML_HOST_EXIT(255U); } } typedef struct Eurydice_slice_uint8_t_x2_s { Eurydice_slice fst; Eurydice_slice snd; } Eurydice_slice_uint8_t_x2; typedef struct Eurydice_slice_uint8_t_1size_t__x2_s { Eurydice_slice fst[1U]; Eurydice_slice snd[1U]; } Eurydice_slice_uint8_t_1size_t__x2; #if defined(__cplusplus) } #endif #define __libcrux_core_H_DEFINED #endif /* from libcrux/libcrux-ml-kem/cg/libcrux_ct_ops.h */ /* * SPDX-FileCopyrightText: 2024 Cryspen Sarl * * SPDX-License-Identifier: MIT or Apache-2.0 * * This code was generated with the following revisions: * Charon: 6b5e110342a771a3e1c739b10294b1778e4be8b4 * Eurydice: 31be7d65ca5d6acdacfb33652e478d24dd85c1cb * Karamel: 3205d3365ea2790b02368f79fcee38e38d0b5908 * F*: a32b316e521fa4f239b610ec8f1d15e78d62cbe8-dirty * Libcrux: 4ad532b206174114dd4140b718e7794a28fc59ee */ #ifndef __libcrux_ct_ops_H #define __libcrux_ct_ops_H #if defined(__cplusplus) extern "C" { #endif /** Return 1 if `value` is not zero and 0 otherwise. */ static inline uint8_t libcrux_ml_kem_constant_time_ops_inz(uint8_t value) { uint16_t value0 = (uint16_t)value; uint16_t result = (((uint32_t)value0 | (uint32_t)core_num__u16_7__wrapping_add(~value0, 1U)) & 0xFFFFU) >> 8U & 1U; return (uint8_t)result; } static KRML_NOINLINE uint8_t libcrux_ml_kem_constant_time_ops_is_non_zero(uint8_t value) { return libcrux_ml_kem_constant_time_ops_inz(value); } /** Return 1 if the bytes of `lhs` and `rhs` do not exactly match and 0 otherwise. */ static inline uint8_t libcrux_ml_kem_constant_time_ops_compare( Eurydice_slice lhs, Eurydice_slice rhs) { uint8_t r = 0U; for (size_t i = (size_t)0U; i < Eurydice_slice_len(lhs, uint8_t); i++) { size_t i0 = i; r = (uint32_t)r | ((uint32_t)Eurydice_slice_index(lhs, i0, uint8_t, uint8_t *) ^ (uint32_t)Eurydice_slice_index(rhs, i0, uint8_t, uint8_t *)); } return libcrux_ml_kem_constant_time_ops_is_non_zero(r); } static KRML_NOINLINE uint8_t libcrux_ml_kem_constant_time_ops_compare_ciphertexts_in_constant_time( Eurydice_slice lhs, Eurydice_slice rhs) { return libcrux_ml_kem_constant_time_ops_compare(lhs, rhs); } /** If `selector` is not zero, return the bytes in `rhs`; return the bytes in `lhs` otherwise. */ static inline void libcrux_ml_kem_constant_time_ops_select_ct( Eurydice_slice lhs, Eurydice_slice rhs, uint8_t selector, uint8_t ret[32U]) { uint8_t mask = core_num__u8_6__wrapping_sub( libcrux_ml_kem_constant_time_ops_is_non_zero(selector), 1U); uint8_t out[32U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE; i++) { size_t i0 = i; out[i0] = ((uint32_t)Eurydice_slice_index(lhs, i0, uint8_t, uint8_t *) & (uint32_t)mask) | ((uint32_t)Eurydice_slice_index(rhs, i0, uint8_t, uint8_t *) & (uint32_t)~mask); } memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } static KRML_NOINLINE void libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( Eurydice_slice lhs, Eurydice_slice rhs, uint8_t selector, uint8_t ret[32U]) { libcrux_ml_kem_constant_time_ops_select_ct(lhs, rhs, selector, ret); } static inline void libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( Eurydice_slice lhs_c, Eurydice_slice rhs_c, Eurydice_slice lhs_s, Eurydice_slice rhs_s, uint8_t ret[32U]) { uint8_t selector = libcrux_ml_kem_constant_time_ops_compare_ciphertexts_in_constant_time( lhs_c, rhs_c); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( lhs_s, rhs_s, selector, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } #if defined(__cplusplus) } #endif #define __libcrux_ct_ops_H_DEFINED #endif /* from libcrux/libcrux-ml-kem/cg/libcrux_sha3_portable.h */ /* * SPDX-FileCopyrightText: 2024 Cryspen Sarl * * SPDX-License-Identifier: MIT or Apache-2.0 * * This code was generated with the following revisions: * Charon: 6b5e110342a771a3e1c739b10294b1778e4be8b4 * Eurydice: 31be7d65ca5d6acdacfb33652e478d24dd85c1cb * Karamel: 3205d3365ea2790b02368f79fcee38e38d0b5908 * F*: a32b316e521fa4f239b610ec8f1d15e78d62cbe8-dirty * Libcrux: 4ad532b206174114dd4140b718e7794a28fc59ee */ #ifndef __libcrux_sha3_portable_H #define __libcrux_sha3_portable_H #if defined(__cplusplus) extern "C" { #endif static const uint64_t libcrux_sha3_generic_keccak_ROUNDCONSTANTS[24U] = { 1ULL, 32898ULL, 9223372036854808714ULL, 9223372039002292224ULL, 32907ULL, 2147483649ULL, 9223372039002292353ULL, 9223372036854808585ULL, 138ULL, 136ULL, 2147516425ULL, 2147483658ULL, 2147516555ULL, 9223372036854775947ULL, 9223372036854808713ULL, 9223372036854808579ULL, 9223372036854808578ULL, 9223372036854775936ULL, 32778ULL, 9223372039002259466ULL, 9223372039002292353ULL, 9223372036854808704ULL, 2147483649ULL, 9223372039002292232ULL}; /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_zero_5a(void) { return 0ULL; } static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__veor5q_u64( uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e) { uint64_t ab = a ^ b; uint64_t cd = c ^ d; uint64_t abcd = ab ^ cd; return abcd ^ e; } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor5_5a( uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e) { return libcrux_sha3_portable_keccak__veor5q_u64(a, b, c, d, e); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 1 - RIGHT= 63 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb(uint64_t x) { return x << (uint32_t)(int32_t)1 | x >> (uint32_t)(int32_t)63; } static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vrax1q_u64(uint64_t a, uint64_t b) { uint64_t uu____0 = a; return uu____0 ^ libcrux_sha3_portable_keccak_rotate_left_cb(b); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vrax1q_u64(a, b); } static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vbcaxq_u64(uint64_t a, uint64_t b, uint64_t c) { return a ^ (b & ~c); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_and_not_xor_5a( uint64_t a, uint64_t b, uint64_t c) { return libcrux_sha3_portable_keccak__vbcaxq_u64(a, b, c); } static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__veorq_n_u64(uint64_t a, uint64_t c) { return a ^ c; } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_constant_5a(uint64_t a, uint64_t c) { return libcrux_sha3_portable_keccak__veorq_n_u64(a, c); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_5a(uint64_t a, uint64_t b) { return a ^ b; } static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_slice_1( Eurydice_slice a[1U], size_t start, size_t len, Eurydice_slice ret[1U]) { ret[0U] = Eurydice_slice_subslice2(a[0U], start, start + len, uint8_t); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_slice_n_5a( Eurydice_slice a[1U], size_t start, size_t len, Eurydice_slice ret[1U]) { /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_a[1U]; memcpy(copy_of_a, a, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret0[1U]; libcrux_sha3_portable_keccak_slice_1(copy_of_a, start, len, ret0); memcpy(ret, ret0, (size_t)1U * sizeof(Eurydice_slice)); } static KRML_MUSTINLINE Eurydice_slice_uint8_t_1size_t__x2 libcrux_sha3_portable_keccak_split_at_mut_1(Eurydice_slice out[1U], size_t mid) { Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at_mut( out[0U], mid, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice out00 = uu____0.fst; Eurydice_slice out01 = uu____0.snd; Eurydice_slice_uint8_t_1size_t__x2 lit; lit.fst[0U] = out00; lit.snd[0U] = out01; return lit; } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ static KRML_MUSTINLINE Eurydice_slice_uint8_t_1size_t__x2 libcrux_sha3_portable_keccak_split_at_mut_n_5a(Eurydice_slice a[1U], size_t mid) { return libcrux_sha3_portable_keccak_split_at_mut_1(a, mid); } /** A monomorphic instance of libcrux_sha3.generic_keccak.KeccakState with types uint64_t with const generics - $1size_t */ typedef struct libcrux_sha3_generic_keccak_KeccakState_48_s { uint64_t st[5U][5U]; } libcrux_sha3_generic_keccak_KeccakState_48; /** Create a new Shake128 x4 state. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakState[TraitClause@0]#1} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.new_1e with types uint64_t with const generics - N= 1 */ static KRML_MUSTINLINE libcrux_sha3_generic_keccak_KeccakState_48 libcrux_sha3_generic_keccak_new_1e_f4(void) { libcrux_sha3_generic_keccak_KeccakState_48 lit; lit.st[0U][0U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[0U][1U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[0U][2U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[0U][3U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[0U][4U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[1U][0U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[1U][1U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[1U][2U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[1U][3U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[1U][4U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[2U][0U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[2U][1U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[2U][2U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[2U][3U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[2U][4U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[3U][0U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[3U][1U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[3U][2U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[3U][3U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[3U][4U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[4U][0U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[4U][1U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[4U][2U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[4U][3U] = libcrux_sha3_portable_keccak_zero_5a(); lit.st[4U][4U] = libcrux_sha3_portable_keccak_zero_5a(); return lit; } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_2c( uint64_t (*s)[5U], Eurydice_slice blocks[1U]) { for (size_t i = (size_t)0U; i < (size_t)72U / (size_t)8U; i++) { size_t i0 = i; uint8_t uu____0[8U]; Result_56 dst; Eurydice_slice_to_array2( &dst, Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t), Eurydice_slice, uint8_t[8U]); unwrap_41_ac(dst, uu____0); size_t uu____1 = i0 / (size_t)5U; size_t uu____2 = i0 % (size_t)5U; s[uu____1][uu____2] = s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_5a_b8( uint64_t (*a)[5U], Eurydice_slice b[1U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_b[1U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_2c(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 36 - RIGHT= 28 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb0(uint64_t x) { return x << (uint32_t)(int32_t)36 | x >> (uint32_t)(int32_t)28; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 36 - RIGHT= 28 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_42(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb0(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 36 - RIGHT= 28 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_42(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 3 - RIGHT= 61 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb1(uint64_t x) { return x << (uint32_t)(int32_t)3 | x >> (uint32_t)(int32_t)61; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 3 - RIGHT= 61 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_420(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb1(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 3 - RIGHT= 61 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb0(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_420(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 41 - RIGHT= 23 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb2(uint64_t x) { return x << (uint32_t)(int32_t)41 | x >> (uint32_t)(int32_t)23; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 41 - RIGHT= 23 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_421(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb2(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 41 - RIGHT= 23 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb1(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_421(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 18 - RIGHT= 46 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb3(uint64_t x) { return x << (uint32_t)(int32_t)18 | x >> (uint32_t)(int32_t)46; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 18 - RIGHT= 46 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_422(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb3(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 18 - RIGHT= 46 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb2(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_422(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 1 - RIGHT= 63 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_423(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 1 - RIGHT= 63 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb3(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_423(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 44 - RIGHT= 20 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb4(uint64_t x) { return x << (uint32_t)(int32_t)44 | x >> (uint32_t)(int32_t)20; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 44 - RIGHT= 20 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_424(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb4(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 44 - RIGHT= 20 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb4(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_424(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 10 - RIGHT= 54 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb5(uint64_t x) { return x << (uint32_t)(int32_t)10 | x >> (uint32_t)(int32_t)54; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 10 - RIGHT= 54 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_425(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb5(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 10 - RIGHT= 54 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb5(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_425(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 45 - RIGHT= 19 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb6(uint64_t x) { return x << (uint32_t)(int32_t)45 | x >> (uint32_t)(int32_t)19; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 45 - RIGHT= 19 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_426(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb6(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 45 - RIGHT= 19 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb6(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_426(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 2 - RIGHT= 62 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb7(uint64_t x) { return x << (uint32_t)(int32_t)2 | x >> (uint32_t)(int32_t)62; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 2 - RIGHT= 62 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_427(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb7(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 2 - RIGHT= 62 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb7(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_427(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 62 - RIGHT= 2 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb8(uint64_t x) { return x << (uint32_t)(int32_t)62 | x >> (uint32_t)(int32_t)2; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 62 - RIGHT= 2 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_428(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb8(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 62 - RIGHT= 2 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb8(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_428(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 6 - RIGHT= 58 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb9(uint64_t x) { return x << (uint32_t)(int32_t)6 | x >> (uint32_t)(int32_t)58; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 6 - RIGHT= 58 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_429(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb9(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 6 - RIGHT= 58 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb9(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_429(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 43 - RIGHT= 21 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb10(uint64_t x) { return x << (uint32_t)(int32_t)43 | x >> (uint32_t)(int32_t)21; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 43 - RIGHT= 21 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4210(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb10(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 43 - RIGHT= 21 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb10(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4210(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 15 - RIGHT= 49 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb11(uint64_t x) { return x << (uint32_t)(int32_t)15 | x >> (uint32_t)(int32_t)49; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 15 - RIGHT= 49 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4211(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb11(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 15 - RIGHT= 49 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb11(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4211(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 61 - RIGHT= 3 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb12(uint64_t x) { return x << (uint32_t)(int32_t)61 | x >> (uint32_t)(int32_t)3; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 61 - RIGHT= 3 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4212(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb12(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 61 - RIGHT= 3 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb12(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4212(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 28 - RIGHT= 36 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb13(uint64_t x) { return x << (uint32_t)(int32_t)28 | x >> (uint32_t)(int32_t)36; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 28 - RIGHT= 36 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4213(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb13(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 28 - RIGHT= 36 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb13(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4213(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 55 - RIGHT= 9 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb14(uint64_t x) { return x << (uint32_t)(int32_t)55 | x >> (uint32_t)(int32_t)9; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 55 - RIGHT= 9 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4214(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb14(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 55 - RIGHT= 9 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb14(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4214(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 25 - RIGHT= 39 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb15(uint64_t x) { return x << (uint32_t)(int32_t)25 | x >> (uint32_t)(int32_t)39; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 25 - RIGHT= 39 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4215(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb15(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 25 - RIGHT= 39 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb15(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4215(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 21 - RIGHT= 43 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb16(uint64_t x) { return x << (uint32_t)(int32_t)21 | x >> (uint32_t)(int32_t)43; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 21 - RIGHT= 43 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4216(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb16(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 21 - RIGHT= 43 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb16(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4216(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 56 - RIGHT= 8 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb17(uint64_t x) { return x << (uint32_t)(int32_t)56 | x >> (uint32_t)(int32_t)8; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 56 - RIGHT= 8 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4217(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb17(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 56 - RIGHT= 8 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb17(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4217(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 27 - RIGHT= 37 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb18(uint64_t x) { return x << (uint32_t)(int32_t)27 | x >> (uint32_t)(int32_t)37; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 27 - RIGHT= 37 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4218(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb18(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 27 - RIGHT= 37 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb18(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4218(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 20 - RIGHT= 44 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb19(uint64_t x) { return x << (uint32_t)(int32_t)20 | x >> (uint32_t)(int32_t)44; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 20 - RIGHT= 44 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4219(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb19(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 20 - RIGHT= 44 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb19(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4219(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 39 - RIGHT= 25 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb20(uint64_t x) { return x << (uint32_t)(int32_t)39 | x >> (uint32_t)(int32_t)25; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 39 - RIGHT= 25 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4220(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb20(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 39 - RIGHT= 25 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb20(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4220(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 8 - RIGHT= 56 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb21(uint64_t x) { return x << (uint32_t)(int32_t)8 | x >> (uint32_t)(int32_t)56; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 8 - RIGHT= 56 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4221(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb21(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 8 - RIGHT= 56 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb21(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4221(a, b); } /** A monomorphic instance of libcrux_sha3.portable_keccak.rotate_left with const generics - LEFT= 14 - RIGHT= 50 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_rotate_left_cb22(uint64_t x) { return x << (uint32_t)(int32_t)14 | x >> (uint32_t)(int32_t)50; } /** A monomorphic instance of libcrux_sha3.portable_keccak._vxarq_u64 with const generics - LEFT= 14 - RIGHT= 50 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak__vxarq_u64_4222(uint64_t a, uint64_t b) { uint64_t ab = a ^ b; return libcrux_sha3_portable_keccak_rotate_left_cb22(ab); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.xor_and_rotate_5a with const generics - LEFT= 14 - RIGHT= 50 */ static KRML_MUSTINLINE uint64_t libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb22(uint64_t a, uint64_t b) { return libcrux_sha3_portable_keccak__vxarq_u64_4222(a, b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.theta_rho with types uint64_t with const generics - N= 1 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_theta_rho_16( libcrux_sha3_generic_keccak_KeccakState_48 *s) { uint64_t c[5U] = { libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][0U], s->st[1U][0U], s->st[2U][0U], s->st[3U][0U], s->st[4U][0U]), libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][1U], s->st[1U][1U], s->st[2U][1U], s->st[3U][1U], s->st[4U][1U]), libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][2U], s->st[1U][2U], s->st[2U][2U], s->st[3U][2U], s->st[4U][2U]), libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][3U], s->st[1U][3U], s->st[2U][3U], s->st[3U][3U], s->st[4U][3U]), libcrux_sha3_portable_keccak_xor5_5a(s->st[0U][4U], s->st[1U][4U], s->st[2U][4U], s->st[3U][4U], s->st[4U][4U])}; uint64_t uu____0 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( c[((size_t)0U + (size_t)4U) % (size_t)5U], c[((size_t)0U + (size_t)1U) % (size_t)5U]); uint64_t uu____1 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( c[((size_t)1U + (size_t)4U) % (size_t)5U], c[((size_t)1U + (size_t)1U) % (size_t)5U]); uint64_t uu____2 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( c[((size_t)2U + (size_t)4U) % (size_t)5U], c[((size_t)2U + (size_t)1U) % (size_t)5U]); uint64_t uu____3 = libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( c[((size_t)3U + (size_t)4U) % (size_t)5U], c[((size_t)3U + (size_t)1U) % (size_t)5U]); uint64_t t[5U] = {uu____0, uu____1, uu____2, uu____3, libcrux_sha3_portable_keccak_rotate_left1_and_xor_5a( c[((size_t)4U + (size_t)4U) % (size_t)5U], c[((size_t)4U + (size_t)1U) % (size_t)5U])}; s->st[0U][0U] = libcrux_sha3_portable_keccak_xor_5a(s->st[0U][0U], t[0U]); s->st[1U][0U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb(s->st[1U][0U], t[0U]); s->st[2U][0U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb0(s->st[2U][0U], t[0U]); s->st[3U][0U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb1(s->st[3U][0U], t[0U]); s->st[4U][0U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb2(s->st[4U][0U], t[0U]); s->st[0U][1U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb3(s->st[0U][1U], t[1U]); s->st[1U][1U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb4(s->st[1U][1U], t[1U]); s->st[2U][1U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb5(s->st[2U][1U], t[1U]); s->st[3U][1U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb6(s->st[3U][1U], t[1U]); s->st[4U][1U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb7(s->st[4U][1U], t[1U]); s->st[0U][2U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb8(s->st[0U][2U], t[2U]); s->st[1U][2U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb9(s->st[1U][2U], t[2U]); s->st[2U][2U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb10(s->st[2U][2U], t[2U]); s->st[3U][2U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb11(s->st[3U][2U], t[2U]); s->st[4U][2U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb12(s->st[4U][2U], t[2U]); s->st[0U][3U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb13(s->st[0U][3U], t[3U]); s->st[1U][3U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb14(s->st[1U][3U], t[3U]); s->st[2U][3U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb15(s->st[2U][3U], t[3U]); s->st[3U][3U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb16(s->st[3U][3U], t[3U]); s->st[4U][3U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb17(s->st[4U][3U], t[3U]); s->st[0U][4U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb18(s->st[0U][4U], t[4U]); s->st[1U][4U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb19(s->st[1U][4U], t[4U]); s->st[2U][4U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb20(s->st[2U][4U], t[4U]); s->st[3U][4U] = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb21(s->st[3U][4U], t[4U]); uint64_t uu____27 = libcrux_sha3_portable_keccak_xor_and_rotate_5a_bb22(s->st[4U][4U], t[4U]); s->st[4U][4U] = uu____27; } /** A monomorphic instance of libcrux_sha3.generic_keccak.pi with types uint64_t with const generics - N= 1 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_pi_1d( libcrux_sha3_generic_keccak_KeccakState_48 *s) { uint64_t old[5U][5U]; memcpy(old, s->st, (size_t)5U * sizeof(uint64_t[5U])); s->st[0U][1U] = old[1U][1U]; s->st[0U][2U] = old[2U][2U]; s->st[0U][3U] = old[3U][3U]; s->st[0U][4U] = old[4U][4U]; s->st[1U][0U] = old[0U][3U]; s->st[1U][1U] = old[1U][4U]; s->st[1U][2U] = old[2U][0U]; s->st[1U][3U] = old[3U][1U]; s->st[1U][4U] = old[4U][2U]; s->st[2U][0U] = old[0U][1U]; s->st[2U][1U] = old[1U][2U]; s->st[2U][2U] = old[2U][3U]; s->st[2U][3U] = old[3U][4U]; s->st[2U][4U] = old[4U][0U]; s->st[3U][0U] = old[0U][4U]; s->st[3U][1U] = old[1U][0U]; s->st[3U][2U] = old[2U][1U]; s->st[3U][3U] = old[3U][2U]; s->st[3U][4U] = old[4U][3U]; s->st[4U][0U] = old[0U][2U]; s->st[4U][1U] = old[1U][3U]; s->st[4U][2U] = old[2U][4U]; s->st[4U][3U] = old[3U][0U]; s->st[4U][4U] = old[4U][1U]; } /** A monomorphic instance of libcrux_sha3.generic_keccak.chi with types uint64_t with const generics - N= 1 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_chi_12( libcrux_sha3_generic_keccak_KeccakState_48 *s) { uint64_t old[5U][5U]; memcpy(old, s->st, (size_t)5U * sizeof(uint64_t[5U])); for (size_t i0 = (size_t)0U; i0 < (size_t)5U; i0++) { size_t i1 = i0; for (size_t i = (size_t)0U; i < (size_t)5U; i++) { size_t j = i; s->st[i1][j] = libcrux_sha3_portable_keccak_and_not_xor_5a( s->st[i1][j], old[i1][(j + (size_t)2U) % (size_t)5U], old[i1][(j + (size_t)1U) % (size_t)5U]); } } } /** A monomorphic instance of libcrux_sha3.generic_keccak.iota with types uint64_t with const generics - N= 1 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_iota_62( libcrux_sha3_generic_keccak_KeccakState_48 *s, size_t i) { s->st[0U][0U] = libcrux_sha3_portable_keccak_xor_constant_5a( s->st[0U][0U], libcrux_sha3_generic_keccak_ROUNDCONSTANTS[i]); } /** A monomorphic instance of libcrux_sha3.generic_keccak.keccakf1600 with types uint64_t with const generics - N= 1 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_keccakf1600_21( libcrux_sha3_generic_keccak_KeccakState_48 *s) { for (size_t i = (size_t)0U; i < (size_t)24U; i++) { size_t i0 = i; libcrux_sha3_generic_keccak_theta_rho_16(s); libcrux_sha3_generic_keccak_pi_1d(s); libcrux_sha3_generic_keccak_chi_12(s); libcrux_sha3_generic_keccak_iota_62(s, i0); } } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block with types uint64_t with const generics - N= 1 - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_block_df( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) { uint64_t(*uu____0)[5U] = s->st; Eurydice_slice uu____1[1U]; memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_5a_b8(uu____0, uu____1); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_df( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t)}; libcrux_sha3_portable_keccak_load_block_2c(s, buf); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_5a_d2( uint64_t (*a)[5U], uint8_t b[1U][200U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_b[1U][200U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_df(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final with types uint64_t with const generics - N= 1 - RATE= 72 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_c7( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) { size_t last_len = Eurydice_slice_len(last[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (last_len > (size_t)0U) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, last_len, uint8_t); Eurydice_slice_copy(uu____0, last[i0], uint8_t); } blocks[i0][last_len] = 6U; size_t uu____1 = i0; size_t uu____2 = (size_t)72U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } uint64_t(*uu____3)[5U] = s->st; uint8_t uu____4[1U][200U]; memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d2(uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_58( uint64_t (*s)[5U], Eurydice_slice out[1U]) { for (size_t i = (size_t)0U; i < (size_t)72U / (size_t)8U; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); } } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_2d( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t)}; libcrux_sha3_portable_keccak_store_block_58(s, buf); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_out[200U]; memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_5a_29( uint64_t (*a)[5U], uint8_t ret[1U][200U]) { libcrux_sha3_portable_keccak_store_block_full_2d(a, ret); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last with types uint64_t with const generics - N= 1 - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_and_last_c5( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_29(s->st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a with const generics - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_5a_59( uint64_t (*a)[5U], Eurydice_slice b[1U]) { libcrux_sha3_portable_keccak_store_block_58(a, b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block with types uint64_t with const generics - N= 1 - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_block_84( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_portable_keccak_store_block_5a_59(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block with types uint64_t with const generics - N= 1 - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_next_block_fc( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(s); libcrux_sha3_portable_keccak_store_block_5a_59(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last with types uint64_t with const generics - N= 1 - RATE= 72 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_last_cf( libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(&s); uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_29(s.st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** A monomorphic instance of libcrux_sha3.generic_keccak.keccak with types uint64_t with const generics - N= 1 - RATE= 72 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_keccak_e9( Eurydice_slice data[1U], Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_KeccakState_48 s = libcrux_sha3_generic_keccak_new_1e_f4(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)72U; i++) { size_t i0 = i; libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)72U, (size_t)72U, ret); libcrux_sha3_generic_keccak_absorb_block_df(uu____0, ret); } size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)72U; libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); libcrux_sha3_generic_keccak_absorb_final_c7(uu____2, ret); size_t outlen = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = outlen / (size_t)72U; size_t last = outlen - outlen % (size_t)72U; if (blocks == (size_t)0U) { libcrux_sha3_generic_keccak_squeeze_first_and_last_c5(&s, out); } else { Eurydice_slice_uint8_t_1size_t__x2 uu____4 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)72U); Eurydice_slice o0[1U]; memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o1[1U]; memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_84(&s, o0); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____5 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)72U); Eurydice_slice o[1U]; memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice orest[1U]; memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc(&s, o); memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < outlen) { libcrux_sha3_generic_keccak_squeeze_last_cf(s, o1); } } } /** A monomorphic instance of libcrux_sha3.portable.keccakx1 with const generics - RATE= 72 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccakx1_ce( Eurydice_slice data[1U], Eurydice_slice out[1U]) { /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccak_e9(copy_of_data, out); } /** A portable SHA3 512 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_portable_sha512(Eurydice_slice digest, Eurydice_slice data) { Eurydice_slice buf0[1U] = {data}; Eurydice_slice buf[1U] = {digest}; libcrux_sha3_portable_keccakx1_ce(buf0, buf); } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_2c0( uint64_t (*s)[5U], Eurydice_slice blocks[1U]) { for (size_t i = (size_t)0U; i < (size_t)136U / (size_t)8U; i++) { size_t i0 = i; uint8_t uu____0[8U]; Result_56 dst; Eurydice_slice_to_array2( &dst, Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t), Eurydice_slice, uint8_t[8U]); unwrap_41_ac(dst, uu____0); size_t uu____1 = i0 / (size_t)5U; size_t uu____2 = i0 % (size_t)5U; s[uu____1][uu____2] = s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_5a_b80( uint64_t (*a)[5U], Eurydice_slice b[1U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_b[1U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_2c0(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block with types uint64_t with const generics - N= 1 - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_block_df0( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) { uint64_t(*uu____0)[5U] = s->st; Eurydice_slice uu____1[1U]; memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_5a_b80(uu____0, uu____1); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_df0( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t)}; libcrux_sha3_portable_keccak_load_block_2c0(s, buf); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_5a_d20( uint64_t (*a)[5U], uint8_t b[1U][200U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_b[1U][200U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_df0(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final with types uint64_t with const generics - N= 1 - RATE= 136 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_c70( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) { size_t last_len = Eurydice_slice_len(last[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (last_len > (size_t)0U) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, last_len, uint8_t); Eurydice_slice_copy(uu____0, last[i0], uint8_t); } blocks[i0][last_len] = 6U; size_t uu____1 = i0; size_t uu____2 = (size_t)136U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } uint64_t(*uu____3)[5U] = s->st; uint8_t uu____4[1U][200U]; memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d20(uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_580( uint64_t (*s)[5U], Eurydice_slice out[1U]) { for (size_t i = (size_t)0U; i < (size_t)136U / (size_t)8U; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); } } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_2d0( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t)}; libcrux_sha3_portable_keccak_store_block_580(s, buf); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_out[200U]; memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_5a_290(uint64_t (*a)[5U], uint8_t ret[1U][200U]) { libcrux_sha3_portable_keccak_store_block_full_2d0(a, ret); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last with types uint64_t with const generics - N= 1 - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_and_last_c50( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_290(s->st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_5a_590( uint64_t (*a)[5U], Eurydice_slice b[1U]) { libcrux_sha3_portable_keccak_store_block_580(a, b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block with types uint64_t with const generics - N= 1 - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_block_840( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_portable_keccak_store_block_5a_590(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block with types uint64_t with const generics - N= 1 - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_next_block_fc0( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(s); libcrux_sha3_portable_keccak_store_block_5a_590(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last with types uint64_t with const generics - N= 1 - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_last_cf0( libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(&s); uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_290(s.st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** A monomorphic instance of libcrux_sha3.generic_keccak.keccak with types uint64_t with const generics - N= 1 - RATE= 136 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_keccak_e90( Eurydice_slice data[1U], Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_KeccakState_48 s = libcrux_sha3_generic_keccak_new_1e_f4(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)136U; i++) { size_t i0 = i; libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)136U, (size_t)136U, ret); libcrux_sha3_generic_keccak_absorb_block_df0(uu____0, ret); } size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)136U; libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); libcrux_sha3_generic_keccak_absorb_final_c70(uu____2, ret); size_t outlen = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = outlen / (size_t)136U; size_t last = outlen - outlen % (size_t)136U; if (blocks == (size_t)0U) { libcrux_sha3_generic_keccak_squeeze_first_and_last_c50(&s, out); } else { Eurydice_slice_uint8_t_1size_t__x2 uu____4 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)136U); Eurydice_slice o0[1U]; memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o1[1U]; memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_840(&s, o0); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____5 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)136U); Eurydice_slice o[1U]; memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice orest[1U]; memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc0(&s, o); memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < outlen) { libcrux_sha3_generic_keccak_squeeze_last_cf0(s, o1); } } } /** A monomorphic instance of libcrux_sha3.portable.keccakx1 with const generics - RATE= 136 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccakx1_ce0( Eurydice_slice data[1U], Eurydice_slice out[1U]) { /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccak_e90(copy_of_data, out); } /** A portable SHA3 256 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_portable_sha256(Eurydice_slice digest, Eurydice_slice data) { Eurydice_slice buf0[1U] = {data}; Eurydice_slice buf[1U] = {digest}; libcrux_sha3_portable_keccakx1_ce0(buf0, buf); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final with types uint64_t with const generics - N= 1 - RATE= 136 - DELIM= 31 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_c71( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) { size_t last_len = Eurydice_slice_len(last[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (last_len > (size_t)0U) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, last_len, uint8_t); Eurydice_slice_copy(uu____0, last[i0], uint8_t); } blocks[i0][last_len] = 31U; size_t uu____1 = i0; size_t uu____2 = (size_t)136U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } uint64_t(*uu____3)[5U] = s->st; uint8_t uu____4[1U][200U]; memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d20(uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.generic_keccak.keccak with types uint64_t with const generics - N= 1 - RATE= 136 - DELIM= 31 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_keccak_e91( Eurydice_slice data[1U], Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_KeccakState_48 s = libcrux_sha3_generic_keccak_new_1e_f4(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)136U; i++) { size_t i0 = i; libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)136U, (size_t)136U, ret); libcrux_sha3_generic_keccak_absorb_block_df0(uu____0, ret); } size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)136U; libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); libcrux_sha3_generic_keccak_absorb_final_c71(uu____2, ret); size_t outlen = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = outlen / (size_t)136U; size_t last = outlen - outlen % (size_t)136U; if (blocks == (size_t)0U) { libcrux_sha3_generic_keccak_squeeze_first_and_last_c50(&s, out); } else { Eurydice_slice_uint8_t_1size_t__x2 uu____4 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)136U); Eurydice_slice o0[1U]; memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o1[1U]; memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_840(&s, o0); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____5 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)136U); Eurydice_slice o[1U]; memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice orest[1U]; memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc0(&s, o); memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < outlen) { libcrux_sha3_generic_keccak_squeeze_last_cf0(s, o1); } } } /** A monomorphic instance of libcrux_sha3.portable.keccakx1 with const generics - RATE= 136 - DELIM= 31 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccakx1_ce1( Eurydice_slice data[1U], Eurydice_slice out[1U]) { /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccak_e91(copy_of_data, out); } /** A portable SHAKE256 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_portable_shake256( Eurydice_slice digest, Eurydice_slice data) { Eurydice_slice buf0[1U] = {data}; Eurydice_slice buf[1U] = {digest}; libcrux_sha3_portable_keccakx1_ce1(buf0, buf); } typedef libcrux_sha3_generic_keccak_KeccakState_48 libcrux_sha3_portable_KeccakState; /** Create a new SHAKE-128 state object. */ static KRML_MUSTINLINE libcrux_sha3_generic_keccak_KeccakState_48 libcrux_sha3_portable_incremental_shake128_init(void) { return libcrux_sha3_generic_keccak_new_1e_f4(); } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_2c1( uint64_t (*s)[5U], Eurydice_slice blocks[1U]) { for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)8U; i++) { size_t i0 = i; uint8_t uu____0[8U]; Result_56 dst; Eurydice_slice_to_array2( &dst, Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t), Eurydice_slice, uint8_t[8U]); unwrap_41_ac(dst, uu____0); size_t uu____1 = i0 / (size_t)5U; size_t uu____2 = i0 % (size_t)5U; s[uu____1][uu____2] = s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); } } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_df1( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t)}; libcrux_sha3_portable_keccak_load_block_2c1(s, buf); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_5a_d21( uint64_t (*a)[5U], uint8_t b[1U][200U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_b[1U][200U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_df1(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final with types uint64_t with const generics - N= 1 - RATE= 168 - DELIM= 31 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_c72( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) { size_t last_len = Eurydice_slice_len(last[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (last_len > (size_t)0U) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, last_len, uint8_t); Eurydice_slice_copy(uu____0, last[i0], uint8_t); } blocks[i0][last_len] = 31U; size_t uu____1 = i0; size_t uu____2 = (size_t)168U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } uint64_t(*uu____3)[5U] = s->st; uint8_t uu____4[1U][200U]; memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d21(uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** Absorb */ static KRML_MUSTINLINE void libcrux_sha3_portable_incremental_shake128_absorb_final( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice data0) { Eurydice_slice buf[1U] = {data0}; libcrux_sha3_generic_keccak_absorb_final_c72(s, buf); } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_581( uint64_t (*s)[5U], Eurydice_slice out[1U]) { for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)8U; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_5a_591( uint64_t (*a)[5U], Eurydice_slice b[1U]) { libcrux_sha3_portable_keccak_store_block_581(a, b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block with types uint64_t with const generics - N= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_next_block_fc1( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(s); libcrux_sha3_portable_keccak_store_block_5a_591(s->st, out); } /** Squeeze another block */ static KRML_MUSTINLINE void libcrux_sha3_portable_incremental_shake128_squeeze_next_block( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out0) { Eurydice_slice buf[1U] = {out0}; libcrux_sha3_generic_keccak_squeeze_next_block_fc1(s, buf); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block with types uint64_t with const generics - N= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_block_841( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_portable_keccak_store_block_5a_591(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_three_blocks with types uint64_t with const generics - N= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_three_blocks_cc( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { Eurydice_slice_uint8_t_1size_t__x2 uu____0 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)168U); Eurydice_slice o0[1U]; memcpy(o0, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o10[1U]; memcpy(o10, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_841(s, o0); Eurydice_slice_uint8_t_1size_t__x2 uu____1 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o10, (size_t)168U); Eurydice_slice o1[1U]; memcpy(o1, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o2[1U]; memcpy(o2, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc1(s, o1); libcrux_sha3_generic_keccak_squeeze_next_block_fc1(s, o2); } /** Squeeze three blocks */ static KRML_MUSTINLINE void libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out0) { Eurydice_slice buf[1U] = {out0}; libcrux_sha3_generic_keccak_squeeze_first_three_blocks_cc(s, buf); } #define libcrux_sha3_Sha224 0 #define libcrux_sha3_Sha256 1 #define libcrux_sha3_Sha384 2 #define libcrux_sha3_Sha512 3 typedef uint8_t libcrux_sha3_Algorithm; /** Returns the output size of a digest. */ static inline size_t libcrux_sha3_digest_size(libcrux_sha3_Algorithm mode) { size_t uu____0; switch (mode) { case libcrux_sha3_Sha224: { uu____0 = (size_t)28U; break; } case libcrux_sha3_Sha256: { uu____0 = (size_t)32U; break; } case libcrux_sha3_Sha384: { uu____0 = (size_t)48U; break; } case libcrux_sha3_Sha512: { uu____0 = (size_t)64U; break; } default: { KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__); KRML_HOST_EXIT(253U); } } return uu____0; } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_2c2( uint64_t (*s)[5U], Eurydice_slice blocks[1U]) { for (size_t i = (size_t)0U; i < (size_t)144U / (size_t)8U; i++) { size_t i0 = i; uint8_t uu____0[8U]; Result_56 dst; Eurydice_slice_to_array2( &dst, Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t), Eurydice_slice, uint8_t[8U]); unwrap_41_ac(dst, uu____0); size_t uu____1 = i0 / (size_t)5U; size_t uu____2 = i0 % (size_t)5U; s[uu____1][uu____2] = s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_5a_b81( uint64_t (*a)[5U], Eurydice_slice b[1U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_b[1U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_2c2(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block with types uint64_t with const generics - N= 1 - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_block_df1( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) { uint64_t(*uu____0)[5U] = s->st; Eurydice_slice uu____1[1U]; memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_5a_b81(uu____0, uu____1); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_df2( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t)}; libcrux_sha3_portable_keccak_load_block_2c2(s, buf); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_5a_d22( uint64_t (*a)[5U], uint8_t b[1U][200U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_b[1U][200U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_df2(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final with types uint64_t with const generics - N= 1 - RATE= 144 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_c73( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) { size_t last_len = Eurydice_slice_len(last[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (last_len > (size_t)0U) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, last_len, uint8_t); Eurydice_slice_copy(uu____0, last[i0], uint8_t); } blocks[i0][last_len] = 6U; size_t uu____1 = i0; size_t uu____2 = (size_t)144U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } uint64_t(*uu____3)[5U] = s->st; uint8_t uu____4[1U][200U]; memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d22(uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_582( uint64_t (*s)[5U], Eurydice_slice out[1U]) { for (size_t i = (size_t)0U; i < (size_t)144U / (size_t)8U; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); } } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_2d1( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t)}; libcrux_sha3_portable_keccak_store_block_582(s, buf); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_out[200U]; memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_5a_291(uint64_t (*a)[5U], uint8_t ret[1U][200U]) { libcrux_sha3_portable_keccak_store_block_full_2d1(a, ret); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last with types uint64_t with const generics - N= 1 - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_and_last_c51( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_291(s->st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a with const generics - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_5a_592( uint64_t (*a)[5U], Eurydice_slice b[1U]) { libcrux_sha3_portable_keccak_store_block_582(a, b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block with types uint64_t with const generics - N= 1 - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_block_842( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_portable_keccak_store_block_5a_592(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block with types uint64_t with const generics - N= 1 - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_next_block_fc2( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(s); libcrux_sha3_portable_keccak_store_block_5a_592(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last with types uint64_t with const generics - N= 1 - RATE= 144 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_last_cf1( libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(&s); uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_291(s.st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** A monomorphic instance of libcrux_sha3.generic_keccak.keccak with types uint64_t with const generics - N= 1 - RATE= 144 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_keccak_e92( Eurydice_slice data[1U], Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_KeccakState_48 s = libcrux_sha3_generic_keccak_new_1e_f4(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)144U; i++) { size_t i0 = i; libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)144U, (size_t)144U, ret); libcrux_sha3_generic_keccak_absorb_block_df1(uu____0, ret); } size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)144U; libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); libcrux_sha3_generic_keccak_absorb_final_c73(uu____2, ret); size_t outlen = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = outlen / (size_t)144U; size_t last = outlen - outlen % (size_t)144U; if (blocks == (size_t)0U) { libcrux_sha3_generic_keccak_squeeze_first_and_last_c51(&s, out); } else { Eurydice_slice_uint8_t_1size_t__x2 uu____4 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)144U); Eurydice_slice o0[1U]; memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o1[1U]; memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_842(&s, o0); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____5 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)144U); Eurydice_slice o[1U]; memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice orest[1U]; memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc2(&s, o); memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < outlen) { libcrux_sha3_generic_keccak_squeeze_last_cf1(s, o1); } } } /** A monomorphic instance of libcrux_sha3.portable.keccakx1 with const generics - RATE= 144 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccakx1_ce2( Eurydice_slice data[1U], Eurydice_slice out[1U]) { /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccak_e92(copy_of_data, out); } /** A portable SHA3 224 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_portable_sha224(Eurydice_slice digest, Eurydice_slice data) { Eurydice_slice buf0[1U] = {data}; Eurydice_slice buf[1U] = {digest}; libcrux_sha3_portable_keccakx1_ce2(buf0, buf); } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_2c3( uint64_t (*s)[5U], Eurydice_slice blocks[1U]) { for (size_t i = (size_t)0U; i < (size_t)104U / (size_t)8U; i++) { size_t i0 = i; uint8_t uu____0[8U]; Result_56 dst; Eurydice_slice_to_array2( &dst, Eurydice_slice_subslice2(blocks[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t), Eurydice_slice, uint8_t[8U]); unwrap_41_ac(dst, uu____0); size_t uu____1 = i0 / (size_t)5U; size_t uu____2 = i0 % (size_t)5U; s[uu____1][uu____2] = s[uu____1][uu____2] ^ core_num__u64_9__from_le_bytes(uu____0); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_5a_b82( uint64_t (*a)[5U], Eurydice_slice b[1U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_b[1U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_2c3(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block with types uint64_t with const generics - N= 1 - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_block_df2( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) { uint64_t(*uu____0)[5U] = s->st; Eurydice_slice uu____1[1U]; memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_5a_b82(uu____0, uu____1); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_df3( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t)}; libcrux_sha3_portable_keccak_load_block_2c3(s, buf); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_full_5a with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_full_5a_d23( uint64_t (*a)[5U], uint8_t b[1U][200U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_b[1U][200U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_df3(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final with types uint64_t with const generics - N= 1 - RATE= 104 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_c74( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice last[1U]) { size_t last_len = Eurydice_slice_len(last[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (last_len > (size_t)0U) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, last_len, uint8_t); Eurydice_slice_copy(uu____0, last[i0], uint8_t); } blocks[i0][last_len] = 6U; size_t uu____1 = i0; size_t uu____2 = (size_t)104U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } uint64_t(*uu____3)[5U] = s->st; uint8_t uu____4[1U][200U]; memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d23(uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_583( uint64_t (*s)[5U], Eurydice_slice out[1U]) { for (size_t i = (size_t)0U; i < (size_t)104U / (size_t)8U; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out[0U], (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes(s[i0 / (size_t)5U][i0 % (size_t)5U], ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); } } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_2d2( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t)}; libcrux_sha3_portable_keccak_store_block_583(s, buf); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_out[200U]; memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_5a_292(uint64_t (*a)[5U], uint8_t ret[1U][200U]) { libcrux_sha3_portable_keccak_store_block_full_2d2(a, ret); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last with types uint64_t with const generics - N= 1 - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_and_last_c52( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_292(s->st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_5a with const generics - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_5a_593( uint64_t (*a)[5U], Eurydice_slice b[1U]) { libcrux_sha3_portable_keccak_store_block_583(a, b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_block with types uint64_t with const generics - N= 1 - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_block_843( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_portable_keccak_store_block_5a_593(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_next_block with types uint64_t with const generics - N= 1 - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_next_block_fc3( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(s); libcrux_sha3_portable_keccak_store_block_5a_593(s->st, out); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last with types uint64_t with const generics - N= 1 - RATE= 104 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_last_cf2( libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(&s); uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_292(s.st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** A monomorphic instance of libcrux_sha3.generic_keccak.keccak with types uint64_t with const generics - N= 1 - RATE= 104 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_keccak_e93( Eurydice_slice data[1U], Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_KeccakState_48 s = libcrux_sha3_generic_keccak_new_1e_f4(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)104U; i++) { size_t i0 = i; libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)104U, (size_t)104U, ret); libcrux_sha3_generic_keccak_absorb_block_df2(uu____0, ret); } size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)104U; libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); libcrux_sha3_generic_keccak_absorb_final_c74(uu____2, ret); size_t outlen = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = outlen / (size_t)104U; size_t last = outlen - outlen % (size_t)104U; if (blocks == (size_t)0U) { libcrux_sha3_generic_keccak_squeeze_first_and_last_c52(&s, out); } else { Eurydice_slice_uint8_t_1size_t__x2 uu____4 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)104U); Eurydice_slice o0[1U]; memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o1[1U]; memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_843(&s, o0); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____5 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)104U); Eurydice_slice o[1U]; memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice orest[1U]; memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc3(&s, o); memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < outlen) { libcrux_sha3_generic_keccak_squeeze_last_cf2(s, o1); } } } /** A monomorphic instance of libcrux_sha3.portable.keccakx1 with const generics - RATE= 104 - DELIM= 6 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccakx1_ce3( Eurydice_slice data[1U], Eurydice_slice out[1U]) { /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccak_e93(copy_of_data, out); } /** A portable SHA3 384 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_portable_sha384(Eurydice_slice digest, Eurydice_slice data) { Eurydice_slice buf0[1U] = {data}; Eurydice_slice buf[1U] = {digest}; libcrux_sha3_portable_keccakx1_ce3(buf0, buf); } /** SHA3 224 Preconditions: - `digest.len() == 28` */ static KRML_MUSTINLINE void libcrux_sha3_sha224_ema(Eurydice_slice digest, Eurydice_slice payload) { libcrux_sha3_portable_sha224(digest, payload); } /** SHA3 224 */ static KRML_MUSTINLINE void libcrux_sha3_sha224(Eurydice_slice data, uint8_t ret[28U]) { uint8_t out[28U] = {0U}; libcrux_sha3_sha224_ema(Eurydice_array_to_slice((size_t)28U, out, uint8_t), data); memcpy(ret, out, (size_t)28U * sizeof(uint8_t)); } /** SHA3 256 */ static KRML_MUSTINLINE void libcrux_sha3_sha256_ema(Eurydice_slice digest, Eurydice_slice payload) { libcrux_sha3_portable_sha256(digest, payload); } /** SHA3 256 */ static KRML_MUSTINLINE void libcrux_sha3_sha256(Eurydice_slice data, uint8_t ret[32U]) { uint8_t out[32U] = {0U}; libcrux_sha3_sha256_ema(Eurydice_array_to_slice((size_t)32U, out, uint8_t), data); memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } /** SHA3 384 */ static KRML_MUSTINLINE void libcrux_sha3_sha384_ema(Eurydice_slice digest, Eurydice_slice payload) { libcrux_sha3_portable_sha384(digest, payload); } /** SHA3 384 */ static KRML_MUSTINLINE void libcrux_sha3_sha384(Eurydice_slice data, uint8_t ret[48U]) { uint8_t out[48U] = {0U}; libcrux_sha3_sha384_ema(Eurydice_array_to_slice((size_t)48U, out, uint8_t), data); memcpy(ret, out, (size_t)48U * sizeof(uint8_t)); } /** SHA3 512 */ static KRML_MUSTINLINE void libcrux_sha3_sha512_ema(Eurydice_slice digest, Eurydice_slice payload) { libcrux_sha3_portable_sha512(digest, payload); } /** SHA3 512 */ static KRML_MUSTINLINE void libcrux_sha3_sha512(Eurydice_slice data, uint8_t ret[64U]) { uint8_t out[64U] = {0U}; libcrux_sha3_sha512_ema(Eurydice_array_to_slice((size_t)64U, out, uint8_t), data); memcpy(ret, out, (size_t)64U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.load_block_5a with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_load_block_5a_b83( uint64_t (*a)[5U], Eurydice_slice b[1U]) { uint64_t(*uu____0)[5U] = a; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_b[1U]; memcpy(copy_of_b, b, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_2c1(uu____0, copy_of_b); } /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_block with types uint64_t with const generics - N= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_block_df3( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice blocks[1U]) { uint64_t(*uu____0)[5U] = s->st; Eurydice_slice uu____1[1U]; memcpy(uu____1, blocks, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_5a_b83(uu____0, uu____1); libcrux_sha3_generic_keccak_keccakf1600_21(s); } /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_2d3( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t)}; libcrux_sha3_portable_keccak_store_block_581(s, buf); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_out[200U]; memcpy(copy_of_out, out, (size_t)200U * sizeof(uint8_t)); memcpy(ret[0U], copy_of_out, (size_t)200U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_block_full_5a with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_block_full_5a_293(uint64_t (*a)[5U], uint8_t ret[1U][200U]) { libcrux_sha3_portable_keccak_store_block_full_2d3(a, ret); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_and_last with types uint64_t with const generics - N= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_and_last_c53( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_293(s->st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_last with types uint64_t with const generics - N= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_last_cf3( libcrux_sha3_generic_keccak_KeccakState_48 s, Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_keccakf1600_21(&s); uint8_t b[1U][200U]; libcrux_sha3_portable_keccak_store_block_full_5a_293(s.st, b); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; core_ops_range_Range_b3 lit; lit.start = (size_t)0U; lit.end = Eurydice_slice_len(out[i0], uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, core_ops_range_Range_b3), uint8_t); } } /** A monomorphic instance of libcrux_sha3.generic_keccak.keccak with types uint64_t with const generics - N= 1 - RATE= 168 - DELIM= 31 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_keccak_e94( Eurydice_slice data[1U], Eurydice_slice out[1U]) { libcrux_sha3_generic_keccak_KeccakState_48 s = libcrux_sha3_generic_keccak_new_1e_f4(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(data[0U], uint8_t) / (size_t)168U; i++) { size_t i0 = i; libcrux_sha3_generic_keccak_KeccakState_48 *uu____0 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a(copy_of_data, i0 * (size_t)168U, (size_t)168U, ret); libcrux_sha3_generic_keccak_absorb_block_df3(uu____0, ret); } size_t rem = Eurydice_slice_len(data[0U], uint8_t) % (size_t)168U; libcrux_sha3_generic_keccak_KeccakState_48 *uu____2 = &s; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_data, Eurydice_slice_len(data[0U], uint8_t) - rem, rem, ret); libcrux_sha3_generic_keccak_absorb_final_c72(uu____2, ret); size_t outlen = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = outlen / (size_t)168U; size_t last = outlen - outlen % (size_t)168U; if (blocks == (size_t)0U) { libcrux_sha3_generic_keccak_squeeze_first_and_last_c53(&s, out); } else { Eurydice_slice_uint8_t_1size_t__x2 uu____4 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)168U); Eurydice_slice o0[1U]; memcpy(o0, uu____4.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o1[1U]; memcpy(o1, uu____4.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_841(&s, o0); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____5 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o1, (size_t)168U); Eurydice_slice o[1U]; memcpy(o, uu____5.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice orest[1U]; memcpy(orest, uu____5.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc1(&s, o); memcpy(o1, orest, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < outlen) { libcrux_sha3_generic_keccak_squeeze_last_cf3(s, o1); } } } /** A monomorphic instance of libcrux_sha3.portable.keccakx1 with const generics - RATE= 168 - DELIM= 31 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccakx1_ce4( Eurydice_slice data[1U], Eurydice_slice out[1U]) { /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_data[1U]; memcpy(copy_of_data, data, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccak_e94(copy_of_data, out); } /** A portable SHAKE128 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_portable_shake128( Eurydice_slice digest, Eurydice_slice data) { Eurydice_slice buf0[1U] = {data}; Eurydice_slice buf[1U] = {digest}; libcrux_sha3_portable_keccakx1_ce4(buf0, buf); } /** SHAKE 128 Writes `out.len()` bytes. */ static KRML_MUSTINLINE void libcrux_sha3_shake128_ema(Eurydice_slice out, Eurydice_slice data) { libcrux_sha3_portable_shake128(out, data); } /** SHAKE 256 Writes `out.len()` bytes. */ static KRML_MUSTINLINE void libcrux_sha3_shake256_ema(Eurydice_slice out, Eurydice_slice data) { libcrux_sha3_portable_shake256(out, data); } static const size_t libcrux_sha3_generic_keccak__PI[24U] = { (size_t)6U, (size_t)12U, (size_t)18U, (size_t)24U, (size_t)3U, (size_t)9U, (size_t)10U, (size_t)16U, (size_t)22U, (size_t)1U, (size_t)7U, (size_t)13U, (size_t)19U, (size_t)20U, (size_t)4U, (size_t)5U, (size_t)11U, (size_t)17U, (size_t)23U, (size_t)2U, (size_t)8U, (size_t)14U, (size_t)15U, (size_t)21U}; static const size_t libcrux_sha3_generic_keccak__ROTC[24U] = { (size_t)1U, (size_t)62U, (size_t)28U, (size_t)27U, (size_t)36U, (size_t)44U, (size_t)6U, (size_t)55U, (size_t)20U, (size_t)3U, (size_t)10U, (size_t)43U, (size_t)25U, (size_t)39U, (size_t)41U, (size_t)45U, (size_t)15U, (size_t)21U, (size_t)8U, (size_t)18U, (size_t)2U, (size_t)61U, (size_t)56U, (size_t)14U}; /** A portable SHA3 224 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_neon_sha224(Eurydice_slice digest, Eurydice_slice data) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** A portable SHA3 256 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_neon_sha256(Eurydice_slice digest, Eurydice_slice data) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** A portable SHA3 384 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_neon_sha384(Eurydice_slice digest, Eurydice_slice data) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** A portable SHA3 512 implementation. */ static KRML_MUSTINLINE void libcrux_sha3_neon_sha512(Eurydice_slice digest, Eurydice_slice data) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** Run SHAKE256 on both inputs in parallel. Writes the two results into `out0` and `out1` */ static KRML_MUSTINLINE void libcrux_sha3_neon_x2_shake256(Eurydice_slice input0, Eurydice_slice input1, Eurydice_slice out0, Eurydice_slice out1) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } typedef struct libcrux_sha3_neon_x2_incremental_KeccakState_s { libcrux_sha3_generic_keccak_KeccakState_48 state[2U]; } libcrux_sha3_neon_x2_incremental_KeccakState; /** Initialise the `KeccakState2`. */ static KRML_MUSTINLINE libcrux_sha3_neon_x2_incremental_KeccakState libcrux_sha3_neon_x2_incremental_shake128_init(void) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** Shake128 absorb `data0` and `data1` in the [`KeccakState`] `s`. */ static KRML_MUSTINLINE void libcrux_sha3_neon_x2_incremental_shake128_absorb_final( libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice data0, Eurydice_slice data1) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** Squeeze 2 times the first three blocks in parallel in the [`KeccakState`] and return the output in `out0` and `out1`. */ static KRML_MUSTINLINE void libcrux_sha3_neon_x2_incremental_shake128_squeeze_first_three_blocks( libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** Squeeze 2 times the next block in parallel in the [`KeccakState`] and return the output in `out0` and `out1`. */ static KRML_MUSTINLINE void libcrux_sha3_neon_x2_incremental_shake128_squeeze_next_block( libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_first_five_blocks with types uint64_t with const generics - N= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_first_five_blocks_4f( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out[1U]) { Eurydice_slice_uint8_t_1size_t__x2 uu____0 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, (size_t)168U); Eurydice_slice o0[1U]; memcpy(o0, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o10[1U]; memcpy(o10, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_first_block_841(s, o0); Eurydice_slice_uint8_t_1size_t__x2 uu____1 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o10, (size_t)168U); Eurydice_slice o1[1U]; memcpy(o1, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o20[1U]; memcpy(o20, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc1(s, o1); Eurydice_slice_uint8_t_1size_t__x2 uu____2 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o20, (size_t)168U); Eurydice_slice o2[1U]; memcpy(o2, uu____2.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o30[1U]; memcpy(o30, uu____2.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc1(s, o2); Eurydice_slice_uint8_t_1size_t__x2 uu____3 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(o30, (size_t)168U); Eurydice_slice o3[1U]; memcpy(o3, uu____3.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice o4[1U]; memcpy(o4, uu____3.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_squeeze_next_block_fc1(s, o3); libcrux_sha3_generic_keccak_squeeze_next_block_fc1(s, o4); } /** Squeeze five blocks */ static KRML_MUSTINLINE void libcrux_sha3_portable_incremental_shake128_squeeze_first_five_blocks( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out0) { Eurydice_slice buf[1U] = {out0}; libcrux_sha3_generic_keccak_squeeze_first_five_blocks_4f(s, buf); } /** Absorb some data for SHAKE-256 for the last time */ static KRML_MUSTINLINE void libcrux_sha3_portable_incremental_shake256_absorb_final( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice data) { Eurydice_slice buf[1U] = {data}; libcrux_sha3_generic_keccak_absorb_final_c71(s, buf); } /** Create a new SHAKE-256 state object. */ static KRML_MUSTINLINE libcrux_sha3_generic_keccak_KeccakState_48 libcrux_sha3_portable_incremental_shake256_init(void) { return libcrux_sha3_generic_keccak_new_1e_f4(); } /** Squeeze the first SHAKE-256 block */ static KRML_MUSTINLINE void libcrux_sha3_portable_incremental_shake256_squeeze_first_block( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out) { Eurydice_slice buf[1U] = {out}; libcrux_sha3_generic_keccak_squeeze_first_block_840(s, buf); } /** Squeeze the next SHAKE-256 block */ static KRML_MUSTINLINE void libcrux_sha3_portable_incremental_shake256_squeeze_next_block( libcrux_sha3_generic_keccak_KeccakState_48 *s, Eurydice_slice out) { Eurydice_slice buf[1U] = {out}; libcrux_sha3_generic_keccak_squeeze_next_block_fc0(s, buf); } /** A monomorphic instance of libcrux_sha3.generic_keccak.KeccakXofState with types uint64_t with const generics - $1size_t - $136size_t */ typedef struct libcrux_sha3_generic_keccak_KeccakXofState_4f_s { libcrux_sha3_generic_keccak_KeccakState_48 inner; uint8_t buf[1U][136U]; size_t buf_len; bool sponge; } libcrux_sha3_generic_keccak_KeccakXofState_4f; typedef libcrux_sha3_generic_keccak_KeccakXofState_4f libcrux_sha3_portable_incremental_Shake256Absorb; /** Consume the internal buffer and the required amount of the input to pad to `RATE`. Returns the `consumed` bytes from `inputs` if there's enough buffered content to consume, and `0` otherwise. If `consumed > 0` is returned, `self.buf` contains a full block to be loaded. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.fill_buffer_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 136 */ static inline size_t libcrux_sha3_generic_keccak_fill_buffer_9d_b0( libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice inputs[1U]) { size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); size_t consumed = (size_t)0U; if (self->buf_len > (size_t)0U) { if (self->buf_len + input_len >= (size_t)136U) { consumed = (size_t)136U - self->buf_len; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( (size_t)136U, self->buf[i0], self->buf_len, uint8_t, size_t); Eurydice_slice_copy( uu____0, Eurydice_slice_subslice_to(inputs[i0], consumed, uint8_t, size_t), uint8_t); } self->buf_len = self->buf_len + consumed; } } return consumed; } /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_full_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 136 */ static inline size_t libcrux_sha3_generic_keccak_absorb_full_9d_f8( libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice inputs[1U]) { libcrux_sha3_generic_keccak_KeccakXofState_4f *uu____0 = self; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs0[1U]; memcpy(copy_of_inputs0, inputs, (size_t)1U * sizeof(Eurydice_slice)); size_t input_consumed = libcrux_sha3_generic_keccak_fill_buffer_9d_b0(uu____0, copy_of_inputs0); if (input_consumed > (size_t)0U) { Eurydice_slice borrowed[1U]; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { uint8_t buf[136U] = {0U}; borrowed[i] = core_array___Array_T__N__23__as_slice( (size_t)136U, buf, uint8_t, Eurydice_slice); } for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; borrowed[i0] = Eurydice_array_to_slice((size_t)136U, self->buf[i0], uint8_t); } uint64_t(*uu____2)[5U] = self->inner.st; Eurydice_slice uu____3[1U]; memcpy(uu____3, borrowed, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_5a_b80(uu____2, uu____3); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); self->buf_len = (size_t)0U; } size_t input_to_consume = Eurydice_slice_len(inputs[0U], uint8_t) - input_consumed; size_t num_blocks = input_to_consume / (size_t)136U; size_t remainder = input_to_consume % (size_t)136U; for (size_t i = (size_t)0U; i < num_blocks; i++) { size_t i0 = i; uint64_t(*uu____4)[5U] = self->inner.st; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs[1U]; memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_inputs, input_consumed + i0 * (size_t)136U, (size_t)136U, ret); libcrux_sha3_portable_keccak_load_block_5a_b80(uu____4, ret); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); } return remainder; } /** Absorb This function takes any number of bytes to absorb and buffers if it's not enough. The function assumes that all input slices in `blocks` have the same length. Only a multiple of `RATE` blocks are absorbed. For the remaining bytes [`absorb_final`] needs to be called. This works best with relatively small `inputs`. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_9d_7b( libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice inputs[1U]) { libcrux_sha3_generic_keccak_KeccakXofState_4f *uu____0 = self; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs[1U]; memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); size_t input_remainder_len = libcrux_sha3_generic_keccak_absorb_full_9d_f8(uu____0, copy_of_inputs); if (input_remainder_len > (size_t)0U) { size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____2 = Eurydice_array_to_subslice2( self->buf[i0], self->buf_len, self->buf_len + input_remainder_len, uint8_t); Eurydice_slice_copy( uu____2, Eurydice_slice_subslice_from( inputs[i0], input_len - input_remainder_len, uint8_t, size_t), uint8_t); } self->buf_len = self->buf_len + input_remainder_len; } } /** Shake256 absorb */ /** This function found in impl {(libcrux_sha3::portable::incremental::XofAbsorb<136: usize> for libcrux_sha3::portable::incremental::Shake256Absorb)#2} */ static inline void libcrux_sha3_portable_incremental_absorb_7d( libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice input) { Eurydice_slice buf[1U] = {input}; libcrux_sha3_generic_keccak_absorb_9d_7b(self, buf); } typedef libcrux_sha3_generic_keccak_KeccakXofState_4f libcrux_sha3_portable_incremental_Shake256Squeeze; /** Absorb a final block. The `inputs` block may be empty. Everything in the `inputs` block beyond `RATE` bytes is ignored. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 136 - DELIMITER= 31 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_9d_25( libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice inputs[1U]) { libcrux_sha3_generic_keccak_KeccakXofState_4f *uu____0 = self; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs[1U]; memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); size_t input_remainder_len = libcrux_sha3_generic_keccak_absorb_full_9d_f8(uu____0, copy_of_inputs); size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (self->buf_len > (size_t)0U) { Eurydice_slice uu____2 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, self->buf_len, uint8_t); Eurydice_slice_copy(uu____2, Eurydice_array_to_subslice2(self->buf[i0], (size_t)0U, self->buf_len, uint8_t), uint8_t); } if (input_remainder_len > (size_t)0U) { Eurydice_slice uu____3 = Eurydice_array_to_subslice2( blocks[i0], self->buf_len, self->buf_len + input_remainder_len, uint8_t); Eurydice_slice_copy( uu____3, Eurydice_slice_subslice_from( inputs[i0], input_len - input_remainder_len, uint8_t, size_t), uint8_t); } blocks[i0][self->buf_len + input_remainder_len] = 31U; size_t uu____4 = i0; size_t uu____5 = (size_t)136U - (size_t)1U; blocks[uu____4][uu____5] = (uint32_t)blocks[uu____4][uu____5] | 128U; } uint64_t(*uu____6)[5U] = self->inner.st; uint8_t uu____7[1U][200U]; memcpy(uu____7, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d20(uu____6, uu____7); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); } /** Shake256 absorb final */ /** This function found in impl {(libcrux_sha3::portable::incremental::XofAbsorb<136: usize> for libcrux_sha3::portable::incremental::Shake256Absorb)#2} */ static inline libcrux_sha3_generic_keccak_KeccakXofState_4f libcrux_sha3_portable_incremental_absorb_final_7d( libcrux_sha3_generic_keccak_KeccakXofState_4f self, Eurydice_slice input) { Eurydice_slice buf[1U] = {input}; libcrux_sha3_generic_keccak_absorb_final_9d_25(&self, buf); return self; } /** An all zero block */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.zero_block_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 136 */ static inline void libcrux_sha3_generic_keccak_zero_block_9d_e6( uint8_t ret[136U]) { ret[0U] = 0U; ret[1U] = 0U; ret[2U] = 0U; ret[3U] = 0U; ret[4U] = 0U; ret[5U] = 0U; ret[6U] = 0U; ret[7U] = 0U; ret[8U] = 0U; ret[9U] = 0U; ret[10U] = 0U; ret[11U] = 0U; ret[12U] = 0U; ret[13U] = 0U; ret[14U] = 0U; ret[15U] = 0U; ret[16U] = 0U; ret[17U] = 0U; ret[18U] = 0U; ret[19U] = 0U; ret[20U] = 0U; ret[21U] = 0U; ret[22U] = 0U; ret[23U] = 0U; ret[24U] = 0U; ret[25U] = 0U; ret[26U] = 0U; ret[27U] = 0U; ret[28U] = 0U; ret[29U] = 0U; ret[30U] = 0U; ret[31U] = 0U; ret[32U] = 0U; ret[33U] = 0U; ret[34U] = 0U; ret[35U] = 0U; ret[36U] = 0U; ret[37U] = 0U; ret[38U] = 0U; ret[39U] = 0U; ret[40U] = 0U; ret[41U] = 0U; ret[42U] = 0U; ret[43U] = 0U; ret[44U] = 0U; ret[45U] = 0U; ret[46U] = 0U; ret[47U] = 0U; ret[48U] = 0U; ret[49U] = 0U; ret[50U] = 0U; ret[51U] = 0U; ret[52U] = 0U; ret[53U] = 0U; ret[54U] = 0U; ret[55U] = 0U; ret[56U] = 0U; ret[57U] = 0U; ret[58U] = 0U; ret[59U] = 0U; ret[60U] = 0U; ret[61U] = 0U; ret[62U] = 0U; ret[63U] = 0U; ret[64U] = 0U; ret[65U] = 0U; ret[66U] = 0U; ret[67U] = 0U; ret[68U] = 0U; ret[69U] = 0U; ret[70U] = 0U; ret[71U] = 0U; ret[72U] = 0U; ret[73U] = 0U; ret[74U] = 0U; ret[75U] = 0U; ret[76U] = 0U; ret[77U] = 0U; ret[78U] = 0U; ret[79U] = 0U; ret[80U] = 0U; ret[81U] = 0U; ret[82U] = 0U; ret[83U] = 0U; ret[84U] = 0U; ret[85U] = 0U; ret[86U] = 0U; ret[87U] = 0U; ret[88U] = 0U; ret[89U] = 0U; ret[90U] = 0U; ret[91U] = 0U; ret[92U] = 0U; ret[93U] = 0U; ret[94U] = 0U; ret[95U] = 0U; ret[96U] = 0U; ret[97U] = 0U; ret[98U] = 0U; ret[99U] = 0U; ret[100U] = 0U; ret[101U] = 0U; ret[102U] = 0U; ret[103U] = 0U; ret[104U] = 0U; ret[105U] = 0U; ret[106U] = 0U; ret[107U] = 0U; ret[108U] = 0U; ret[109U] = 0U; ret[110U] = 0U; ret[111U] = 0U; ret[112U] = 0U; ret[113U] = 0U; ret[114U] = 0U; ret[115U] = 0U; ret[116U] = 0U; ret[117U] = 0U; ret[118U] = 0U; ret[119U] = 0U; ret[120U] = 0U; ret[121U] = 0U; ret[122U] = 0U; ret[123U] = 0U; ret[124U] = 0U; ret[125U] = 0U; ret[126U] = 0U; ret[127U] = 0U; ret[128U] = 0U; ret[129U] = 0U; ret[130U] = 0U; ret[131U] = 0U; ret[132U] = 0U; ret[133U] = 0U; ret[134U] = 0U; ret[135U] = 0U; } /** Generate a new keccak xof state. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.new_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 136 */ static inline libcrux_sha3_generic_keccak_KeccakXofState_4f libcrux_sha3_generic_keccak_new_9d_7e(void) { libcrux_sha3_generic_keccak_KeccakXofState_4f lit; lit.inner = libcrux_sha3_generic_keccak_new_1e_f4(); uint8_t ret[136U]; libcrux_sha3_generic_keccak_zero_block_9d_e6(ret); memcpy(lit.buf[0U], ret, (size_t)136U * sizeof(uint8_t)); lit.buf_len = (size_t)0U; lit.sponge = false; return lit; } /** Shake256 new state */ /** This function found in impl {(libcrux_sha3::portable::incremental::XofAbsorb<136: usize> for libcrux_sha3::portable::incremental::Shake256Absorb)#2} */ static inline libcrux_sha3_generic_keccak_KeccakXofState_4f libcrux_sha3_portable_incremental_new_7d(void) { return libcrux_sha3_generic_keccak_new_9d_7e(); } /** A monomorphic instance of libcrux_sha3.generic_keccak.KeccakXofState with types uint64_t with const generics - $1size_t - $168size_t */ typedef struct libcrux_sha3_generic_keccak_KeccakXofState_78_s { libcrux_sha3_generic_keccak_KeccakState_48 inner; uint8_t buf[1U][168U]; size_t buf_len; bool sponge; } libcrux_sha3_generic_keccak_KeccakXofState_78; typedef libcrux_sha3_generic_keccak_KeccakXofState_78 libcrux_sha3_portable_incremental_Shake128Absorb; /** Consume the internal buffer and the required amount of the input to pad to `RATE`. Returns the `consumed` bytes from `inputs` if there's enough buffered content to consume, and `0` otherwise. If `consumed > 0` is returned, `self.buf` contains a full block to be loaded. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.fill_buffer_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 168 */ static inline size_t libcrux_sha3_generic_keccak_fill_buffer_9d_b00( libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice inputs[1U]) { size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); size_t consumed = (size_t)0U; if (self->buf_len > (size_t)0U) { if (self->buf_len + input_len >= (size_t)168U) { consumed = (size_t)168U - self->buf_len; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( (size_t)168U, self->buf[i0], self->buf_len, uint8_t, size_t); Eurydice_slice_copy( uu____0, Eurydice_slice_subslice_to(inputs[i0], consumed, uint8_t, size_t), uint8_t); } self->buf_len = self->buf_len + consumed; } } return consumed; } /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_full_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 168 */ static inline size_t libcrux_sha3_generic_keccak_absorb_full_9d_f80( libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice inputs[1U]) { libcrux_sha3_generic_keccak_KeccakXofState_78 *uu____0 = self; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs0[1U]; memcpy(copy_of_inputs0, inputs, (size_t)1U * sizeof(Eurydice_slice)); size_t input_consumed = libcrux_sha3_generic_keccak_fill_buffer_9d_b00(uu____0, copy_of_inputs0); if (input_consumed > (size_t)0U) { Eurydice_slice borrowed[1U]; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { uint8_t buf[168U] = {0U}; borrowed[i] = core_array___Array_T__N__23__as_slice( (size_t)168U, buf, uint8_t, Eurydice_slice); } for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; borrowed[i0] = Eurydice_array_to_slice((size_t)168U, self->buf[i0], uint8_t); } uint64_t(*uu____2)[5U] = self->inner.st; Eurydice_slice uu____3[1U]; memcpy(uu____3, borrowed, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_load_block_5a_b83(uu____2, uu____3); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); self->buf_len = (size_t)0U; } size_t input_to_consume = Eurydice_slice_len(inputs[0U], uint8_t) - input_consumed; size_t num_blocks = input_to_consume / (size_t)168U; size_t remainder = input_to_consume % (size_t)168U; for (size_t i = (size_t)0U; i < num_blocks; i++) { size_t i0 = i; uint64_t(*uu____4)[5U] = self->inner.st; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs[1U]; memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice ret[1U]; libcrux_sha3_portable_keccak_slice_n_5a( copy_of_inputs, input_consumed + i0 * (size_t)168U, (size_t)168U, ret); libcrux_sha3_portable_keccak_load_block_5a_b83(uu____4, ret); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); } return remainder; } /** Absorb This function takes any number of bytes to absorb and buffers if it's not enough. The function assumes that all input slices in `blocks` have the same length. Only a multiple of `RATE` blocks are absorbed. For the remaining bytes [`absorb_final`] needs to be called. This works best with relatively small `inputs`. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_9d_7b0( libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice inputs[1U]) { libcrux_sha3_generic_keccak_KeccakXofState_78 *uu____0 = self; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs[1U]; memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); size_t input_remainder_len = libcrux_sha3_generic_keccak_absorb_full_9d_f80(uu____0, copy_of_inputs); if (input_remainder_len > (size_t)0U) { size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; Eurydice_slice uu____2 = Eurydice_array_to_subslice2( self->buf[i0], self->buf_len, self->buf_len + input_remainder_len, uint8_t); Eurydice_slice_copy( uu____2, Eurydice_slice_subslice_from( inputs[i0], input_len - input_remainder_len, uint8_t, size_t), uint8_t); } self->buf_len = self->buf_len + input_remainder_len; } } /** This function found in impl {(libcrux_sha3::portable::incremental::XofAbsorb<168: usize> for libcrux_sha3::portable::incremental::Shake128Absorb)} */ static inline void libcrux_sha3_portable_incremental_absorb_1c( libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice input) { Eurydice_slice buf[1U] = {input}; libcrux_sha3_generic_keccak_absorb_9d_7b0(self, buf); } typedef libcrux_sha3_generic_keccak_KeccakXofState_78 libcrux_sha3_portable_incremental_Shake128Squeeze; /** Absorb a final block. The `inputs` block may be empty. Everything in the `inputs` block beyond `RATE` bytes is ignored. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.absorb_final_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 168 - DELIMITER= 31 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_absorb_final_9d_250( libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice inputs[1U]) { libcrux_sha3_generic_keccak_KeccakXofState_78 *uu____0 = self; /* Passing arrays by value in Rust generates a copy in C */ Eurydice_slice copy_of_inputs[1U]; memcpy(copy_of_inputs, inputs, (size_t)1U * sizeof(Eurydice_slice)); size_t input_remainder_len = libcrux_sha3_generic_keccak_absorb_full_9d_f80(uu____0, copy_of_inputs); size_t input_len = Eurydice_slice_len(inputs[0U], uint8_t); uint8_t blocks[1U][200U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)1U; i++) { size_t i0 = i; if (self->buf_len > (size_t)0U) { Eurydice_slice uu____2 = Eurydice_array_to_subslice2( blocks[i0], (size_t)0U, self->buf_len, uint8_t); Eurydice_slice_copy(uu____2, Eurydice_array_to_subslice2(self->buf[i0], (size_t)0U, self->buf_len, uint8_t), uint8_t); } if (input_remainder_len > (size_t)0U) { Eurydice_slice uu____3 = Eurydice_array_to_subslice2( blocks[i0], self->buf_len, self->buf_len + input_remainder_len, uint8_t); Eurydice_slice_copy( uu____3, Eurydice_slice_subslice_from( inputs[i0], input_len - input_remainder_len, uint8_t, size_t), uint8_t); } blocks[i0][self->buf_len + input_remainder_len] = 31U; size_t uu____4 = i0; size_t uu____5 = (size_t)168U - (size_t)1U; blocks[uu____4][uu____5] = (uint32_t)blocks[uu____4][uu____5] | 128U; } uint64_t(*uu____6)[5U] = self->inner.st; uint8_t uu____7[1U][200U]; memcpy(uu____7, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak_load_block_full_5a_d21(uu____6, uu____7); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); } /** This function found in impl {(libcrux_sha3::portable::incremental::XofAbsorb<168: usize> for libcrux_sha3::portable::incremental::Shake128Absorb)} */ static inline libcrux_sha3_generic_keccak_KeccakXofState_78 libcrux_sha3_portable_incremental_absorb_final_1c( libcrux_sha3_generic_keccak_KeccakXofState_78 self, Eurydice_slice input) { Eurydice_slice buf[1U] = {input}; libcrux_sha3_generic_keccak_absorb_final_9d_250(&self, buf); return self; } /** An all zero block */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.zero_block_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 168 */ static inline void libcrux_sha3_generic_keccak_zero_block_9d_e60( uint8_t ret[168U]) { ret[0U] = 0U; ret[1U] = 0U; ret[2U] = 0U; ret[3U] = 0U; ret[4U] = 0U; ret[5U] = 0U; ret[6U] = 0U; ret[7U] = 0U; ret[8U] = 0U; ret[9U] = 0U; ret[10U] = 0U; ret[11U] = 0U; ret[12U] = 0U; ret[13U] = 0U; ret[14U] = 0U; ret[15U] = 0U; ret[16U] = 0U; ret[17U] = 0U; ret[18U] = 0U; ret[19U] = 0U; ret[20U] = 0U; ret[21U] = 0U; ret[22U] = 0U; ret[23U] = 0U; ret[24U] = 0U; ret[25U] = 0U; ret[26U] = 0U; ret[27U] = 0U; ret[28U] = 0U; ret[29U] = 0U; ret[30U] = 0U; ret[31U] = 0U; ret[32U] = 0U; ret[33U] = 0U; ret[34U] = 0U; ret[35U] = 0U; ret[36U] = 0U; ret[37U] = 0U; ret[38U] = 0U; ret[39U] = 0U; ret[40U] = 0U; ret[41U] = 0U; ret[42U] = 0U; ret[43U] = 0U; ret[44U] = 0U; ret[45U] = 0U; ret[46U] = 0U; ret[47U] = 0U; ret[48U] = 0U; ret[49U] = 0U; ret[50U] = 0U; ret[51U] = 0U; ret[52U] = 0U; ret[53U] = 0U; ret[54U] = 0U; ret[55U] = 0U; ret[56U] = 0U; ret[57U] = 0U; ret[58U] = 0U; ret[59U] = 0U; ret[60U] = 0U; ret[61U] = 0U; ret[62U] = 0U; ret[63U] = 0U; ret[64U] = 0U; ret[65U] = 0U; ret[66U] = 0U; ret[67U] = 0U; ret[68U] = 0U; ret[69U] = 0U; ret[70U] = 0U; ret[71U] = 0U; ret[72U] = 0U; ret[73U] = 0U; ret[74U] = 0U; ret[75U] = 0U; ret[76U] = 0U; ret[77U] = 0U; ret[78U] = 0U; ret[79U] = 0U; ret[80U] = 0U; ret[81U] = 0U; ret[82U] = 0U; ret[83U] = 0U; ret[84U] = 0U; ret[85U] = 0U; ret[86U] = 0U; ret[87U] = 0U; ret[88U] = 0U; ret[89U] = 0U; ret[90U] = 0U; ret[91U] = 0U; ret[92U] = 0U; ret[93U] = 0U; ret[94U] = 0U; ret[95U] = 0U; ret[96U] = 0U; ret[97U] = 0U; ret[98U] = 0U; ret[99U] = 0U; ret[100U] = 0U; ret[101U] = 0U; ret[102U] = 0U; ret[103U] = 0U; ret[104U] = 0U; ret[105U] = 0U; ret[106U] = 0U; ret[107U] = 0U; ret[108U] = 0U; ret[109U] = 0U; ret[110U] = 0U; ret[111U] = 0U; ret[112U] = 0U; ret[113U] = 0U; ret[114U] = 0U; ret[115U] = 0U; ret[116U] = 0U; ret[117U] = 0U; ret[118U] = 0U; ret[119U] = 0U; ret[120U] = 0U; ret[121U] = 0U; ret[122U] = 0U; ret[123U] = 0U; ret[124U] = 0U; ret[125U] = 0U; ret[126U] = 0U; ret[127U] = 0U; ret[128U] = 0U; ret[129U] = 0U; ret[130U] = 0U; ret[131U] = 0U; ret[132U] = 0U; ret[133U] = 0U; ret[134U] = 0U; ret[135U] = 0U; ret[136U] = 0U; ret[137U] = 0U; ret[138U] = 0U; ret[139U] = 0U; ret[140U] = 0U; ret[141U] = 0U; ret[142U] = 0U; ret[143U] = 0U; ret[144U] = 0U; ret[145U] = 0U; ret[146U] = 0U; ret[147U] = 0U; ret[148U] = 0U; ret[149U] = 0U; ret[150U] = 0U; ret[151U] = 0U; ret[152U] = 0U; ret[153U] = 0U; ret[154U] = 0U; ret[155U] = 0U; ret[156U] = 0U; ret[157U] = 0U; ret[158U] = 0U; ret[159U] = 0U; ret[160U] = 0U; ret[161U] = 0U; ret[162U] = 0U; ret[163U] = 0U; ret[164U] = 0U; ret[165U] = 0U; ret[166U] = 0U; ret[167U] = 0U; } /** Generate a new keccak xof state. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.new_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 168 */ static inline libcrux_sha3_generic_keccak_KeccakXofState_78 libcrux_sha3_generic_keccak_new_9d_7e0(void) { libcrux_sha3_generic_keccak_KeccakXofState_78 lit; lit.inner = libcrux_sha3_generic_keccak_new_1e_f4(); uint8_t ret[168U]; libcrux_sha3_generic_keccak_zero_block_9d_e60(ret); memcpy(lit.buf[0U], ret, (size_t)168U * sizeof(uint8_t)); lit.buf_len = (size_t)0U; lit.sponge = false; return lit; } /** This function found in impl {(libcrux_sha3::portable::incremental::XofAbsorb<168: usize> for libcrux_sha3::portable::incremental::Shake128Absorb)} */ static inline libcrux_sha3_generic_keccak_KeccakXofState_78 libcrux_sha3_portable_incremental_new_1c(void) { return libcrux_sha3_generic_keccak_new_9d_7e0(); } /** `out` has the exact size we want here. It must be less than or equal to `RATE`. */ /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_5a with const generics - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_5a_1c( uint64_t (*state)[5U], Eurydice_slice out[1U]) { size_t num_full_blocks = Eurydice_slice_len(out[0U], uint8_t) / (size_t)8U; size_t last_block_len = Eurydice_slice_len(out[0U], uint8_t) % (size_t)8U; for (size_t i = (size_t)0U; i < num_full_blocks; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out[0U], i0 * (size_t)8U, i0 * (size_t)8U + (size_t)8U, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes(state[i0 / (size_t)5U][i0 % (size_t)5U], ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); } if (last_block_len != (size_t)0U) { Eurydice_slice uu____1 = Eurydice_slice_subslice2( out[0U], num_full_blocks * (size_t)8U, num_full_blocks * (size_t)8U + last_block_len, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes( state[num_full_blocks / (size_t)5U][num_full_blocks % (size_t)5U], ret); Eurydice_slice_copy( uu____1, Eurydice_array_to_subslice2(ret, (size_t)0U, last_block_len, uint8_t), uint8_t); } } /** Squeeze `N` x `LEN` bytes. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 136 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_9d_96( libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice out[1U]) { if (self->sponge) { libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); } size_t out_len = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = out_len / (size_t)136U; size_t last = out_len - out_len % (size_t)136U; size_t mid; if ((size_t)136U >= out_len) { mid = out_len; } else { mid = (size_t)136U; } Eurydice_slice_uint8_t_1size_t__x2 uu____0 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, mid); Eurydice_slice out00[1U]; memcpy(out00, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice out_rest[1U]; memcpy(out_rest, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_store_5a_1c(self->inner.st, out00); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____1 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out_rest, (size_t)136U); Eurydice_slice out0[1U]; memcpy(out0, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice tmp[1U]; memcpy(tmp, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); libcrux_sha3_portable_keccak_store_5a_1c(self->inner.st, out0); memcpy(out_rest, tmp, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < out_len) { libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); libcrux_sha3_portable_keccak_store_5a_1c(self->inner.st, out_rest); } self->sponge = true; } /** Shake256 squeeze */ /** This function found in impl {(libcrux_sha3::portable::incremental::XofSqueeze<136: usize> for libcrux_sha3::portable::incremental::Shake256Squeeze)#3} */ static inline void libcrux_sha3_portable_incremental_squeeze_8a( libcrux_sha3_generic_keccak_KeccakXofState_4f *self, Eurydice_slice out) { Eurydice_slice buf[1U] = {out}; libcrux_sha3_generic_keccak_squeeze_9d_96(self, buf); } /** `out` has the exact size we want here. It must be less than or equal to `RATE`. */ /** This function found in impl {(libcrux_sha3::traits::internal::KeccakItem<1: usize> for u64)} */ /** A monomorphic instance of libcrux_sha3.portable_keccak.store_5a with const generics - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_portable_keccak_store_5a_1c0( uint64_t (*state)[5U], Eurydice_slice out[1U]) { size_t num_full_blocks = Eurydice_slice_len(out[0U], uint8_t) / (size_t)8U; size_t last_block_len = Eurydice_slice_len(out[0U], uint8_t) % (size_t)8U; for (size_t i = (size_t)0U; i < num_full_blocks; i++) { size_t i0 = i; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out[0U], i0 * (size_t)8U, i0 * (size_t)8U + (size_t)8U, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes(state[i0 / (size_t)5U][i0 % (size_t)5U], ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)8U, ret, uint8_t), uint8_t); } if (last_block_len != (size_t)0U) { Eurydice_slice uu____1 = Eurydice_slice_subslice2( out[0U], num_full_blocks * (size_t)8U, num_full_blocks * (size_t)8U + last_block_len, uint8_t); uint8_t ret[8U]; core_num__u64_9__to_le_bytes( state[num_full_blocks / (size_t)5U][num_full_blocks % (size_t)5U], ret); Eurydice_slice_copy( uu____1, Eurydice_array_to_subslice2(ret, (size_t)0U, last_block_len, uint8_t), uint8_t); } } /** Squeeze `N` x `LEN` bytes. */ /** This function found in impl {libcrux_sha3::generic_keccak::KeccakXofState[TraitClause@0]#2} */ /** A monomorphic instance of libcrux_sha3.generic_keccak.squeeze_9d with types uint64_t with const generics - PARALLEL_LANES= 1 - RATE= 168 */ static KRML_MUSTINLINE void libcrux_sha3_generic_keccak_squeeze_9d_960( libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice out[1U]) { if (self->sponge) { libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); } size_t out_len = Eurydice_slice_len(out[0U], uint8_t); size_t blocks = out_len / (size_t)168U; size_t last = out_len - out_len % (size_t)168U; size_t mid; if ((size_t)168U >= out_len) { mid = out_len; } else { mid = (size_t)168U; } Eurydice_slice_uint8_t_1size_t__x2 uu____0 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out, mid); Eurydice_slice out00[1U]; memcpy(out00, uu____0.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice out_rest[1U]; memcpy(out_rest, uu____0.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_portable_keccak_store_5a_1c0(self->inner.st, out00); core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){.start = (size_t)1U, .end = blocks}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { if (core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3) .tag == None) { break; } else { Eurydice_slice_uint8_t_1size_t__x2 uu____1 = libcrux_sha3_portable_keccak_split_at_mut_n_5a(out_rest, (size_t)168U); Eurydice_slice out0[1U]; memcpy(out0, uu____1.fst, (size_t)1U * sizeof(Eurydice_slice)); Eurydice_slice tmp[1U]; memcpy(tmp, uu____1.snd, (size_t)1U * sizeof(Eurydice_slice)); libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); libcrux_sha3_portable_keccak_store_5a_1c0(self->inner.st, out0); memcpy(out_rest, tmp, (size_t)1U * sizeof(Eurydice_slice)); } } if (last < out_len) { libcrux_sha3_generic_keccak_keccakf1600_21(&self->inner); libcrux_sha3_portable_keccak_store_5a_1c0(self->inner.st, out_rest); } self->sponge = true; } /** Shake128 squeeze */ /** This function found in impl {(libcrux_sha3::portable::incremental::XofSqueeze<168: usize> for libcrux_sha3::portable::incremental::Shake128Squeeze)#1} */ static inline void libcrux_sha3_portable_incremental_squeeze_10( libcrux_sha3_generic_keccak_KeccakXofState_78 *self, Eurydice_slice out) { Eurydice_slice buf[1U] = {out}; libcrux_sha3_generic_keccak_squeeze_9d_960(self, buf); } /** This function found in impl {(core::clone::Clone for libcrux_sha3::portable::KeccakState)} */ static inline libcrux_sha3_generic_keccak_KeccakState_48 libcrux_sha3_portable_clone_3d( libcrux_sha3_generic_keccak_KeccakState_48 *self) { return self[0U]; } /** This function found in impl {(core::convert::From for u32)#1} */ static inline uint32_t libcrux_sha3_from_eb(libcrux_sha3_Algorithm v) { uint32_t uu____0; switch (v) { case libcrux_sha3_Sha224: { uu____0 = 1U; break; } case libcrux_sha3_Sha256: { uu____0 = 2U; break; } case libcrux_sha3_Sha384: { uu____0 = 3U; break; } case libcrux_sha3_Sha512: { uu____0 = 4U; break; } default: { KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__); KRML_HOST_EXIT(253U); } } return uu____0; } /** This function found in impl {(core::convert::From for libcrux_sha3::Algorithm)} */ static inline libcrux_sha3_Algorithm libcrux_sha3_from_2d(uint32_t v) { libcrux_sha3_Algorithm uu____0; switch (v) { case 1U: { uu____0 = libcrux_sha3_Sha224; break; } case 2U: { uu____0 = libcrux_sha3_Sha256; break; } case 3U: { uu____0 = libcrux_sha3_Sha384; break; } case 4U: { uu____0 = libcrux_sha3_Sha512; break; } default: { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } } return uu____0; } typedef uint8_t libcrux_sha3_Sha3_512Digest[64U]; typedef uint8_t libcrux_sha3_Sha3_384Digest[48U]; typedef uint8_t libcrux_sha3_Sha3_256Digest[32U]; typedef uint8_t libcrux_sha3_Sha3_224Digest[28U]; #if defined(__cplusplus) } #endif #define __libcrux_sha3_portable_H_DEFINED #endif /* from libcrux/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h */ /* * SPDX-FileCopyrightText: 2024 Cryspen Sarl * * SPDX-License-Identifier: MIT or Apache-2.0 * * This code was generated with the following revisions: * Charon: 6b5e110342a771a3e1c739b10294b1778e4be8b4 * Eurydice: 31be7d65ca5d6acdacfb33652e478d24dd85c1cb * Karamel: 3205d3365ea2790b02368f79fcee38e38d0b5908 * F*: a32b316e521fa4f239b610ec8f1d15e78d62cbe8-dirty * Libcrux: 4ad532b206174114dd4140b718e7794a28fc59ee */ #ifndef __libcrux_mlkem768_portable_H #define __libcrux_mlkem768_portable_H #if defined(__cplusplus) extern "C" { #endif #define LIBCRUX_ML_KEM_HASH_FUNCTIONS_BLOCK_SIZE ((size_t)168U) #define LIBCRUX_ML_KEM_HASH_FUNCTIONS_THREE_BLOCKS \ (LIBCRUX_ML_KEM_HASH_FUNCTIONS_BLOCK_SIZE * (size_t)3U) static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_G( Eurydice_slice input, uint8_t ret[64U]) { uint8_t digest[64U] = {0U}; libcrux_sha3_portable_sha512( Eurydice_array_to_slice((size_t)64U, digest, uint8_t), input); memcpy(ret, digest, (size_t)64U * sizeof(uint8_t)); } static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_H( Eurydice_slice input, uint8_t ret[32U]) { uint8_t digest[32U] = {0U}; libcrux_sha3_portable_sha256( Eurydice_array_to_slice((size_t)32U, digest, uint8_t), input); memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); } #define LIBCRUX_ML_KEM_IND_CCA_ENCAPS_SEED_SIZE \ (LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE) #define LIBCRUX_ML_KEM_IND_CCA_KEY_GENERATION_SEED_SIZE \ (LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE + \ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE) typedef uint8_t libcrux_ml_kem_ind_cca_MlKemSharedSecret[32U]; static const int16_t libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[128U] = {(int16_t)-1044, (int16_t)-758, (int16_t)-359, (int16_t)-1517, (int16_t)1493, (int16_t)1422, (int16_t)287, (int16_t)202, (int16_t)-171, (int16_t)622, (int16_t)1577, (int16_t)182, (int16_t)962, (int16_t)-1202, (int16_t)-1474, (int16_t)1468, (int16_t)573, (int16_t)-1325, (int16_t)264, (int16_t)383, (int16_t)-829, (int16_t)1458, (int16_t)-1602, (int16_t)-130, (int16_t)-681, (int16_t)1017, (int16_t)732, (int16_t)608, (int16_t)-1542, (int16_t)411, (int16_t)-205, (int16_t)-1571, (int16_t)1223, (int16_t)652, (int16_t)-552, (int16_t)1015, (int16_t)-1293, (int16_t)1491, (int16_t)-282, (int16_t)-1544, (int16_t)516, (int16_t)-8, (int16_t)-320, (int16_t)-666, (int16_t)-1618, (int16_t)-1162, (int16_t)126, (int16_t)1469, (int16_t)-853, (int16_t)-90, (int16_t)-271, (int16_t)830, (int16_t)107, (int16_t)-1421, (int16_t)-247, (int16_t)-951, (int16_t)-398, (int16_t)961, (int16_t)-1508, (int16_t)-725, (int16_t)448, (int16_t)-1065, (int16_t)677, (int16_t)-1275, (int16_t)-1103, (int16_t)430, (int16_t)555, (int16_t)843, (int16_t)-1251, (int16_t)871, (int16_t)1550, (int16_t)105, (int16_t)422, (int16_t)587, (int16_t)177, (int16_t)-235, (int16_t)-291, (int16_t)-460, (int16_t)1574, (int16_t)1653, (int16_t)-246, (int16_t)778, (int16_t)1159, (int16_t)-147, (int16_t)-777, (int16_t)1483, (int16_t)-602, (int16_t)1119, (int16_t)-1590, (int16_t)644, (int16_t)-872, (int16_t)349, (int16_t)418, (int16_t)329, (int16_t)-156, (int16_t)-75, (int16_t)817, (int16_t)1097, (int16_t)603, (int16_t)610, (int16_t)1322, (int16_t)-1285, (int16_t)-1465, (int16_t)384, (int16_t)-1215, (int16_t)-136, (int16_t)1218, (int16_t)-1335, (int16_t)-874, (int16_t)220, (int16_t)-1187, (int16_t)-1659, (int16_t)-1185, (int16_t)-1530, (int16_t)-1278, (int16_t)794, (int16_t)-1510, (int16_t)-854, (int16_t)-870, (int16_t)478, (int16_t)-108, (int16_t)-308, (int16_t)996, (int16_t)991, (int16_t)958, (int16_t)-1460, (int16_t)1522, (int16_t)1628}; #define LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR ((size_t)16U) #define LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT \ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / \ LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR) #define LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS ((int16_t)3329) #define LIBCRUX_ML_KEM_VECTOR_TRAITS_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS \ ((int16_t)1353) #define LIBCRUX_ML_KEM_VECTOR_TRAITS_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R \ (62209U) typedef struct libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { int16_t elements[16U]; } libcrux_ml_kem_vector_portable_vector_type_PortableVector; static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_vector_type_from_i16_array( Eurydice_slice array) { libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; int16_t ret[16U]; Result_c0 dst; Eurydice_slice_to_array2( &dst, Eurydice_slice_subslice2(array, (size_t)0U, (size_t)16U, int16_t), Eurydice_slice, int16_t[16U]); unwrap_41_f9(dst, ret); memcpy(lit.elements, ret, (size_t)16U * sizeof(int16_t)); return lit; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_from_i16_array_0d(Eurydice_slice array) { return libcrux_ml_kem_vector_portable_vector_type_from_i16_array(array); } typedef struct uint8_t_x11_s { uint8_t fst; uint8_t snd; uint8_t thd; uint8_t f3; uint8_t f4; uint8_t f5; uint8_t f6; uint8_t f7; uint8_t f8; uint8_t f9; uint8_t f10; } uint8_t_x11; static KRML_MUSTINLINE uint8_t_x11 libcrux_ml_kem_vector_portable_serialize_serialize_11_int(Eurydice_slice v) { uint8_t r0 = (uint8_t)Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *); uint8_t r1 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) & (int16_t)31) << 3U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) >> 8U); uint8_t r2 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) & (int16_t)3) << 6U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) >> 5U); uint8_t r3 = (uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) >> 2U & (int16_t)255); uint8_t r4 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) & (int16_t)127) << 1U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) >> 10U); uint8_t r5 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)4U, int16_t, int16_t *) & (int16_t)15) << 4U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) >> 7U); uint8_t r6 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) & (int16_t)1) << 7U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)4U, int16_t, int16_t *) >> 4U); uint8_t r7 = (uint8_t)(Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) >> 1U & (int16_t)255); uint8_t r8 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)6U, int16_t, int16_t *) & (int16_t)63) << 2U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) >> 9U); uint8_t r9 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)7U, int16_t, int16_t *) & (int16_t)7) << 5U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)6U, int16_t, int16_t *) >> 6U); uint8_t r10 = (uint8_t)(Eurydice_slice_index(v, (size_t)7U, int16_t, int16_t *) >> 3U); return (CLITERAL(uint8_t_x11){.fst = r0, .snd = r1, .thd = r2, .f3 = r3, .f4 = r4, .f5 = r5, .f6 = r6, .f7 = r7, .f8 = r8, .f9 = r9, .f10 = r10}); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_serialize_serialize_11( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, uint8_t ret[22U]) { uint8_t_x11 r0_10 = libcrux_ml_kem_vector_portable_serialize_serialize_11_int( Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)8U, int16_t)); uint8_t_x11 r11_21 = libcrux_ml_kem_vector_portable_serialize_serialize_11_int( Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)16U, int16_t)); uint8_t result[22U] = {0U}; result[0U] = r0_10.fst; result[1U] = r0_10.snd; result[2U] = r0_10.thd; result[3U] = r0_10.f3; result[4U] = r0_10.f4; result[5U] = r0_10.f5; result[6U] = r0_10.f6; result[7U] = r0_10.f7; result[8U] = r0_10.f8; result[9U] = r0_10.f9; result[10U] = r0_10.f10; result[11U] = r11_21.fst; result[12U] = r11_21.snd; result[13U] = r11_21.thd; result[14U] = r11_21.f3; result[15U] = r11_21.f4; result[16U] = r11_21.f5; result[17U] = r11_21.f6; result[18U] = r11_21.f7; result[19U] = r11_21.f8; result[20U] = r11_21.f9; result[21U] = r11_21.f10; memcpy(ret, result, (size_t)22U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline void libcrux_ml_kem_vector_portable_serialize_11_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, uint8_t ret[22U]) { libcrux_ml_kem_vector_portable_serialize_serialize_11(a, ret); } typedef struct int16_t_x8_s { int16_t fst; int16_t snd; int16_t thd; int16_t f3; int16_t f4; int16_t f5; int16_t f6; int16_t f7; } int16_t_x8; static KRML_MUSTINLINE int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_11_int( Eurydice_slice bytes) { int16_t r0 = ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) & (int16_t)7) << 8U | (int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *); int16_t r1 = ((int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) & (int16_t)63) << 5U | (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) >> 3U; int16_t r2 = (((int16_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) & (int16_t)1) << 10U | (int16_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) << 2U) | (int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) >> 6U; int16_t r3 = ((int16_t)Eurydice_slice_index(bytes, (size_t)5U, uint8_t, uint8_t *) & (int16_t)15) << 7U | (int16_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) >> 1U; int16_t r4 = ((int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) & (int16_t)127) << 4U | (int16_t)Eurydice_slice_index(bytes, (size_t)5U, uint8_t, uint8_t *) >> 4U; int16_t r5 = (((int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) & (int16_t)3) << 9U | (int16_t)Eurydice_slice_index(bytes, (size_t)7U, uint8_t, uint8_t *) << 1U) | (int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) >> 7U; int16_t r6 = ((int16_t)Eurydice_slice_index(bytes, (size_t)9U, uint8_t, uint8_t *) & (int16_t)31) << 6U | (int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) >> 2U; int16_t r7 = (int16_t)Eurydice_slice_index(bytes, (size_t)10U, uint8_t, uint8_t *) << 3U | (int16_t)Eurydice_slice_index(bytes, (size_t)9U, uint8_t, uint8_t *) >> 5U; return (CLITERAL(int16_t_x8){.fst = r0, .snd = r1, .thd = r2, .f3 = r3, .f4 = r4, .f5 = r5, .f6 = r6, .f7 = r7}); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_vector_type_zero(void) { libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; lit.elements[0U] = (int16_t)0; lit.elements[1U] = (int16_t)0; lit.elements[2U] = (int16_t)0; lit.elements[3U] = (int16_t)0; lit.elements[4U] = (int16_t)0; lit.elements[5U] = (int16_t)0; lit.elements[6U] = (int16_t)0; lit.elements[7U] = (int16_t)0; lit.elements[8U] = (int16_t)0; lit.elements[9U] = (int16_t)0; lit.elements[10U] = (int16_t)0; lit.elements[11U] = (int16_t)0; lit.elements[12U] = (int16_t)0; lit.elements[13U] = (int16_t)0; lit.elements[14U] = (int16_t)0; lit.elements[15U] = (int16_t)0; return lit; } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_serialize_deserialize_11(Eurydice_slice bytes) { int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_11_int( Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)11U, uint8_t)); int16_t_x8 v8_15 = libcrux_ml_kem_vector_portable_serialize_deserialize_11_int( Eurydice_slice_subslice2(bytes, (size_t)11U, (size_t)22U, uint8_t)); libcrux_ml_kem_vector_portable_vector_type_PortableVector v = libcrux_ml_kem_vector_portable_vector_type_zero(); v.elements[0U] = v0_7.fst; v.elements[1U] = v0_7.snd; v.elements[2U] = v0_7.thd; v.elements[3U] = v0_7.f3; v.elements[4U] = v0_7.f4; v.elements[5U] = v0_7.f5; v.elements[6U] = v0_7.f6; v.elements[7U] = v0_7.f7; v.elements[8U] = v8_15.fst; v.elements[9U] = v8_15.snd; v.elements[10U] = v8_15.thd; v.elements[11U] = v8_15.f3; v.elements[12U] = v8_15.f4; v.elements[13U] = v8_15.f5; v.elements[14U] = v8_15.f6; v.elements[15U] = v8_15.f7; return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_deserialize_11_0d(Eurydice_slice a) { return libcrux_ml_kem_vector_portable_serialize_deserialize_11(a); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_vector_type_to_i16_array( libcrux_ml_kem_vector_portable_vector_type_PortableVector x, int16_t ret[16U]) { memcpy(ret, x.elements, (size_t)16U * sizeof(int16_t)); } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline void libcrux_ml_kem_vector_portable_to_i16_array_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector x, int16_t ret[16U]) { libcrux_ml_kem_vector_portable_vector_type_to_i16_array(x, ret); } static const uint8_t libcrux_ml_kem_vector_rej_sample_table_REJECTION_SAMPLE_SHUFFLE_TABLE [256U][16U] = {{255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 255U, 255U, 255U, 255U, 255U, 255U}, {10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U}, {8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 255U, 255U, 255U, 255U}, {12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 255U, 255U, 255U, 255U}, {10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U}, {8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U}, {6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 255U, 255U}, {14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 14U, 15U, 255U, 255U, 255U, 255U}, {10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U}, {8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U}, {6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 14U, 15U, 255U, 255U}, {12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 12U, 13U, 14U, 15U, 255U, 255U}, {10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U}, {8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U}, {6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U, 255U, 255U}, {0U, 1U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {0U, 1U, 2U, 3U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U}, {4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U, 255U, 255U}, {0U, 1U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U}, {2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 255U, 255U}, {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U}}; /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ZERO_0d(void) { return libcrux_ml_kem_vector_portable_vector_type_zero(); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_add( libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; size_t uu____0 = i0; lhs.elements[uu____0] = lhs.elements[uu____0] + rhs->elements[i0]; } return lhs; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_add_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { return libcrux_ml_kem_vector_portable_arithmetic_add(lhs, rhs); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_sub( libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; size_t uu____0 = i0; lhs.elements[uu____0] = lhs.elements[uu____0] - rhs->elements[i0]; } return lhs; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_sub_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { return libcrux_ml_kem_vector_portable_arithmetic_sub(lhs, rhs); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; size_t uu____0 = i0; v.elements[uu____0] = v.elements[uu____0] * c; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_multiply_by_constant_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { return libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant(v, c); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; size_t uu____0 = i0; v.elements[uu____0] = v.elements[uu____0] & c; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_bitwise_and_with_constant_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { return libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant(v, c); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { core_ops_range_Range_b3 iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range_b3){ .start = (size_t)0U, .end = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR}), core_ops_range_Range_b3, core_ops_range_Range_b3); while (true) { Option_b3 uu____0 = core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next( &iter, size_t, Option_b3); if (!(uu____0.tag == None)) { size_t i = uu____0.f0; if (v.elements[i] >= (int16_t)3329) { size_t uu____1 = i; v.elements[uu____1] = v.elements[uu____1] - (int16_t)3329; } continue; } return v; } } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_cond_subtract_3329_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329(v); } #define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER \ ((int32_t)20159) #define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT ((int32_t)26) #define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R \ ((int32_t)1 << (uint32_t) \ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT) /** Signed Barrett Reduction Given an input `value`, `barrett_reduce` outputs a representative `result` such that: - result ≡ value (mod FIELD_MODULUS) - the absolute value of `result` is bound as follows: `|result| ≤ FIELD_MODULUS / 2 · (|value|/BARRETT_R + 1) In particular, if `|value| < BARRETT_R`, then `|result| < FIELD_MODULUS`. */ static inline int16_t libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( int16_t value) { int32_t t = (int32_t)value * LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER + (LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R >> 1U); int16_t quotient = (int16_t)(t >> (uint32_t) LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT); return value - quotient * LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; v.elements[i0] = libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( v.elements[i0]); } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_barrett_reduce_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce(v); } #define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT (16U) #define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_R \ ((int32_t)1 << (uint32_t) \ LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT) /** Signed Montgomery Reduction Given an input `value`, `montgomery_reduce` outputs a representative `o` such that: - o ≡ value · MONTGOMERY_R^(-1) (mod FIELD_MODULUS) - the absolute value of `o` is bound as follows: `|result| ≤ (|value| / MONTGOMERY_R) + (FIELD_MODULUS / 2) In particular, if `|value| ≤ FIELD_MODULUS * MONTGOMERY_R`, then `|o| < (3 · FIELD_MODULUS) / 2`. */ static inline int16_t libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( int32_t value) { int32_t k = (int32_t)(int16_t)value * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R; int32_t k_times_modulus = (int32_t)(int16_t)k * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; int16_t c = (int16_t)(k_times_modulus >> (uint32_t) LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); int16_t value_high = (int16_t)(value >> (uint32_t) LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); return value_high - c; } /** If `fe` is some field element 'x' of the Kyber field and `fer` is congruent to `y · MONTGOMERY_R`, this procedure outputs a value that is congruent to `x · y`, as follows: `fe · fer ≡ x · y · MONTGOMERY_R (mod FIELD_MODULUS)` `montgomery_reduce` takes the value `x · y · MONTGOMERY_R` and outputs a representative `x · y · MONTGOMERY_R * MONTGOMERY_R^{-1} ≡ x · y (mod FIELD_MODULUS)`. */ static KRML_MUSTINLINE int16_t libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( int16_t fe, int16_t fer) { return libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( (int32_t)fe * (int32_t)fer); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; v.elements[i0] = libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( v.elements[i0], c); } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t r) { return libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( v, r); } /** The `compress_*` functions implement the `Compress` function specified in the NIST FIPS 203 standard (Page 18, Expression 4.5), which is defined as: ```plaintext Compress_d: ℤq -> ℤ_{2ᵈ} Compress_d(x) = ⌈(2ᵈ/q)·x⌋ ``` Since `⌈x⌋ = ⌊x + 1/2⌋` we have: ```plaintext Compress_d(x) = ⌊(2ᵈ/q)·x + 1/2⌋ = ⌊(2^{d+1}·x + q) / 2q⌋ ``` For further information about the function implementations, consult the `implementation_notes.pdf` document in this directory. The NIST FIPS 203 standard can be found at . */ static inline uint8_t libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( uint16_t fe) { int16_t shifted = (int16_t)1664 - (int16_t)fe; int16_t mask = shifted >> 15U; int16_t shifted_to_positive = mask ^ shifted; int16_t shifted_positive_in_range = shifted_to_positive - (int16_t)832; return (uint8_t)(shifted_positive_in_range >> 15U & (int16_t)1); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_compress_1( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; v.elements[i0] = (int16_t) libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( (uint16_t)v.elements[i0]); } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_1_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_compress_1(v); } static KRML_MUSTINLINE uint32_t libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( uint8_t n, uint32_t value) { return value & ((1U << (uint32_t)n) - 1U); } static inline int16_t libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( uint8_t coefficient_bits, uint16_t fe) { uint64_t compressed = (uint64_t)fe << (uint32_t)coefficient_bits; compressed = compressed + 1664ULL; compressed = compressed * 10321340ULL; compressed = compressed >> 35U; return (int16_t) libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( coefficient_bits, (uint32_t)compressed); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_ntt_ntt_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, int16_t zeta, size_t i, size_t j) { int16_t t = libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( v->elements[j], zeta); v->elements[j] = v->elements[i] - t; v->elements[i] = v->elements[i] + t; } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)0U, (size_t)2U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)1U, (size_t)3U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)4U, (size_t)6U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)5U, (size_t)7U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta2, (size_t)8U, (size_t)10U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta2, (size_t)9U, (size_t)11U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta3, (size_t)12U, (size_t)14U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta3, (size_t)13U, (size_t)15U); return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_layer_1_step_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { return libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step(a, zeta0, zeta1, zeta2, zeta3); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1) { libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)0U, (size_t)4U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)1U, (size_t)5U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)2U, (size_t)6U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta0, (size_t)3U, (size_t)7U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)8U, (size_t)12U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)9U, (size_t)13U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)10U, (size_t)14U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta1, (size_t)11U, (size_t)15U); return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_layer_2_step_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1) { return libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step(a, zeta0, zeta1); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) { libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)0U, (size_t)8U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)1U, (size_t)9U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)2U, (size_t)10U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)3U, (size_t)11U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)4U, (size_t)12U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)5U, (size_t)13U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)6U, (size_t)14U); libcrux_ml_kem_vector_portable_ntt_ntt_step(&v, zeta, (size_t)7U, (size_t)15U); return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_layer_3_step_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) { return libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step(a, zeta); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_ntt_inv_ntt_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, int16_t zeta, size_t i, size_t j) { int16_t a_minus_b = v->elements[j] - v->elements[i]; v->elements[i] = libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( v->elements[i] + v->elements[j]); v->elements[j] = libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( a_minus_b, zeta); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)0U, (size_t)2U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)1U, (size_t)3U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)4U, (size_t)6U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)5U, (size_t)7U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta2, (size_t)8U, (size_t)10U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta2, (size_t)9U, (size_t)11U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta3, (size_t)12U, (size_t)14U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta3, (size_t)13U, (size_t)15U); return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_inv_ntt_layer_1_step_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( a, zeta0, zeta1, zeta2, zeta3); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1) { libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)0U, (size_t)4U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)1U, (size_t)5U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)2U, (size_t)6U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta0, (size_t)3U, (size_t)7U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)8U, (size_t)12U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)9U, (size_t)13U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)10U, (size_t)14U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta1, (size_t)11U, (size_t)15U); return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_inv_ntt_layer_2_step_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1) { return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step(a, zeta0, zeta1); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) { libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)0U, (size_t)8U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)1U, (size_t)9U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)2U, (size_t)10U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)3U, (size_t)11U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)4U, (size_t)12U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)5U, (size_t)13U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)6U, (size_t)14U); libcrux_ml_kem_vector_portable_ntt_inv_ntt_step(&v, zeta, (size_t)7U, (size_t)15U); return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_inv_ntt_layer_3_step_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) { return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step(a, zeta); } /** Compute the product of two Kyber binomials with respect to the modulus `X² - zeta`. This function almost implements Algorithm 11 of the NIST FIPS 203 standard, which is reproduced below: ```plaintext Input: a₀, a₁, b₀, b₁ ∈ ℤq. Input: γ ∈ ℤq. Output: c₀, c₁ ∈ ℤq. c₀ ← a₀·b₀ + a₁·b₁·γ c₁ ← a₀·b₁ + a₁·b₀ return c₀, c₁ ``` We say "almost" because the coefficients output by this function are in the Montgomery domain (unlike in the specification). The NIST FIPS 203 standard can be found at . */ static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( libcrux_ml_kem_vector_portable_vector_type_PortableVector *a, libcrux_ml_kem_vector_portable_vector_type_PortableVector *b, int16_t zeta, size_t i, size_t j, libcrux_ml_kem_vector_portable_vector_type_PortableVector *out) { int16_t o0 = libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( (int32_t)a->elements[i] * (int32_t)b->elements[i] + (int32_t) libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( (int32_t)a->elements[j] * (int32_t)b->elements[j]) * (int32_t)zeta); int16_t o1 = libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( (int32_t)a->elements[i] * (int32_t)b->elements[j] + (int32_t)a->elements[j] * (int32_t)b->elements[i]); out->elements[i] = o0; out->elements[j] = o1; } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_ntt_multiply( libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { libcrux_ml_kem_vector_portable_vector_type_PortableVector out = libcrux_ml_kem_vector_portable_vector_type_zero(); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, zeta0, (size_t)0U, (size_t)1U, &out); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, -zeta0, (size_t)2U, (size_t)3U, &out); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, zeta1, (size_t)4U, (size_t)5U, &out); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, -zeta1, (size_t)6U, (size_t)7U, &out); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, zeta2, (size_t)8U, (size_t)9U, &out); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, -zeta2, (size_t)10U, (size_t)11U, &out); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, zeta3, (size_t)12U, (size_t)13U, &out); libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( lhs, rhs, -zeta3, (size_t)14U, (size_t)15U, &out); return out; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_ntt_multiply_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { return libcrux_ml_kem_vector_portable_ntt_ntt_multiply(lhs, rhs, zeta0, zeta1, zeta2, zeta3); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_serialize_serialize_1( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, uint8_t ret[2U]) { uint8_t result[2U] = {0U}; for (size_t i = (size_t)0U; i < (size_t)8U; i++) { size_t i0 = i; size_t uu____0 = (size_t)0U; result[uu____0] = (uint32_t)result[uu____0] | (uint32_t)(uint8_t)v.elements[i0] << (uint32_t)i0; } for (size_t i = (size_t)8U; i < (size_t)16U; i++) { size_t i0 = i; size_t uu____1 = (size_t)1U; result[uu____1] = (uint32_t)result[uu____1] | (uint32_t)(uint8_t)v.elements[i0] << (uint32_t)(i0 - (size_t)8U); } memcpy(ret, result, (size_t)2U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline void libcrux_ml_kem_vector_portable_serialize_1_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, uint8_t ret[2U]) { libcrux_ml_kem_vector_portable_serialize_serialize_1(a, ret); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_serialize_deserialize_1(Eurydice_slice v) { libcrux_ml_kem_vector_portable_vector_type_PortableVector result = libcrux_ml_kem_vector_portable_vector_type_zero(); for (size_t i = (size_t)0U; i < (size_t)8U; i++) { size_t i0 = i; result.elements[i0] = (int16_t)((uint32_t)Eurydice_slice_index( v, (size_t)0U, uint8_t, uint8_t *) >> (uint32_t)i0 & 1U); } for (size_t i = (size_t)8U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; result.elements[i0] = (int16_t)((uint32_t)Eurydice_slice_index( v, (size_t)1U, uint8_t, uint8_t *) >> (uint32_t)(i0 - (size_t)8U) & 1U); } return result; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_deserialize_1_0d(Eurydice_slice a) { return libcrux_ml_kem_vector_portable_serialize_deserialize_1(a); } typedef struct uint8_t_x4_s { uint8_t fst; uint8_t snd; uint8_t thd; uint8_t f3; } uint8_t_x4; static KRML_MUSTINLINE uint8_t_x4 libcrux_ml_kem_vector_portable_serialize_serialize_4_int(Eurydice_slice v) { uint8_t result0 = (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) << 4U | (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *); uint8_t result1 = (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) << 4U | (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *); uint8_t result2 = (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) << 4U | (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)4U, int16_t, int16_t *); uint8_t result3 = (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)7U, int16_t, int16_t *) << 4U | (uint32_t)(uint8_t)Eurydice_slice_index(v, (size_t)6U, int16_t, int16_t *); return (CLITERAL(uint8_t_x4){ .fst = result0, .snd = result1, .thd = result2, .f3 = result3}); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_serialize_serialize_4( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, uint8_t ret[8U]) { uint8_t_x4 result0_3 = libcrux_ml_kem_vector_portable_serialize_serialize_4_int( Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)8U, int16_t)); uint8_t_x4 result4_7 = libcrux_ml_kem_vector_portable_serialize_serialize_4_int( Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)16U, int16_t)); uint8_t result[8U] = {0U}; result[0U] = result0_3.fst; result[1U] = result0_3.snd; result[2U] = result0_3.thd; result[3U] = result0_3.f3; result[4U] = result4_7.fst; result[5U] = result4_7.snd; result[6U] = result4_7.thd; result[7U] = result4_7.f3; memcpy(ret, result, (size_t)8U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline void libcrux_ml_kem_vector_portable_serialize_4_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, uint8_t ret[8U]) { libcrux_ml_kem_vector_portable_serialize_serialize_4(a, ret); } static KRML_MUSTINLINE int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_4_int( Eurydice_slice bytes) { int16_t v0 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *) & 15U); int16_t v1 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *) >> 4U & 15U); int16_t v2 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) & 15U); int16_t v3 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) >> 4U & 15U); int16_t v4 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) & 15U); int16_t v5 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) >> 4U & 15U); int16_t v6 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) & 15U); int16_t v7 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) >> 4U & 15U); return (CLITERAL(int16_t_x8){.fst = v0, .snd = v1, .thd = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7}); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_serialize_deserialize_4(Eurydice_slice bytes) { int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_4_int( Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)4U, uint8_t)); int16_t_x8 v8_15 = libcrux_ml_kem_vector_portable_serialize_deserialize_4_int( Eurydice_slice_subslice2(bytes, (size_t)4U, (size_t)8U, uint8_t)); libcrux_ml_kem_vector_portable_vector_type_PortableVector v = libcrux_ml_kem_vector_portable_vector_type_zero(); v.elements[0U] = v0_7.fst; v.elements[1U] = v0_7.snd; v.elements[2U] = v0_7.thd; v.elements[3U] = v0_7.f3; v.elements[4U] = v0_7.f4; v.elements[5U] = v0_7.f5; v.elements[6U] = v0_7.f6; v.elements[7U] = v0_7.f7; v.elements[8U] = v8_15.fst; v.elements[9U] = v8_15.snd; v.elements[10U] = v8_15.thd; v.elements[11U] = v8_15.f3; v.elements[12U] = v8_15.f4; v.elements[13U] = v8_15.f5; v.elements[14U] = v8_15.f6; v.elements[15U] = v8_15.f7; return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_deserialize_4_0d(Eurydice_slice a) { return libcrux_ml_kem_vector_portable_serialize_deserialize_4(a); } typedef struct uint8_t_x5_s { uint8_t fst; uint8_t snd; uint8_t thd; uint8_t f3; uint8_t f4; } uint8_t_x5; static KRML_MUSTINLINE uint8_t_x5 libcrux_ml_kem_vector_portable_serialize_serialize_5_int(Eurydice_slice v) { uint8_t r0 = (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) | Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) << 5U); uint8_t r1 = (uint8_t)((Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) >> 3U | Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) << 2U) | Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) << 7U); uint8_t r2 = (uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) >> 1U | Eurydice_slice_index(v, (size_t)4U, int16_t, int16_t *) << 4U); uint8_t r3 = (uint8_t)((Eurydice_slice_index(v, (size_t)4U, int16_t, int16_t *) >> 4U | Eurydice_slice_index(v, (size_t)5U, int16_t, int16_t *) << 1U) | Eurydice_slice_index(v, (size_t)6U, int16_t, int16_t *) << 6U); uint8_t r4 = (uint8_t)(Eurydice_slice_index(v, (size_t)6U, int16_t, int16_t *) >> 2U | Eurydice_slice_index(v, (size_t)7U, int16_t, int16_t *) << 3U); return (CLITERAL(uint8_t_x5){ .fst = r0, .snd = r1, .thd = r2, .f3 = r3, .f4 = r4}); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_serialize_serialize_5( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, uint8_t ret[10U]) { uint8_t_x5 r0_4 = libcrux_ml_kem_vector_portable_serialize_serialize_5_int( Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)8U, int16_t)); uint8_t_x5 r5_9 = libcrux_ml_kem_vector_portable_serialize_serialize_5_int( Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)16U, int16_t)); uint8_t result[10U] = {0U}; result[0U] = r0_4.fst; result[1U] = r0_4.snd; result[2U] = r0_4.thd; result[3U] = r0_4.f3; result[4U] = r0_4.f4; result[5U] = r5_9.fst; result[6U] = r5_9.snd; result[7U] = r5_9.thd; result[8U] = r5_9.f3; result[9U] = r5_9.f4; memcpy(ret, result, (size_t)10U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline void libcrux_ml_kem_vector_portable_serialize_5_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, uint8_t ret[10U]) { libcrux_ml_kem_vector_portable_serialize_serialize_5(a, ret); } static KRML_MUSTINLINE int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_5_int( Eurydice_slice bytes) { int16_t v0 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *) & 31U); int16_t v1 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) & 3U) << 3U | (uint32_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *) >> 5U); int16_t v2 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) >> 2U & 31U); int16_t v3 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) & 15U) << 1U | (uint32_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) >> 7U); int16_t v4 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) & 1U) << 4U | (uint32_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) >> 4U); int16_t v5 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) >> 1U & 31U); int16_t v6 = (int16_t)(((uint32_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) & 7U) << 2U | (uint32_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) >> 6U); int16_t v7 = (int16_t)((uint32_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) >> 3U); return (CLITERAL(int16_t_x8){.fst = v0, .snd = v1, .thd = v2, .f3 = v3, .f4 = v4, .f5 = v5, .f6 = v6, .f7 = v7}); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_serialize_deserialize_5(Eurydice_slice bytes) { int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_5_int( Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)5U, uint8_t)); int16_t_x8 v8_15 = libcrux_ml_kem_vector_portable_serialize_deserialize_5_int( Eurydice_slice_subslice2(bytes, (size_t)5U, (size_t)10U, uint8_t)); libcrux_ml_kem_vector_portable_vector_type_PortableVector v = libcrux_ml_kem_vector_portable_vector_type_zero(); v.elements[0U] = v0_7.fst; v.elements[1U] = v0_7.snd; v.elements[2U] = v0_7.thd; v.elements[3U] = v0_7.f3; v.elements[4U] = v0_7.f4; v.elements[5U] = v0_7.f5; v.elements[6U] = v0_7.f6; v.elements[7U] = v0_7.f7; v.elements[8U] = v8_15.fst; v.elements[9U] = v8_15.snd; v.elements[10U] = v8_15.thd; v.elements[11U] = v8_15.f3; v.elements[12U] = v8_15.f4; v.elements[13U] = v8_15.f5; v.elements[14U] = v8_15.f6; v.elements[15U] = v8_15.f7; return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_deserialize_5_0d(Eurydice_slice a) { return libcrux_ml_kem_vector_portable_serialize_deserialize_5(a); } static KRML_MUSTINLINE uint8_t_x5 libcrux_ml_kem_vector_portable_serialize_serialize_10_int(Eurydice_slice v) { uint8_t r0 = (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) & (int16_t)255); uint8_t r1 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) & (int16_t)63) << 2U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) >> 8U & (int16_t)3); uint8_t r2 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) & (int16_t)15) << 4U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) >> 6U & (int16_t)15); uint8_t r3 = (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) & (int16_t)3) << 6U | (uint32_t)(uint8_t)(Eurydice_slice_index(v, (size_t)2U, int16_t, int16_t *) >> 4U & (int16_t)63); uint8_t r4 = (uint8_t)(Eurydice_slice_index(v, (size_t)3U, int16_t, int16_t *) >> 2U & (int16_t)255); return (CLITERAL(uint8_t_x5){ .fst = r0, .snd = r1, .thd = r2, .f3 = r3, .f4 = r4}); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_serialize_serialize_10( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, uint8_t ret[20U]) { uint8_t_x5 r0_4 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)4U, int16_t)); uint8_t_x5 r5_9 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( Eurydice_array_to_subslice2(v.elements, (size_t)4U, (size_t)8U, int16_t)); uint8_t_x5 r10_14 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)12U, int16_t)); uint8_t_x5 r15_19 = libcrux_ml_kem_vector_portable_serialize_serialize_10_int( Eurydice_array_to_subslice2(v.elements, (size_t)12U, (size_t)16U, int16_t)); uint8_t result[20U] = {0U}; result[0U] = r0_4.fst; result[1U] = r0_4.snd; result[2U] = r0_4.thd; result[3U] = r0_4.f3; result[4U] = r0_4.f4; result[5U] = r5_9.fst; result[6U] = r5_9.snd; result[7U] = r5_9.thd; result[8U] = r5_9.f3; result[9U] = r5_9.f4; result[10U] = r10_14.fst; result[11U] = r10_14.snd; result[12U] = r10_14.thd; result[13U] = r10_14.f3; result[14U] = r10_14.f4; result[15U] = r15_19.fst; result[16U] = r15_19.snd; result[17U] = r15_19.thd; result[18U] = r15_19.f3; result[19U] = r15_19.f4; memcpy(ret, result, (size_t)20U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline void libcrux_ml_kem_vector_portable_serialize_10_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, uint8_t ret[20U]) { libcrux_ml_kem_vector_portable_serialize_serialize_10(a, ret); } static KRML_MUSTINLINE int16_t_x8 libcrux_ml_kem_vector_portable_serialize_deserialize_10_int( Eurydice_slice bytes) { int16_t r0 = ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) & (int16_t)3) << 8U | ((int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *) & (int16_t)255); int16_t r1 = ((int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) & (int16_t)15) << 6U | (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *) >> 2U; int16_t r2 = ((int16_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) & (int16_t)63) << 4U | (int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *) >> 4U; int16_t r3 = (int16_t)Eurydice_slice_index(bytes, (size_t)4U, uint8_t, uint8_t *) << 2U | (int16_t)Eurydice_slice_index(bytes, (size_t)3U, uint8_t, uint8_t *) >> 6U; int16_t r4 = ((int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) & (int16_t)3) << 8U | ((int16_t)Eurydice_slice_index(bytes, (size_t)5U, uint8_t, uint8_t *) & (int16_t)255); int16_t r5 = ((int16_t)Eurydice_slice_index(bytes, (size_t)7U, uint8_t, uint8_t *) & (int16_t)15) << 6U | (int16_t)Eurydice_slice_index(bytes, (size_t)6U, uint8_t, uint8_t *) >> 2U; int16_t r6 = ((int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) & (int16_t)63) << 4U | (int16_t)Eurydice_slice_index(bytes, (size_t)7U, uint8_t, uint8_t *) >> 4U; int16_t r7 = (int16_t)Eurydice_slice_index(bytes, (size_t)9U, uint8_t, uint8_t *) << 2U | (int16_t)Eurydice_slice_index(bytes, (size_t)8U, uint8_t, uint8_t *) >> 6U; return (CLITERAL(int16_t_x8){.fst = r0, .snd = r1, .thd = r2, .f3 = r3, .f4 = r4, .f5 = r5, .f6 = r6, .f7 = r7}); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_serialize_deserialize_10(Eurydice_slice bytes) { int16_t_x8 v0_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_10_int( Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)10U, uint8_t)); int16_t_x8 v8_15 = libcrux_ml_kem_vector_portable_serialize_deserialize_10_int( Eurydice_slice_subslice2(bytes, (size_t)10U, (size_t)20U, uint8_t)); libcrux_ml_kem_vector_portable_vector_type_PortableVector v = libcrux_ml_kem_vector_portable_vector_type_zero(); v.elements[0U] = v0_7.fst; v.elements[1U] = v0_7.snd; v.elements[2U] = v0_7.thd; v.elements[3U] = v0_7.f3; v.elements[4U] = v0_7.f4; v.elements[5U] = v0_7.f5; v.elements[6U] = v0_7.f6; v.elements[7U] = v0_7.f7; v.elements[8U] = v8_15.fst; v.elements[9U] = v8_15.snd; v.elements[10U] = v8_15.thd; v.elements[11U] = v8_15.f3; v.elements[12U] = v8_15.f4; v.elements[13U] = v8_15.f5; v.elements[14U] = v8_15.f6; v.elements[15U] = v8_15.f7; return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_deserialize_10_0d(Eurydice_slice a) { return libcrux_ml_kem_vector_portable_serialize_deserialize_10(a); } typedef struct uint8_t_x3_s { uint8_t fst; uint8_t snd; uint8_t thd; } uint8_t_x3; static KRML_MUSTINLINE uint8_t_x3 libcrux_ml_kem_vector_portable_serialize_serialize_12_int(Eurydice_slice v) { uint8_t r0 = (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) & (int16_t)255); uint8_t r1 = (uint8_t)(Eurydice_slice_index(v, (size_t)0U, int16_t, int16_t *) >> 8U | (Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) & (int16_t)15) << 4U); uint8_t r2 = (uint8_t)(Eurydice_slice_index(v, (size_t)1U, int16_t, int16_t *) >> 4U & (int16_t)255); return (CLITERAL(uint8_t_x3){.fst = r0, .snd = r1, .thd = r2}); } static KRML_MUSTINLINE void libcrux_ml_kem_vector_portable_serialize_serialize_12( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, uint8_t ret[24U]) { uint8_t_x3 r0_2 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)0U, (size_t)2U, int16_t)); uint8_t_x3 r3_5 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)2U, (size_t)4U, int16_t)); uint8_t_x3 r6_8 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)4U, (size_t)6U, int16_t)); uint8_t_x3 r9_11 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)6U, (size_t)8U, int16_t)); uint8_t_x3 r12_14 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)8U, (size_t)10U, int16_t)); uint8_t_x3 r15_17 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)10U, (size_t)12U, int16_t)); uint8_t_x3 r18_20 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)12U, (size_t)14U, int16_t)); uint8_t_x3 r21_23 = libcrux_ml_kem_vector_portable_serialize_serialize_12_int( Eurydice_array_to_subslice2(v.elements, (size_t)14U, (size_t)16U, int16_t)); uint8_t result[24U] = {0U}; result[0U] = r0_2.fst; result[1U] = r0_2.snd; result[2U] = r0_2.thd; result[3U] = r3_5.fst; result[4U] = r3_5.snd; result[5U] = r3_5.thd; result[6U] = r6_8.fst; result[7U] = r6_8.snd; result[8U] = r6_8.thd; result[9U] = r9_11.fst; result[10U] = r9_11.snd; result[11U] = r9_11.thd; result[12U] = r12_14.fst; result[13U] = r12_14.snd; result[14U] = r12_14.thd; result[15U] = r15_17.fst; result[16U] = r15_17.snd; result[17U] = r15_17.thd; result[18U] = r18_20.fst; result[19U] = r18_20.snd; result[20U] = r18_20.thd; result[21U] = r21_23.fst; result[22U] = r21_23.snd; result[23U] = r21_23.thd; memcpy(ret, result, (size_t)24U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline void libcrux_ml_kem_vector_portable_serialize_12_0d( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, uint8_t ret[24U]) { libcrux_ml_kem_vector_portable_serialize_serialize_12(a, ret); } typedef struct int16_t_x2_s { int16_t fst; int16_t snd; } int16_t_x2; static KRML_MUSTINLINE int16_t_x2 libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice bytes) { int16_t byte0 = (int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *); int16_t byte1 = (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *); int16_t byte2 = (int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, uint8_t *); int16_t r0 = (byte1 & (int16_t)15) << 8U | (byte0 & (int16_t)255); int16_t r1 = byte2 << 4U | (byte1 >> 4U & (int16_t)15); return (CLITERAL(int16_t_x2){.fst = r0, .snd = r1}); } static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_serialize_deserialize_12(Eurydice_slice bytes) { int16_t_x2 v0_1 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)0U, (size_t)3U, uint8_t)); int16_t_x2 v2_3 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)3U, (size_t)6U, uint8_t)); int16_t_x2 v4_5 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)6U, (size_t)9U, uint8_t)); int16_t_x2 v6_7 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)9U, (size_t)12U, uint8_t)); int16_t_x2 v8_9 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)12U, (size_t)15U, uint8_t)); int16_t_x2 v10_11 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)15U, (size_t)18U, uint8_t)); int16_t_x2 v12_13 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)18U, (size_t)21U, uint8_t)); int16_t_x2 v14_15 = libcrux_ml_kem_vector_portable_serialize_deserialize_12_int( Eurydice_slice_subslice2(bytes, (size_t)21U, (size_t)24U, uint8_t)); libcrux_ml_kem_vector_portable_vector_type_PortableVector re = libcrux_ml_kem_vector_portable_vector_type_zero(); re.elements[0U] = v0_1.fst; re.elements[1U] = v0_1.snd; re.elements[2U] = v2_3.fst; re.elements[3U] = v2_3.snd; re.elements[4U] = v4_5.fst; re.elements[5U] = v4_5.snd; re.elements[6U] = v6_7.fst; re.elements[7U] = v6_7.snd; re.elements[8U] = v8_9.fst; re.elements[9U] = v8_9.snd; re.elements[10U] = v10_11.fst; re.elements[11U] = v10_11.snd; re.elements[12U] = v12_13.fst; re.elements[13U] = v12_13.snd; re.elements[14U] = v14_15.fst; re.elements[15U] = v14_15.snd; return re; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_deserialize_12_0d(Eurydice_slice a) { return libcrux_ml_kem_vector_portable_serialize_deserialize_12(a); } static KRML_MUSTINLINE size_t libcrux_ml_kem_vector_portable_sampling_rej_sample(Eurydice_slice a, Eurydice_slice result) { size_t sampled = (size_t)0U; for (size_t i = (size_t)0U; i < Eurydice_slice_len(a, uint8_t) / (size_t)3U; i++) { size_t i0 = i; int16_t b1 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)0U, uint8_t, uint8_t *); int16_t b2 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)1U, uint8_t, uint8_t *); int16_t b3 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)2U, uint8_t, uint8_t *); int16_t d1 = (b2 & (int16_t)15) << 8U | b1; int16_t d2 = b3 << 4U | b2 >> 4U; bool uu____0; int16_t uu____1; bool uu____2; size_t uu____3; int16_t uu____4; size_t uu____5; int16_t uu____6; if (d1 < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS) { if (sampled < (size_t)16U) { Eurydice_slice_index(result, sampled, int16_t, int16_t *) = d1; sampled++; uu____1 = d2; uu____6 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; uu____0 = uu____1 < uu____6; if (uu____0) { uu____3 = sampled; uu____2 = uu____3 < (size_t)16U; if (uu____2) { uu____4 = d2; uu____5 = sampled; Eurydice_slice_index(result, uu____5, int16_t, int16_t *) = uu____4; sampled++; continue; } } continue; } } uu____1 = d2; uu____6 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; uu____0 = uu____1 < uu____6; if (uu____0) { uu____3 = sampled; uu____2 = uu____3 < (size_t)16U; if (uu____2) { uu____4 = d2; uu____5 = sampled; Eurydice_slice_index(result, uu____5, int16_t, int16_t *) = uu____4; sampled++; continue; } } } return sampled; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline size_t libcrux_ml_kem_vector_portable_rej_sample_0d( Eurydice_slice a, Eurydice_slice out) { return libcrux_ml_kem_vector_portable_sampling_rej_sample(a, out); } #define LIBCRUX_ML_KEM_MLKEM768_VECTOR_U_COMPRESSION_FACTOR_768 ((size_t)10U) #define LIBCRUX_ML_KEM_MLKEM768_C1_BLOCK_SIZE_768 \ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ LIBCRUX_ML_KEM_MLKEM768_VECTOR_U_COMPRESSION_FACTOR_768 / (size_t)8U) #define LIBCRUX_ML_KEM_MLKEM768_RANK_768 ((size_t)3U) #define LIBCRUX_ML_KEM_MLKEM768_C1_SIZE_768 \ (LIBCRUX_ML_KEM_MLKEM768_C1_BLOCK_SIZE_768 * LIBCRUX_ML_KEM_MLKEM768_RANK_768) #define LIBCRUX_ML_KEM_MLKEM768_VECTOR_V_COMPRESSION_FACTOR_768 ((size_t)4U) #define LIBCRUX_ML_KEM_MLKEM768_C2_SIZE_768 \ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ LIBCRUX_ML_KEM_MLKEM768_VECTOR_V_COMPRESSION_FACTOR_768 / (size_t)8U) #define LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_CIPHERTEXT_SIZE_768 \ (LIBCRUX_ML_KEM_MLKEM768_C1_SIZE_768 + LIBCRUX_ML_KEM_MLKEM768_C2_SIZE_768) #define LIBCRUX_ML_KEM_MLKEM768_T_AS_NTT_ENCODED_SIZE_768 \ (LIBCRUX_ML_KEM_MLKEM768_RANK_768 * \ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT / (size_t)8U) #define LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_PUBLIC_KEY_SIZE_768 \ (LIBCRUX_ML_KEM_MLKEM768_T_AS_NTT_ENCODED_SIZE_768 + (size_t)32U) #define LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_SECRET_KEY_SIZE_768 \ (LIBCRUX_ML_KEM_MLKEM768_RANK_768 * \ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT / (size_t)8U) #define LIBCRUX_ML_KEM_MLKEM768_ETA1 ((size_t)2U) #define LIBCRUX_ML_KEM_MLKEM768_ETA1_RANDOMNESS_SIZE \ (LIBCRUX_ML_KEM_MLKEM768_ETA1 * (size_t)64U) #define LIBCRUX_ML_KEM_MLKEM768_ETA2 ((size_t)2U) #define LIBCRUX_ML_KEM_MLKEM768_ETA2_RANDOMNESS_SIZE \ (LIBCRUX_ML_KEM_MLKEM768_ETA2 * (size_t)64U) #define LIBCRUX_ML_KEM_MLKEM768_IMPLICIT_REJECTION_HASH_INPUT_SIZE \ (LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE + \ LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_CIPHERTEXT_SIZE_768) typedef libcrux_ml_kem_types_MlKemPrivateKey_55 libcrux_ml_kem_mlkem768_MlKem768PrivateKey; typedef libcrux_ml_kem_types_MlKemPublicKey_15 libcrux_ml_kem_mlkem768_MlKem768PublicKey; #define LIBCRUX_ML_KEM_MLKEM768_RANKED_BYTES_PER_RING_ELEMENT_768 \ (LIBCRUX_ML_KEM_MLKEM768_RANK_768 * \ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_RING_ELEMENT / (size_t)8U) #define LIBCRUX_ML_KEM_MLKEM768_SECRET_KEY_SIZE_768 \ (LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_SECRET_KEY_SIZE_768 + \ LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_PUBLIC_KEY_SIZE_768 + \ LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE + \ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE) /** A monomorphic instance of libcrux_ml_kem.polynomial.PolynomialRingElement with types libcrux_ml_kem_vector_portable_vector_type_PortableVector */ typedef struct libcrux_ml_kem_polynomial_PolynomialRingElement_f0_s { libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients[16U]; } libcrux_ml_kem_polynomial_PolynomialRingElement_f0; /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.ZERO_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_polynomial_ZERO_89_ea(void) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 lit; lit.coefficients[0U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[1U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[2U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[3U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[4U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[5U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[6U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[7U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[8U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[9U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[10U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[11U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[12U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[13U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[14U] = libcrux_ml_kem_vector_portable_ZERO_0d(); lit.coefficients[15U] = libcrux_ml_kem_vector_portable_ZERO_0d(); return lit; } /** A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_secret_key.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_ind_cpa_deserialize_secret_key_closure_6b(size_t _) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_to_uncompressed_ring_element with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element_af( Eurydice_slice serialized) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(serialized, uint8_t) / (size_t)24U; i++) { size_t i0 = i; Eurydice_slice bytes = Eurydice_slice_subslice2( serialized, i0 * (size_t)24U, i0 * (size_t)24U + (size_t)24U, uint8_t); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_deserialize_12_0d(bytes); re.coefficients[i0] = uu____0; } return re; } /** Call [`deserialize_to_uncompressed_ring_element`] for each ring element. */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_secret_key with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_ind_cpa_deserialize_secret_key_24( Eurydice_slice secret_key, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { secret_as_ntt[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } for (size_t i = (size_t)0U; i < Eurydice_slice_len(secret_key, uint8_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; i++) { size_t i0 = i; Eurydice_slice secret_bytes = Eurydice_slice_subslice2( secret_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, uint8_t); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element_af( secret_bytes); secret_as_ntt[i0] = uu____0; } memcpy( ret, secret_as_ntt, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); } /** A monomorphic instance of libcrux_ml_kem.ind_cpa.unpacked.IndCpaPrivateKeyUnpacked with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - $3size_t */ typedef struct libcrux_ml_kem_ind_cpa_unpacked_IndCpaPrivateKeyUnpacked_f8_s { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; } libcrux_ml_kem_ind_cpa_unpacked_IndCpaPrivateKeyUnpacked_f8; /** A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_then_decompress_u.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - U_COMPRESSION_FACTOR= 10 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u_closure_7c(size_t _) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with const generics - COEFFICIENT_BITS= 10 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int32_t decompressed = (int32_t)v.elements[i0] * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)10); decompressed = decompressed >> (uint32_t)((int32_t)10 + (int32_t)1); v.elements[i0] = (int16_t)decompressed; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const generics - COEFFICIENT_BITS= 10 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b( v); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_10 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_then_decompress_10_2c( Eurydice_slice serialized) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(serialized, uint8_t) / (size_t)20U; i++) { size_t i0 = i; Eurydice_slice bytes = Eurydice_slice_subslice2( serialized, i0 * (size_t)20U, i0 * (size_t)20U + (size_t)20U, uint8_t); libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_portable_deserialize_10_0d(bytes); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a( coefficient); re.coefficients[i0] = uu____0; } return re; } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with const generics - COEFFICIENT_BITS= 11 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b0( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int32_t decompressed = (int32_t)v.elements[i0] * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)11); decompressed = decompressed >> (uint32_t)((int32_t)11 + (int32_t)1); v.elements[i0] = (int16_t)decompressed; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const generics - COEFFICIENT_BITS= 11 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a0( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b0( v); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_11 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_then_decompress_11_8d( Eurydice_slice serialized) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(serialized, uint8_t) / (size_t)22U; i++) { size_t i0 = i; Eurydice_slice bytes = Eurydice_slice_subslice2( serialized, i0 * (size_t)22U, i0 * (size_t)22U + (size_t)22U, uint8_t); libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_portable_deserialize_11_0d(bytes); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a0( coefficient); re.coefficients[i0] = uu____0; } return re; } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_ring_element_u with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - COMPRESSION_FACTOR= 10 */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_u_34( Eurydice_slice serialized) { return libcrux_ml_kem_serialize_deserialize_then_decompress_10_2c(serialized); } typedef struct libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2_s { libcrux_ml_kem_vector_portable_vector_type_PortableVector fst; libcrux_ml_kem_vector_portable_vector_type_PortableVector snd; } libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2; /** A monomorphic instance of libcrux_ml_kem.vector.traits.montgomery_multiply_fe with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_traits_montgomery_multiply_fe_67( libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t fer) { return libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d(v, fer); } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_layer_int_vec_step with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 libcrux_ml_kem_ntt_ntt_layer_int_vec_step_0c( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, libcrux_ml_kem_vector_portable_vector_type_PortableVector b, int16_t zeta_r) { libcrux_ml_kem_vector_portable_vector_type_PortableVector t = libcrux_ml_kem_vector_traits_montgomery_multiply_fe_67(b, zeta_r); b = libcrux_ml_kem_vector_portable_sub_0d(a, &t); a = libcrux_ml_kem_vector_portable_add_0d(a, &t); return ( CLITERAL(libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2){ .fst = a, .snd = b}); } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_4_plus with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t layer, size_t _initial_coefficient_bound) { size_t step = (size_t)1U << (uint32_t)layer; for (size_t i0 = (size_t)0U; i0 < (size_t)128U >> (uint32_t)layer; i0++) { size_t round = i0; zeta_i[0U] = zeta_i[0U] + (size_t)1U; size_t offset = round * step * (size_t)2U; size_t offset_vec = offset / (size_t)16U; size_t step_vec = step / (size_t)16U; for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { size_t j = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 uu____0 = libcrux_ml_kem_ntt_ntt_layer_int_vec_step_0c( re->coefficients[j], re->coefficients[j + step_vec], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; re->coefficients[j] = x; re->coefficients[j + step_vec] = y; } } } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_3 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_ntt_ntt_at_layer_3_fd( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t _layer, size_t _initial_coefficient_bound) { for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t round = i; zeta_i[0U] = zeta_i[0U] + (size_t)1U; libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_ntt_layer_3_step_0d( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); re->coefficients[round] = uu____0; } } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_2 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_ntt_ntt_at_layer_2_ad( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t _layer, size_t _initial_coefficient_bound) { for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t round = i; zeta_i[0U] = zeta_i[0U] + (size_t)1U; re->coefficients[round] = libcrux_ml_kem_vector_portable_ntt_layer_2_step_0d( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + (size_t)1U]); zeta_i[0U] = zeta_i[0U] + (size_t)1U; } } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_1 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_ntt_ntt_at_layer_1_a2( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t _layer, size_t _initial_coefficient_bound) { for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t round = i; zeta_i[0U] = zeta_i[0U] + (size_t)1U; re->coefficients[round] = libcrux_ml_kem_vector_portable_ntt_layer_1_step_0d( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + (size_t)1U], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + (size_t)2U], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + (size_t)3U]); zeta_i[0U] = zeta_i[0U] + (size_t)3U; } } /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.poly_barrett_reduce_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_polynomial_poly_barrett_reduce_89_8b( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_barrett_reduce_0d( self->coefficients[i0]); self->coefficients[i0] = uu____0; } } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_vector_u with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - VECTOR_U_COMPRESSION_FACTOR= 10 */ static KRML_MUSTINLINE void libcrux_ml_kem_ntt_ntt_vector_u_9f( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) { size_t zeta_i = (size_t)0U; libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51(&zeta_i, re, (size_t)7U, (size_t)3328U); libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51(&zeta_i, re, (size_t)6U, (size_t)3328U); libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51(&zeta_i, re, (size_t)5U, (size_t)3328U); libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51(&zeta_i, re, (size_t)4U, (size_t)3328U); libcrux_ml_kem_ntt_ntt_at_layer_3_fd(&zeta_i, re, (size_t)3U, (size_t)3328U); libcrux_ml_kem_ntt_ntt_at_layer_2_ad(&zeta_i, re, (size_t)2U, (size_t)3328U); libcrux_ml_kem_ntt_ntt_at_layer_1_a2(&zeta_i, re, (size_t)1U, (size_t)3328U); libcrux_ml_kem_polynomial_poly_barrett_reduce_89_8b(re); } /** Call [`deserialize_then_decompress_ring_element_u`] on each ring element in the `ciphertext`. */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.deserialize_then_decompress_u with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - U_COMPRESSION_FACTOR= 10 */ static KRML_MUSTINLINE void libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u_f4( uint8_t *ciphertext, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { u_as_ntt[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } for (size_t i = (size_t)0U; i < Eurydice_slice_len( Eurydice_array_to_slice((size_t)1088U, ciphertext, uint8_t), uint8_t) / (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)10U / (size_t)8U); i++) { size_t i0 = i; Eurydice_slice u_bytes = Eurydice_array_to_subslice2( ciphertext, i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)10U / (size_t)8U), i0 * (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)10U / (size_t)8U) + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)10U / (size_t)8U, uint8_t); u_as_ntt[i0] = libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_u_34( u_bytes); libcrux_ml_kem_ntt_ntt_vector_u_9f(&u_as_ntt[i0]); } memcpy( ret, u_as_ntt, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with const generics - COEFFICIENT_BITS= 4 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b1( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int32_t decompressed = (int32_t)v.elements[i0] * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)4); decompressed = decompressed >> (uint32_t)((int32_t)4 + (int32_t)1); v.elements[i0] = (int16_t)decompressed; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const generics - COEFFICIENT_BITS= 4 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a1( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b1( v); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_4 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_then_decompress_4_41( Eurydice_slice serialized) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(serialized, uint8_t) / (size_t)8U; i++) { size_t i0 = i; Eurydice_slice bytes = Eurydice_slice_subslice2( serialized, i0 * (size_t)8U, i0 * (size_t)8U + (size_t)8U, uint8_t); libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_portable_deserialize_4_0d(bytes); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a1( coefficient); re.coefficients[i0] = uu____0; } return re; } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.decompress_ciphertext_coefficient with const generics - COEFFICIENT_BITS= 5 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b2( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int32_t decompressed = (int32_t)v.elements[i0] * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; decompressed = (decompressed << 1U) + ((int32_t)1 << (uint32_t)(int32_t)5); decompressed = decompressed >> (uint32_t)((int32_t)5 + (int32_t)1); v.elements[i0] = (int16_t)decompressed; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.decompress_ciphertext_coefficient_0d with const generics - COEFFICIENT_BITS= 5 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a2( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient_6b2( v); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_5 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_then_decompress_5_4e( Eurydice_slice serialized) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(serialized, uint8_t) / (size_t)10U; i++) { size_t i0 = i; Eurydice_slice bytes = Eurydice_slice_subslice2( serialized, i0 * (size_t)10U, i0 * (size_t)10U + (size_t)10U, uint8_t); re.coefficients[i0] = libcrux_ml_kem_vector_portable_deserialize_5_0d(bytes); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = libcrux_ml_kem_vector_portable_decompress_ciphertext_coefficient_0d_5a2( re.coefficients[i0]); re.coefficients[i0] = uu____1; } return re; } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_ring_element_v with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - COMPRESSION_FACTOR= 4 */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_v_56( Eurydice_slice serialized) { return libcrux_ml_kem_serialize_deserialize_then_decompress_4_41(serialized); } /** Given two `KyberPolynomialRingElement`s in their NTT representations, compute their product. Given two polynomials in the NTT domain `f^` and `ĵ`, the `iᵗʰ` coefficient of the product `k̂` is determined by the calculation: ```plaintext ĥ[2·i] + ĥ[2·i + 1]X = (f^[2·i] + f^[2·i + 1]X)·(ĝ[2·i] + ĝ[2·i + 1]X) mod (X² - ζ^(2·BitRev₇(i) + 1)) ``` This function almost implements Algorithm 10 of the NIST FIPS 203 standard, which is reproduced below: ```plaintext Input: Two arrays fˆ ∈ ℤ₂₅₆ and ĝ ∈ ℤ₂₅₆. Output: An array ĥ ∈ ℤq. for(i ← 0; i < 128; i++) (ĥ[2i], ĥ[2i+1]) ← BaseCaseMultiply(fˆ[2i], fˆ[2i+1], ĝ[2i], ĝ[2i+1], ζ^(2·BitRev₇(i) + 1)) end for return ĥ ``` We say "almost" because the coefficients of the ring element output by this function are in the Montgomery domain. The NIST FIPS 203 standard can be found at . */ /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.ntt_multiply_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_polynomial_ntt_multiply_89_2a( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *rhs) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 out = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_ntt_multiply_0d( &self->coefficients[i0], &rhs->coefficients[i0], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + (size_t)4U * i0], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + (size_t)4U * i0 + (size_t)1U], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + (size_t)4U * i0 + (size_t)2U], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + (size_t)4U * i0 + (size_t)3U]); out.coefficients[i0] = uu____0; } return out; } /** Given two polynomial ring elements `lhs` and `rhs`, compute the pointwise sum of their constituent coefficients. */ /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.add_to_ring_element_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_polynomial_add_to_ring_element_89_84( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *rhs) { for (size_t i = (size_t)0U; i < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)16U, self->coefficients, libcrux_ml_kem_vector_portable_vector_type_PortableVector), libcrux_ml_kem_vector_portable_vector_type_PortableVector); i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_add_0d(self->coefficients[i0], &rhs->coefficients[i0]); self->coefficients[i0] = uu____0; } } /** A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_1 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_1_83( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t _layer) { for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t round = i; zeta_i[0U] = zeta_i[0U] - (size_t)1U; re->coefficients[round] = libcrux_ml_kem_vector_portable_inv_ntt_layer_1_step_0d( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - (size_t)1U], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - (size_t)2U], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - (size_t)3U]); zeta_i[0U] = zeta_i[0U] - (size_t)3U; } } /** A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_2 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_2_c3( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t _layer) { for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t round = i; zeta_i[0U] = zeta_i[0U] - (size_t)1U; re->coefficients[round] = libcrux_ml_kem_vector_portable_inv_ntt_layer_2_step_0d( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - (size_t)1U]); zeta_i[0U] = zeta_i[0U] - (size_t)1U; } } /** A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_3 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_3_68( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t _layer) { for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t round = i; zeta_i[0U] = zeta_i[0U] - (size_t)1U; libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_inv_ntt_layer_3_step_0d( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); re->coefficients[round] = uu____0; } } /** A monomorphic instance of libcrux_ml_kem.invert_ntt.inv_ntt_layer_int_vec_step_reduce with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 libcrux_ml_kem_invert_ntt_inv_ntt_layer_int_vec_step_reduce_65( libcrux_ml_kem_vector_portable_vector_type_PortableVector a, libcrux_ml_kem_vector_portable_vector_type_PortableVector b, int16_t zeta_r) { libcrux_ml_kem_vector_portable_vector_type_PortableVector a_minus_b = libcrux_ml_kem_vector_portable_sub_0d(b, &a); a = libcrux_ml_kem_vector_portable_barrett_reduce_0d( libcrux_ml_kem_vector_portable_add_0d(a, &b)); b = libcrux_ml_kem_vector_traits_montgomery_multiply_fe_67(a_minus_b, zeta_r); return ( CLITERAL(libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2){ .fst = a, .snd = b}); } /** A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_at_layer_4_plus with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus_6e( size_t *zeta_i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, size_t layer) { size_t step = (size_t)1U << (uint32_t)layer; for (size_t i0 = (size_t)0U; i0 < (size_t)128U >> (uint32_t)layer; i0++) { size_t round = i0; zeta_i[0U] = zeta_i[0U] - (size_t)1U; size_t offset = round * step * (size_t)2U; size_t offset_vec = offset / LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; size_t step_vec = step / LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { size_t j = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector_x2 uu____0 = libcrux_ml_kem_invert_ntt_inv_ntt_layer_int_vec_step_reduce_65( re->coefficients[j], re->coefficients[j + step_vec], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; re->coefficients[j] = x; re->coefficients[j + step_vec] = y; } } } /** A monomorphic instance of libcrux_ml_kem.invert_ntt.invert_ntt_montgomery with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_invert_ntt_invert_ntt_montgomery_f6( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) { size_t zeta_i = LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_1_83(&zeta_i, re, (size_t)1U); libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_2_c3(&zeta_i, re, (size_t)2U); libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_3_68(&zeta_i, re, (size_t)3U); libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus_6e(&zeta_i, re, (size_t)4U); libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus_6e(&zeta_i, re, (size_t)5U); libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus_6e(&zeta_i, re, (size_t)6U); libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus_6e(&zeta_i, re, (size_t)7U); libcrux_ml_kem_polynomial_poly_barrett_reduce_89_8b(re); } /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.subtract_reduce_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_polynomial_subtract_reduce_89_d4( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 b) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient_normal_form = libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( b.coefficients[i0], (int16_t)1441); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_barrett_reduce_0d( libcrux_ml_kem_vector_portable_sub_0d(self->coefficients[i0], &coefficient_normal_form)); b.coefficients[i0] = uu____0; } return b; } /** The following functions compute various expressions involving vectors and matrices. The computation of these expressions has been abstracted away into these functions in order to save on loop iterations. Compute v − InverseNTT(sᵀ ◦ NTT(u)) */ /** A monomorphic instance of libcrux_ml_kem.matrix.compute_message with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_matrix_compute_message_b3( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *v, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *secret_as_ntt, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *u_as_ntt) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = libcrux_ml_kem_polynomial_ntt_multiply_89_2a(&secret_as_ntt[i0], &u_as_ntt[i0]); libcrux_ml_kem_polynomial_add_to_ring_element_89_84(&result, &product); } libcrux_ml_kem_invert_ntt_invert_ntt_montgomery_f6(&result); result = libcrux_ml_kem_polynomial_subtract_reduce_89_d4(v, result); return result; } /** A monomorphic instance of libcrux_ml_kem.vector.portable.arithmetic.shift_right with const generics - SHIFT_BY= 15 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_arithmetic_shift_right_94( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; v.elements[i0] = v.elements[i0] >> (uint32_t)(int32_t)15; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.shift_right_0d with const generics - SHIFT_BY= 15 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_shift_right_0d_19( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_arithmetic_shift_right_94(v); } /** A monomorphic instance of libcrux_ml_kem.vector.traits.to_unsigned_representative with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_traits_to_unsigned_representative_db( libcrux_ml_kem_vector_portable_vector_type_PortableVector a) { libcrux_ml_kem_vector_portable_vector_type_PortableVector t = libcrux_ml_kem_vector_portable_shift_right_0d_19(a); libcrux_ml_kem_vector_portable_vector_type_PortableVector fm = libcrux_ml_kem_vector_portable_bitwise_and_with_constant_0d( t, LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS); return libcrux_ml_kem_vector_portable_add_0d(a, &fm); } /** A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_message with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_compress_then_serialize_message_aa( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, uint8_t ret[32U]) { uint8_t serialized[32U] = {0U}; for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_traits_to_unsigned_representative_db( re.coefficients[i0]); libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient_compressed = libcrux_ml_kem_vector_portable_compress_1_0d(coefficient); uint8_t bytes[2U]; libcrux_ml_kem_vector_portable_serialize_1_0d(coefficient_compressed, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice2( serialized, (size_t)2U * i0, (size_t)2U * i0 + (size_t)2U, uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)2U, bytes, uint8_t), uint8_t); } memcpy(ret, serialized, (size_t)32U * sizeof(uint8_t)); } /** This function implements Algorithm 14 of the NIST FIPS 203 specification; this is the Kyber CPA-PKE decryption algorithm. Algorithm 14 is reproduced below: ```plaintext Input: decryption key dkₚₖₑ ∈ 𝔹^{384k}. Input: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. Output: message m ∈ 𝔹^{32}. c₁ ← c[0 : 32dᵤk] c₂ ← c[32dᵤk : 32(dᵤk + dᵥ)] u ← Decompress_{dᵤ}(ByteDecode_{dᵤ}(c₁)) v ← Decompress_{dᵥ}(ByteDecode_{dᵥ}(c₂)) ŝ ← ByteDecode₁₂(dkₚₖₑ) w ← v - NTT-¹(ŝᵀ ◦ NTT(u)) m ← ByteEncode₁(Compress₁(w)) return m ``` The NIST FIPS 203 standard can be found at . */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt_unpacked with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - VECTOR_U_ENCODED_SIZE= 960 - U_COMPRESSION_FACTOR= 10 - V_COMPRESSION_FACTOR= 4 */ static inline void libcrux_ml_kem_ind_cpa_decrypt_unpacked_6d( libcrux_ml_kem_ind_cpa_unpacked_IndCpaPrivateKeyUnpacked_f8 *secret_key, uint8_t *ciphertext, uint8_t ret[32U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u_as_ntt[3U]; libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u_f4(ciphertext, u_as_ntt); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_v_56( Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, (size_t)960U, uint8_t, size_t)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message = libcrux_ml_kem_matrix_compute_message_b3(&v, secret_key->secret_as_ntt, u_as_ntt); uint8_t ret0[32U]; libcrux_ml_kem_serialize_compress_then_serialize_message_aa(message, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } /** A monomorphic instance of libcrux_ml_kem.ind_cpa.decrypt with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - VECTOR_U_ENCODED_SIZE= 960 - U_COMPRESSION_FACTOR= 10 - V_COMPRESSION_FACTOR= 4 */ static inline void libcrux_ml_kem_ind_cpa_decrypt_43(Eurydice_slice secret_key, uint8_t *ciphertext, uint8_t ret[32U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; libcrux_ml_kem_ind_cpa_deserialize_secret_key_24(secret_key, secret_as_ntt); /* Passing arrays by value in Rust generates a copy in C */ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_secret_as_ntt[3U]; memcpy( copy_of_secret_as_ntt, secret_as_ntt, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); libcrux_ml_kem_ind_cpa_unpacked_IndCpaPrivateKeyUnpacked_f8 secret_key_unpacked; memcpy( secret_key_unpacked.secret_as_ntt, copy_of_secret_as_ntt, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); uint8_t ret0[32U]; libcrux_ml_kem_ind_cpa_decrypt_unpacked_6d(&secret_key_unpacked, ciphertext, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.G_f1 with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_G_f1_e4( Eurydice_slice input, uint8_t ret[64U]) { libcrux_ml_kem_hash_functions_portable_G(input, ret); } /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF with const generics - LEN= 32 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_PRF_2b( Eurydice_slice input, uint8_t ret[32U]) { uint8_t digest[32U] = {0U}; libcrux_sha3_portable_shake256( Eurydice_array_to_slice((size_t)32U, digest, uint8_t), input); memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 with const generics - K= 3 - LEN= 32 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_PRF_f1_ee( Eurydice_slice input, uint8_t ret[32U]) { libcrux_ml_kem_hash_functions_portable_PRF_2b(input, ret); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_ring_elements_reduced.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - PUBLIC_KEY_SIZE= 1152 - K= 3 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_closure_cd( size_t _i) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** Only use with public values. This MUST NOT be used with secret inputs, like its caller `deserialize_ring_elements_reduced`. */ /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_to_reduced_ring_element with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element_4c( Eurydice_slice serialized) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < Eurydice_slice_len(serialized, uint8_t) / (size_t)24U; i++) { size_t i0 = i; Eurydice_slice bytes = Eurydice_slice_subslice2( serialized, i0 * (size_t)24U, i0 * (size_t)24U + (size_t)24U, uint8_t); libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_portable_deserialize_12_0d(bytes); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_cond_subtract_3329_0d(coefficient); re.coefficients[i0] = uu____0; } return re; } /** This function deserializes ring elements and reduces the result by the field modulus. This function MUST NOT be used on secret inputs. */ /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - PUBLIC_KEY_SIZE= 1152 - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_33( Eurydice_slice public_key, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { deserialized_pk[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } for (size_t i = (size_t)0U; i < Eurydice_slice_len(public_key, uint8_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; i++) { size_t i0 = i; Eurydice_slice ring_element = Eurydice_slice_subslice2( public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, uint8_t); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element_4c( ring_element); deserialized_pk[i0] = uu____0; } memcpy( ret, deserialized_pk, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); } /** A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A.closure.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_matrix_sample_matrix_A_closure_closure_78(size_t _j) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static inline void libcrux_ml_kem_matrix_sample_matrix_A_closure_4b( size_t _i, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { for (size_t i = (size_t)0U; i < (size_t)3U; i++) { ret[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } } /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PortableHash with const generics - $3size_t */ typedef struct libcrux_ml_kem_hash_functions_portable_PortableHash_58_s { libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[3U]; } libcrux_ml_kem_hash_functions_portable_PortableHash_58; /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.shake128_init_absorb with const generics - K= 3 */ static KRML_MUSTINLINE libcrux_ml_kem_hash_functions_portable_PortableHash_58 libcrux_ml_kem_hash_functions_portable_shake128_init_absorb_b7( uint8_t input[3U][34U]) { libcrux_sha3_generic_keccak_KeccakState_48 shake128_state[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { shake128_state[i] = libcrux_sha3_portable_incremental_shake128_init(); } for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; libcrux_sha3_portable_incremental_shake128_absorb_final( &shake128_state[i0], Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t)); } /* Passing arrays by value in Rust generates a copy in C */ libcrux_sha3_generic_keccak_KeccakState_48 copy_of_shake128_state[3U]; memcpy(copy_of_shake128_state, shake128_state, (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); libcrux_ml_kem_hash_functions_portable_PortableHash_58 lit; memcpy(lit.shake128_state, copy_of_shake128_state, (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState_48)); return lit; } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.shake128_init_absorb_f1 with const generics - K= 3 */ static KRML_MUSTINLINE libcrux_ml_kem_hash_functions_portable_PortableHash_58 libcrux_ml_kem_hash_functions_portable_shake128_init_absorb_f1_8c( uint8_t input[3U][34U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_input[3U][34U]; memcpy(copy_of_input, input, (size_t)3U * sizeof(uint8_t[34U])); return libcrux_ml_kem_hash_functions_portable_shake128_init_absorb_b7( copy_of_input); } /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_shake128_squeeze_three_blocks_ca( libcrux_ml_kem_hash_functions_portable_PortableHash_58 *st, uint8_t ret[3U][504U]) { uint8_t out[3U][504U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( &st->shake128_state[i0], Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t)); } memcpy(ret, out, (size_t)3U * sizeof(uint8_t[504U])); } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.shake128_squeeze_three_blocks_f1 with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_shake128_squeeze_three_blocks_f1_69( libcrux_ml_kem_hash_functions_portable_PortableHash_58 *self, uint8_t ret[3U][504U]) { libcrux_ml_kem_hash_functions_portable_shake128_squeeze_three_blocks_ca(self, ret); } /** If `bytes` contains a set of uniformly random bytes, this function uniformly samples a ring element `â` that is treated as being the NTT representation of the corresponding polynomial `a`. Since rejection sampling is used, it is possible the supplied bytes are not enough to sample the element, in which case an `Err` is returned and the caller must try again with a fresh set of bytes. This function partially implements Algorithm 6 of the NIST FIPS 203 standard, We say "partially" because this implementation only accepts a finite set of bytes as input and returns an error if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other hand samples from an infinite stream of bytes until the ring element is filled. Algorithm 6 is reproduced below: ```plaintext Input: byte stream B ∈ 𝔹*. Output: array â ∈ ℤ₂₅₆. i ← 0 j ← 0 while j < 256 do d₁ ← B[i] + 256·(B[i+1] mod 16) d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] if d₁ < q then â[j] ← d₁ j ← j + 1 end if if d₂ < q and j < 256 then â[j] ← d₂ j ← j + 1 end if i ← i + 3 end while return â ``` The NIST FIPS 203 standard can be found at . */ /** A monomorphic instance of libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - N= 504 */ static KRML_MUSTINLINE bool libcrux_ml_kem_sampling_sample_from_uniform_distribution_next_db( uint8_t randomness[3U][504U], size_t *sampled_coefficients, int16_t (*out)[272U]) { for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { size_t i1 = i0; for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { size_t r = i; if (sampled_coefficients[i1] < LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2(randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, uint8_t); size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( uu____0, Eurydice_array_to_subslice2( out[i1], sampled_coefficients[i1], sampled_coefficients[i1] + (size_t)16U, int16_t)); size_t uu____1 = i1; sampled_coefficients[uu____1] = sampled_coefficients[uu____1] + sampled; } } } bool done = true; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; if (sampled_coefficients[i0] >= LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { sampled_coefficients[i0] = LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; } else { done = false; } } return done; } /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_shake128_squeeze_block_dd( libcrux_ml_kem_hash_functions_portable_PortableHash_58 *st, uint8_t ret[3U][168U]) { uint8_t out[3U][168U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; libcrux_sha3_portable_incremental_shake128_squeeze_next_block( &st->shake128_state[i0], Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t)); } memcpy(ret, out, (size_t)3U * sizeof(uint8_t[168U])); } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.shake128_squeeze_block_f1 with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_shake128_squeeze_block_f1_60( libcrux_ml_kem_hash_functions_portable_PortableHash_58 *self, uint8_t ret[3U][168U]) { libcrux_ml_kem_hash_functions_portable_shake128_squeeze_block_dd(self, ret); } /** If `bytes` contains a set of uniformly random bytes, this function uniformly samples a ring element `â` that is treated as being the NTT representation of the corresponding polynomial `a`. Since rejection sampling is used, it is possible the supplied bytes are not enough to sample the element, in which case an `Err` is returned and the caller must try again with a fresh set of bytes. This function partially implements Algorithm 6 of the NIST FIPS 203 standard, We say "partially" because this implementation only accepts a finite set of bytes as input and returns an error if the set is not enough; Algorithm 6 of the FIPS 203 standard on the other hand samples from an infinite stream of bytes until the ring element is filled. Algorithm 6 is reproduced below: ```plaintext Input: byte stream B ∈ 𝔹*. Output: array â ∈ ℤ₂₅₆. i ← 0 j ← 0 while j < 256 do d₁ ← B[i] + 256·(B[i+1] mod 16) d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] if d₁ < q then â[j] ← d₁ j ← j + 1 end if if d₂ < q and j < 256 then â[j] ← d₂ j ← j + 1 end if i ← i + 3 end while return â ``` The NIST FIPS 203 standard can be found at . */ /** A monomorphic instance of libcrux_ml_kem.sampling.sample_from_uniform_distribution_next with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - N= 168 */ static KRML_MUSTINLINE bool libcrux_ml_kem_sampling_sample_from_uniform_distribution_next_db0( uint8_t randomness[3U][168U], size_t *sampled_coefficients, int16_t (*out)[272U]) { for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { size_t i1 = i0; for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { size_t r = i; if (sampled_coefficients[i1] < LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { Eurydice_slice uu____0 = Eurydice_array_to_subslice2(randomness[i1], r * (size_t)24U, r * (size_t)24U + (size_t)24U, uint8_t); size_t sampled = libcrux_ml_kem_vector_portable_rej_sample_0d( uu____0, Eurydice_array_to_subslice2( out[i1], sampled_coefficients[i1], sampled_coefficients[i1] + (size_t)16U, int16_t)); size_t uu____1 = i1; sampled_coefficients[uu____1] = sampled_coefficients[uu____1] + sampled; } } } bool done = true; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; if (sampled_coefficients[i0] >= LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { sampled_coefficients[i0] = LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; } else { done = false; } } return done; } /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.from_i16_array_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_polynomial_from_i16_array_89_c1(Eurydice_slice a) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_from_i16_array_0d( Eurydice_slice_subslice2(a, i0 * (size_t)16U, (i0 + (size_t)1U) * (size_t)16U, int16_t)); result.coefficients[i0] = uu____0; } return result; } /** A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_sampling_sample_from_xof_closure_04(int16_t s[272U]) { return libcrux_ml_kem_polynomial_from_i16_array_89_c1( Eurydice_array_to_subslice2(s, (size_t)0U, (size_t)256U, int16_t)); } /** A monomorphic instance of libcrux_ml_kem.sampling.sample_from_xof with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_sampling_sample_from_xof_3f( uint8_t seeds[3U][34U], libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { size_t sampled_coefficients[3U] = {0U}; int16_t out[3U][272U] = {{0U}}; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_seeds[3U][34U]; memcpy(copy_of_seeds, seeds, (size_t)3U * sizeof(uint8_t[34U])); libcrux_ml_kem_hash_functions_portable_PortableHash_58 xof_state = libcrux_ml_kem_hash_functions_portable_shake128_init_absorb_f1_8c( copy_of_seeds); uint8_t randomness0[3U][504U]; libcrux_ml_kem_hash_functions_portable_shake128_squeeze_three_blocks_f1_69( &xof_state, randomness0); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness0[3U][504U]; memcpy(copy_of_randomness0, randomness0, (size_t)3U * sizeof(uint8_t[504U])); bool done = libcrux_ml_kem_sampling_sample_from_uniform_distribution_next_db( copy_of_randomness0, sampled_coefficients, out); while (true) { if (done) { break; } else { uint8_t randomness[3U][168U]; libcrux_ml_kem_hash_functions_portable_shake128_squeeze_block_f1_60( &xof_state, randomness); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[3U][168U]; memcpy(copy_of_randomness, randomness, (size_t)3U * sizeof(uint8_t[168U])); done = libcrux_ml_kem_sampling_sample_from_uniform_distribution_next_db0( copy_of_randomness, sampled_coefficients, out); } } /* Passing arrays by value in Rust generates a copy in C */ int16_t copy_of_out[3U][272U]; memcpy(copy_of_out, out, (size_t)3U * sizeof(int16_t[272U])); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret0[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { ret0[i] = libcrux_ml_kem_sampling_sample_from_xof_closure_04(copy_of_out[i]); } memcpy( ret, ret0, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); } /** A monomorphic instance of libcrux_ml_kem.matrix.sample_matrix_A with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_matrix_sample_matrix_A_38( uint8_t seed[34U], bool transpose, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U][3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[3U][3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { libcrux_ml_kem_matrix_sample_matrix_A_closure_4b(i, A_transpose[i]); } for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { size_t i1 = i0; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_seed[34U]; memcpy(copy_of_seed, seed, (size_t)34U * sizeof(uint8_t)); uint8_t seeds[3U][34U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { memcpy(seeds[i], copy_of_seed, (size_t)34U * sizeof(uint8_t)); } for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t j = i; seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j; } /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_seeds[3U][34U]; memcpy(copy_of_seeds, seeds, (size_t)3U * sizeof(uint8_t[34U])); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sampled[3U]; libcrux_ml_kem_sampling_sample_from_xof_3f(copy_of_seeds, sampled); for (size_t i = (size_t)0U; i < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)3U, sampled, libcrux_ml_kem_polynomial_PolynomialRingElement_f0), libcrux_ml_kem_polynomial_PolynomialRingElement_f0); i++) { size_t j = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 sample = sampled[j]; if (transpose) { A_transpose[j][i1] = sample; } else { A_transpose[i1][j] = sample; } } } memcpy(ret, A_transpose, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U])); } /** A monomorphic instance of K. with types libcrux_ml_kem_polynomial_PolynomialRingElement libcrux_ml_kem_vector_portable_vector_type_PortableVector[3size_t], uint8_t */ typedef struct tuple_b0_s { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 fst[3U]; uint8_t snd; } tuple_b0; /** A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_vector_cbd_then_ntt.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - ETA= 2 - ETA_RANDOMNESS_SIZE= 128 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_closure_f7(size_t _i) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN with const generics - K= 3 - LEN= 128 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_PRFxN_c5( uint8_t (*input)[33U], uint8_t ret[3U][128U]) { uint8_t out[3U][128U] = {{0U}}; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; libcrux_sha3_portable_shake256( Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t), Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t)); } memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRFxN_f1 with const generics - K= 3 - LEN= 128 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_PRFxN_f1_93( uint8_t (*input)[33U], uint8_t ret[3U][128U]) { libcrux_ml_kem_hash_functions_portable_PRFxN_c5(input, ret); } /** Given a series of uniformly random bytes in `randomness`, for some number `eta`, the `sample_from_binomial_distribution_{eta}` functions sample a ring element from a binomial distribution centered at 0 that uses two sets of `eta` coin flips. If, for example, `eta = ETA`, each ring coefficient is a value `v` such such that `v ∈ {-ETA, -ETA + 1, ..., 0, ..., ETA + 1, ETA}` and: ```plaintext - If v < 0, Pr[v] = Pr[-v] - If v >= 0, Pr[v] = BINOMIAL_COEFFICIENT(2 * ETA; ETA - v) / 2 ^ (2 * ETA) ``` The values `v < 0` are mapped to the appropriate `KyberFieldElement`. The expected value is: ```plaintext E[X] = (-ETA)Pr[-ETA] + (-(ETA - 1))Pr[-(ETA - 1)] + ... + (ETA - 1)Pr[ETA - 1] + (ETA)Pr[ETA] = 0 since Pr[-v] = Pr[v] when v < 0. ``` And the variance is: ```plaintext Var(X) = E[(X - E[X])^2] = E[X^2] = sum_(v=-ETA to ETA)v^2 * (BINOMIAL_COEFFICIENT(2 * ETA; ETA - v) / 2^(2 * ETA)) = ETA / 2 ``` This function implements Algorithm 7 of the NIST FIPS 203 standard, which is reproduced below: ```plaintext Input: byte array B ∈ 𝔹^{64η}. Output: array f ∈ ℤ₂₅₆. b ← BytesToBits(B) for (i ← 0; i < 256; i++) x ← ∑(j=0 to η - 1) b[2iη + j] y ← ∑(j=0 to η - 1) b[2iη + η + j] f[i] ← x−y mod q end for return f ``` The NIST FIPS 203 standard can be found at . */ /** A monomorphic instance of libcrux_ml_kem.sampling.sample_from_binomial_distribution_2 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_sampling_sample_from_binomial_distribution_2_85( Eurydice_slice randomness) { int16_t sampled_i16s[256U] = {0U}; for (size_t i0 = (size_t)0U; i0 < Eurydice_slice_len(randomness, uint8_t) / (size_t)4U; i0++) { size_t chunk_number = i0; Eurydice_slice byte_chunk = Eurydice_slice_subslice2( randomness, chunk_number * (size_t)4U, chunk_number * (size_t)4U + (size_t)4U, uint8_t); uint32_t random_bits_as_u32 = (((uint32_t)Eurydice_slice_index(byte_chunk, (size_t)0U, uint8_t, uint8_t *) | (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)1U, uint8_t, uint8_t *) << 8U) | (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)2U, uint8_t, uint8_t *) << 16U) | (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)3U, uint8_t, uint8_t *) << 24U; uint32_t even_bits = random_bits_as_u32 & 1431655765U; uint32_t odd_bits = random_bits_as_u32 >> 1U & 1431655765U; uint32_t coin_toss_outcomes = even_bits + odd_bits; for (uint32_t i = 0U; i < CORE_NUM__U32_8__BITS / 4U; i++) { uint32_t outcome_set = i; uint32_t outcome_set0 = outcome_set * 4U; int16_t outcome_1 = (int16_t)(coin_toss_outcomes >> (uint32_t)outcome_set0 & 3U); int16_t outcome_2 = (int16_t)(coin_toss_outcomes >> (uint32_t)(outcome_set0 + 2U) & 3U); size_t offset = (size_t)(outcome_set0 >> 2U); sampled_i16s[(size_t)8U * chunk_number + offset] = outcome_1 - outcome_2; } } return libcrux_ml_kem_polynomial_from_i16_array_89_c1( Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t)); } /** A monomorphic instance of libcrux_ml_kem.sampling.sample_from_binomial_distribution_3 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_sampling_sample_from_binomial_distribution_3_eb( Eurydice_slice randomness) { int16_t sampled_i16s[256U] = {0U}; for (size_t i0 = (size_t)0U; i0 < Eurydice_slice_len(randomness, uint8_t) / (size_t)3U; i0++) { size_t chunk_number = i0; Eurydice_slice byte_chunk = Eurydice_slice_subslice2( randomness, chunk_number * (size_t)3U, chunk_number * (size_t)3U + (size_t)3U, uint8_t); uint32_t random_bits_as_u24 = ((uint32_t)Eurydice_slice_index(byte_chunk, (size_t)0U, uint8_t, uint8_t *) | (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)1U, uint8_t, uint8_t *) << 8U) | (uint32_t)Eurydice_slice_index(byte_chunk, (size_t)2U, uint8_t, uint8_t *) << 16U; uint32_t first_bits = random_bits_as_u24 & 2396745U; uint32_t second_bits = random_bits_as_u24 >> 1U & 2396745U; uint32_t third_bits = random_bits_as_u24 >> 2U & 2396745U; uint32_t coin_toss_outcomes = first_bits + second_bits + third_bits; for (int32_t i = (int32_t)0; i < (int32_t)24 / (int32_t)6; i++) { int32_t outcome_set = i; int32_t outcome_set0 = outcome_set * (int32_t)6; int16_t outcome_1 = (int16_t)(coin_toss_outcomes >> (uint32_t)outcome_set0 & 7U); int16_t outcome_2 = (int16_t)(coin_toss_outcomes >> (uint32_t)(outcome_set0 + (int32_t)3) & 7U); size_t offset = (size_t)(outcome_set0 / (int32_t)6); sampled_i16s[(size_t)4U * chunk_number + offset] = outcome_1 - outcome_2; } } return libcrux_ml_kem_polynomial_from_i16_array_89_c1( Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t)); } /** A monomorphic instance of libcrux_ml_kem.sampling.sample_from_binomial_distribution with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - ETA= 2 */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_sampling_sample_from_binomial_distribution_c6( Eurydice_slice randomness) { return libcrux_ml_kem_sampling_sample_from_binomial_distribution_2_85( randomness); } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_at_layer_7 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_ntt_ntt_at_layer_7_f4( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) { size_t step = LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT / (size_t)2U; for (size_t i = (size_t)0U; i < step; i++) { size_t j = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector t = libcrux_ml_kem_vector_portable_multiply_by_constant_0d( re->coefficients[j + step], (int16_t)-1600); re->coefficients[j + step] = libcrux_ml_kem_vector_portable_sub_0d(re->coefficients[j], &t); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = libcrux_ml_kem_vector_portable_add_0d(re->coefficients[j], &t); re->coefficients[j] = uu____1; } } /** A monomorphic instance of libcrux_ml_kem.ntt.ntt_binomially_sampled_ring_element with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element_0f( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re) { libcrux_ml_kem_ntt_ntt_at_layer_7_f4(re); size_t zeta_i = (size_t)1U; libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51(&zeta_i, re, (size_t)6U, (size_t)3U); libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51(&zeta_i, re, (size_t)5U, (size_t)3U); libcrux_ml_kem_ntt_ntt_at_layer_4_plus_51(&zeta_i, re, (size_t)4U, (size_t)3U); libcrux_ml_kem_ntt_ntt_at_layer_3_fd(&zeta_i, re, (size_t)3U, (size_t)3U); libcrux_ml_kem_ntt_ntt_at_layer_2_ad(&zeta_i, re, (size_t)2U, (size_t)3U); libcrux_ml_kem_ntt_ntt_at_layer_1_a2(&zeta_i, re, (size_t)1U, (size_t)3U); libcrux_ml_kem_polynomial_poly_barrett_reduce_89_8b(re); } /** Sample a vector of ring elements from a centered binomial distribution and convert them into their NTT representations. */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_vector_cbd_then_ntt with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - ETA= 2 - ETA_RANDOMNESS_SIZE= 128 */ static KRML_MUSTINLINE tuple_b0 libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_fc(uint8_t prf_input[33U], uint8_t domain_separator) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re_as_ntt[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { re_as_ntt[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input[33U]; memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t)); } for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; prf_inputs[i0][32U] = domain_separator; domain_separator = (uint32_t)domain_separator + 1U; } uint8_t prf_outputs[3U][128U]; libcrux_ml_kem_hash_functions_portable_PRFxN_f1_93(prf_inputs, prf_outputs); for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; re_as_ntt[i0] = libcrux_ml_kem_sampling_sample_from_binomial_distribution_c6( Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t)); libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element_0f(&re_as_ntt[i0]); } /* Passing arrays by value in Rust generates a copy in C */ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_re_as_ntt[3U]; memcpy( copy_of_re_as_ntt, re_as_ntt, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); tuple_b0 lit; memcpy( lit.fst, copy_of_re_as_ntt, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); lit.snd = domain_separator; return lit; } /** A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_ring_element_cbd.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - ETA2_RANDOMNESS_SIZE= 128 - ETA2= 2 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_ind_cpa_sample_ring_element_cbd_closure_77(size_t _i) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** Sample a vector of ring elements from a centered binomial distribution. */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.sample_ring_element_cbd with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - ETA2_RANDOMNESS_SIZE= 128 - ETA2= 2 */ static KRML_MUSTINLINE tuple_b0 libcrux_ml_kem_ind_cpa_sample_ring_element_cbd_ac(uint8_t prf_input[33U], uint8_t domain_separator) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { error_1[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input[33U]; memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { memcpy(prf_inputs[i], copy_of_prf_input, (size_t)33U * sizeof(uint8_t)); } for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; prf_inputs[i0][32U] = domain_separator; domain_separator = (uint32_t)domain_separator + 1U; } uint8_t prf_outputs[3U][128U]; libcrux_ml_kem_hash_functions_portable_PRFxN_f1_93(prf_inputs, prf_outputs); for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____1 = libcrux_ml_kem_sampling_sample_from_binomial_distribution_c6( Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t)); error_1[i0] = uu____1; } /* Passing arrays by value in Rust generates a copy in C */ libcrux_ml_kem_polynomial_PolynomialRingElement_f0 copy_of_error_1[3U]; memcpy( copy_of_error_1, error_1, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); tuple_b0 lit; memcpy( lit.fst, copy_of_error_1, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); lit.snd = domain_separator; return lit; } /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF with const generics - LEN= 128 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_PRF_2b0( Eurydice_slice input, uint8_t ret[128U]) { uint8_t digest[128U] = {0U}; libcrux_sha3_portable_shake256( Eurydice_array_to_slice((size_t)128U, digest, uint8_t), input); memcpy(ret, digest, (size_t)128U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.PRF_f1 with const generics - K= 3 - LEN= 128 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_PRF_f1_ee0( Eurydice_slice input, uint8_t ret[128U]) { libcrux_ml_kem_hash_functions_portable_PRF_2b0(input, ret); } /** A monomorphic instance of libcrux_ml_kem.matrix.compute_vector_u.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_matrix_compute_vector_u_closure_d6(size_t _i) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.add_error_reduce_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_polynomial_add_error_reduce_89_38( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t j = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient_normal_form = libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( self->coefficients[j], (int16_t)1441); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_barrett_reduce_0d( libcrux_ml_kem_vector_portable_add_0d(coefficient_normal_form, &error->coefficients[j])); self->coefficients[j] = uu____0; } } /** Compute u := InvertNTT(Aᵀ ◦ r̂) + e₁ */ /** A monomorphic instance of libcrux_ml_kem.matrix.compute_vector_u with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_matrix_compute_vector_u_59( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*a_as_ntt)[3U], libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_1, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { result[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } for (size_t i0 = (size_t)0U; i0 < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)3U, a_as_ntt, libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]), libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]); i0++) { size_t i1 = i0; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = a_as_ntt[i1]; for (size_t i = (size_t)0U; i < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)3U, row, libcrux_ml_kem_polynomial_PolynomialRingElement_f0), libcrux_ml_kem_polynomial_PolynomialRingElement_f0); i++) { size_t j = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *a_element = &row[j]; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = libcrux_ml_kem_polynomial_ntt_multiply_89_2a(a_element, &r_as_ntt[j]); libcrux_ml_kem_polynomial_add_to_ring_element_89_84(&result[i1], &product); } libcrux_ml_kem_invert_ntt_invert_ntt_montgomery_f6(&result[i1]); libcrux_ml_kem_polynomial_add_error_reduce_89_38(&result[i1], &error_1[i1]); } memcpy( ret, result, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); } /** A monomorphic instance of libcrux_ml_kem.vector.traits.decompress_1 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_traits_decompress_1_63( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_ZERO_0d(); return libcrux_ml_kem_vector_portable_bitwise_and_with_constant_0d( libcrux_ml_kem_vector_portable_sub_0d(uu____0, &v), (int16_t)1665); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_then_decompress_message with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_then_decompress_message_0d( uint8_t serialized[32U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < (size_t)16U; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient_compressed = libcrux_ml_kem_vector_portable_deserialize_1_0d( Eurydice_array_to_subslice2(serialized, (size_t)2U * i0, (size_t)2U * i0 + (size_t)2U, uint8_t)); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_traits_decompress_1_63(coefficient_compressed); re.coefficients[i0] = uu____0; } return re; } /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.add_message_error_reduce_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_polynomial_add_message_error_reduce_89_ea( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *message, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient_normal_form = libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( result.coefficients[i0], (int16_t)1441); libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp = libcrux_ml_kem_vector_portable_add_0d(self->coefficients[i0], &message->coefficients[i0]); libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp0 = libcrux_ml_kem_vector_portable_add_0d(coefficient_normal_form, &tmp); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_barrett_reduce_0d(tmp0); result.coefficients[i0] = uu____0; } return result; } /** Compute InverseNTT(tᵀ ◦ r̂) + e₂ + message */ /** A monomorphic instance of libcrux_ml_kem.matrix.compute_ring_element_v with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static KRML_MUSTINLINE libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_matrix_compute_ring_element_v_54( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *r_as_ntt, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_2, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *message) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result = libcrux_ml_kem_polynomial_ZERO_89_ea(); for (size_t i = (size_t)0U; i < (size_t)3U; i++) { size_t i0 = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = libcrux_ml_kem_polynomial_ntt_multiply_89_2a(&t_as_ntt[i0], &r_as_ntt[i0]); libcrux_ml_kem_polynomial_add_to_ring_element_89_84(&result, &product); } libcrux_ml_kem_invert_ntt_invert_ntt_montgomery_f6(&result); result = libcrux_ml_kem_polynomial_add_message_error_reduce_89_ea( error_2, message, result); return result; } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress with const generics - COEFFICIENT_BITS= 10 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_compress_02( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( (uint8_t)(int32_t)10, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d with const generics - COEFFICIENT_BITS= 10 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_0d_28( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_compress_02(v); } /** A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_10 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - OUT_LEN= 320 */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_compress_then_serialize_10_fc( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[320U]) { uint8_t serialized[320U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_portable_compress_0d_28( libcrux_ml_kem_vector_traits_to_unsigned_representative_db( re->coefficients[i0])); uint8_t bytes[20U]; libcrux_ml_kem_vector_portable_serialize_10_0d(coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice2( serialized, (size_t)20U * i0, (size_t)20U * i0 + (size_t)20U, uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)20U, bytes, uint8_t), uint8_t); } memcpy(ret, serialized, (size_t)320U * sizeof(uint8_t)); } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress with const generics - COEFFICIENT_BITS= 11 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_compress_020( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( (uint8_t)(int32_t)11, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d with const generics - COEFFICIENT_BITS= 11 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_0d_280( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_compress_020(v); } /** A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_11 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - OUT_LEN= 320 */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_compress_then_serialize_11_e1( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[320U]) { uint8_t serialized[320U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_portable_compress_0d_280( libcrux_ml_kem_vector_traits_to_unsigned_representative_db( re->coefficients[i0])); uint8_t bytes[22U]; libcrux_ml_kem_vector_portable_serialize_11_0d(coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice2( serialized, (size_t)22U * i0, (size_t)22U * i0 + (size_t)22U, uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)22U, bytes, uint8_t), uint8_t); } memcpy(ret, serialized, (size_t)320U * sizeof(uint8_t)); } /** A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_ring_element_u with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - COMPRESSION_FACTOR= 10 - OUT_LEN= 320 */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_compress_then_serialize_ring_element_u_5f( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[320U]) { uint8_t uu____0[320U]; libcrux_ml_kem_serialize_compress_then_serialize_10_fc(re, uu____0); memcpy(ret, uu____0, (size_t)320U * sizeof(uint8_t)); } /** Call [`compress_then_serialize_ring_element_u`] on each ring element. */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.compress_then_serialize_u with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - OUT_LEN= 960 - COMPRESSION_FACTOR= 10 - BLOCK_LEN= 320 */ static inline void libcrux_ml_kem_ind_cpa_compress_then_serialize_u_a7( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 input[3U], Eurydice_slice out) { for (size_t i = (size_t)0U; i < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)3U, input, libcrux_ml_kem_polynomial_PolynomialRingElement_f0), libcrux_ml_kem_polynomial_PolynomialRingElement_f0); i++) { size_t i0 = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = input[i0]; Eurydice_slice uu____0 = Eurydice_slice_subslice2( out, i0 * ((size_t)960U / (size_t)3U), (i0 + (size_t)1U) * ((size_t)960U / (size_t)3U), uint8_t); uint8_t ret[320U]; libcrux_ml_kem_serialize_compress_then_serialize_ring_element_u_5f(&re, ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)320U, ret, uint8_t), uint8_t); } } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress with const generics - COEFFICIENT_BITS= 4 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_compress_021( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( (uint8_t)(int32_t)4, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d with const generics - COEFFICIENT_BITS= 4 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_0d_281( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_compress_021(v); } /** A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_4 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_compress_then_serialize_4_9a( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, Eurydice_slice serialized) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_portable_compress_0d_281( libcrux_ml_kem_vector_traits_to_unsigned_representative_db( re.coefficients[i0])); uint8_t bytes[8U]; libcrux_ml_kem_vector_portable_serialize_4_0d(coefficient, bytes); Eurydice_slice_copy( Eurydice_slice_subslice2(serialized, (size_t)8U * i0, (size_t)8U * i0 + (size_t)8U, uint8_t), Eurydice_array_to_slice((size_t)8U, bytes, uint8_t), uint8_t); } } /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress.compress with const generics - COEFFICIENT_BITS= 5 */ static KRML_MUSTINLINE libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_compress_022( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( (uint8_t)(int32_t)5, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } /** This function found in impl {(libcrux_ml_kem::vector::traits::Operations for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ /** A monomorphic instance of libcrux_ml_kem.vector.portable.compress_0d with const generics - COEFFICIENT_BITS= 5 */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_compress_0d_282( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_compress_compress_022(v); } /** A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_5 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_compress_then_serialize_5_1f( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, Eurydice_slice serialized) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients = libcrux_ml_kem_vector_portable_compress_0d_282( libcrux_ml_kem_vector_traits_to_unsigned_representative_db( re.coefficients[i0])); uint8_t bytes[10U]; libcrux_ml_kem_vector_portable_serialize_5_0d(coefficients, bytes); Eurydice_slice_copy( Eurydice_slice_subslice2(serialized, (size_t)10U * i0, (size_t)10U * i0 + (size_t)10U, uint8_t), Eurydice_array_to_slice((size_t)10U, bytes, uint8_t), uint8_t); } } /** A monomorphic instance of libcrux_ml_kem.serialize.compress_then_serialize_ring_element_v with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - COMPRESSION_FACTOR= 4 - OUT_LEN= 128 */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_compress_then_serialize_ring_element_v_4e( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re, Eurydice_slice out) { libcrux_ml_kem_serialize_compress_then_serialize_4_9a(re, out); } /** A monomorphic instance of libcrux_ml_kem.ind_cpa.encrypt with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_LEN= 960 - C2_LEN= 128 - U_COMPRESSION_FACTOR= 10 - V_COMPRESSION_FACTOR= 4 - BLOCK_LEN= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 */ static inline void libcrux_ml_kem_ind_cpa_encrypt_60(Eurydice_slice public_key, uint8_t message[32U], Eurydice_slice randomness, uint8_t ret[1088U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[3U]; libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_33( Eurydice_slice_subslice_to(public_key, (size_t)1152U, uint8_t, size_t), t_as_ntt); Eurydice_slice seed = Eurydice_slice_subslice_from(public_key, (size_t)1152U, uint8_t, size_t); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A[3U][3U]; uint8_t ret0[34U]; libcrux_ml_kem_utils_into_padded_array_ea1(seed, ret0); libcrux_ml_kem_matrix_sample_matrix_A_38(ret0, false, A); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array_ea2(randomness, prf_input); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input0[33U]; memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); tuple_b0 uu____1 = libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_fc( copy_of_prf_input0, 0U); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 r_as_ntt[3U]; memcpy( r_as_ntt, uu____1.fst, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); uint8_t domain_separator0 = uu____1.snd; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input[33U]; memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); tuple_b0 uu____3 = libcrux_ml_kem_ind_cpa_sample_ring_element_cbd_ac( copy_of_prf_input, domain_separator0); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_1[3U]; memcpy( error_1, uu____3.fst, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); uint8_t domain_separator = uu____3.snd; prf_input[32U] = domain_separator; uint8_t prf_output[128U]; libcrux_ml_kem_hash_functions_portable_PRF_f1_ee0( Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t), prf_output); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_2 = libcrux_ml_kem_sampling_sample_from_binomial_distribution_c6( Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 u[3U]; libcrux_ml_kem_matrix_compute_vector_u_59(A, r_as_ntt, error_1, u); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_message[32U]; memcpy(copy_of_message, message, (size_t)32U * sizeof(uint8_t)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 message_as_ring_element = libcrux_ml_kem_serialize_deserialize_then_decompress_message_0d( copy_of_message); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 v = libcrux_ml_kem_matrix_compute_ring_element_v_54( t_as_ntt, r_as_ntt, &error_2, &message_as_ring_element); uint8_t ciphertext[1088U] = {0U}; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____5[3U]; memcpy( uu____5, u, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); libcrux_ml_kem_ind_cpa_compress_then_serialize_u_a7( uu____5, Eurydice_array_to_subslice2(ciphertext, (size_t)0U, (size_t)960U, uint8_t)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____6 = v; libcrux_ml_kem_serialize_compress_then_serialize_ring_element_v_4e( uu____6, Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, (size_t)960U, uint8_t, size_t)); memcpy(ret, ciphertext, (size_t)1088U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::variant::Variant for libcrux_ml_kem::variant::MlKem)#1} */ /** A monomorphic instance of libcrux_ml_kem.variant.kdf_d8 with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 */ static KRML_MUSTINLINE void libcrux_ml_kem_variant_kdf_d8_41( Eurydice_slice shared_secret, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *_, uint8_t ret[32U]) { uint8_t out[32U] = {0U}; Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), shared_secret, uint8_t); memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } /** A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_MlKem with const generics - K= 3 - SECRET_KEY_SIZE= 2400 - CPA_SECRET_KEY_SIZE= 1152 - PUBLIC_KEY_SIZE= 1184 - CIPHERTEXT_SIZE= 1088 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - C1_BLOCK_SIZE= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 - IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1120 */ static inline void libcrux_ml_kem_ind_cca_decapsulate_70( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)2400U, private_key->value, uint8_t), (size_t)1152U, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice ind_cpa_secret_key = uu____0.fst; Eurydice_slice secret_key0 = uu____0.snd; Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( secret_key0, (size_t)1184U, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice ind_cpa_public_key = uu____1.fst; Eurydice_slice secret_key = uu____1.snd; Eurydice_slice_uint8_t_x2 uu____2 = Eurydice_slice_split_at( secret_key, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; Eurydice_slice implicit_rejection_value = uu____2.snd; uint8_t decrypted[32U]; libcrux_ml_kem_ind_cpa_decrypt_43(ind_cpa_secret_key, ciphertext->value, decrypted); uint8_t to_hash0[64U]; libcrux_ml_kem_utils_into_padded_array_ea( Eurydice_array_to_slice((size_t)32U, decrypted, uint8_t), to_hash0); Eurydice_slice_copy( Eurydice_array_to_subslice_from( (size_t)64U, to_hash0, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, size_t), ind_cpa_public_key_hash, uint8_t); uint8_t hashed[64U]; libcrux_ml_kem_hash_functions_portable_G_f1_e4( Eurydice_array_to_slice((size_t)64U, to_hash0, uint8_t), hashed); Eurydice_slice_uint8_t_x2 uu____3 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice shared_secret0 = uu____3.fst; Eurydice_slice pseudorandomness = uu____3.snd; uint8_t to_hash[1120U]; libcrux_ml_kem_utils_into_padded_array_ea0(implicit_rejection_value, to_hash); Eurydice_slice uu____4 = Eurydice_array_to_subslice_from( (size_t)1120U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, size_t); Eurydice_slice_copy(uu____4, libcrux_ml_kem_types_as_ref_00_24(ciphertext), uint8_t); uint8_t implicit_rejection_shared_secret0[32U]; libcrux_ml_kem_hash_functions_portable_PRF_f1_ee( Eurydice_array_to_slice((size_t)1120U, to_hash, uint8_t), implicit_rejection_shared_secret0); Eurydice_slice uu____5 = ind_cpa_public_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_decrypted[32U]; memcpy(copy_of_decrypted, decrypted, (size_t)32U * sizeof(uint8_t)); uint8_t expected_ciphertext[1088U]; libcrux_ml_kem_ind_cpa_encrypt_60(uu____5, copy_of_decrypted, pseudorandomness, expected_ciphertext); uint8_t implicit_rejection_shared_secret[32U]; libcrux_ml_kem_variant_kdf_d8_41( Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret0, uint8_t), ciphertext, implicit_rejection_shared_secret); uint8_t shared_secret[32U]; libcrux_ml_kem_variant_kdf_d8_41(shared_secret0, ciphertext, shared_secret); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( libcrux_ml_kem_types_as_ref_00_24(ciphertext), Eurydice_array_to_slice((size_t)1088U, expected_ciphertext, uint8_t), Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t), ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } /** Portable decapsulate */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.decapsulate with const generics - K= 3 - SECRET_KEY_SIZE= 2400 - CPA_SECRET_KEY_SIZE= 1152 - PUBLIC_KEY_SIZE= 1184 - CIPHERTEXT_SIZE= 1088 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - C1_BLOCK_SIZE= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 - IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1120 */ static inline void libcrux_ml_kem_ind_cca_instantiations_portable_decapsulate_2e( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { libcrux_ml_kem_ind_cca_decapsulate_70(private_key, ciphertext, ret); } /** Decapsulate ML-KEM 768 Generates an [`MlKemSharedSecret`]. The input is a reference to an [`MlKem768PrivateKey`] and an [`MlKem768Ciphertext`]. */ static inline void libcrux_ml_kem_mlkem768_portable_decapsulate( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { libcrux_ml_kem_ind_cca_instantiations_portable_decapsulate_2e( private_key, ciphertext, ret); } /** This function found in impl {(libcrux_ml_kem::variant::Variant for libcrux_ml_kem::variant::MlKem)#1} */ /** A monomorphic instance of libcrux_ml_kem.variant.entropy_preprocess_d8 with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_variant_entropy_preprocess_d8_63( Eurydice_slice randomness, uint8_t ret[32U]) { uint8_t out[32U] = {0U}; Eurydice_slice_copy(Eurydice_array_to_slice((size_t)32U, out, uint8_t), randomness, uint8_t); memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } /** This function found in impl {(libcrux_ml_kem::hash_functions::Hash for libcrux_ml_kem::hash_functions::portable::PortableHash)} */ /** A monomorphic instance of libcrux_ml_kem.hash_functions.portable.H_f1 with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_hash_functions_portable_H_f1_1a( Eurydice_slice input, uint8_t ret[32U]) { libcrux_ml_kem_hash_functions_portable_H(input, ret); } /** A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_MlKem with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - PUBLIC_KEY_SIZE= 1184 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - VECTOR_U_BLOCK_LEN= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 */ static inline tuple_3c libcrux_ml_kem_ind_cca_encapsulate_cd( libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, uint8_t randomness[32U]) { uint8_t randomness0[32U]; libcrux_ml_kem_variant_entropy_preprocess_d8_63( Eurydice_array_to_slice((size_t)32U, randomness, uint8_t), randomness0); uint8_t to_hash[64U]; libcrux_ml_kem_utils_into_padded_array_ea( Eurydice_array_to_slice((size_t)32U, randomness0, uint8_t), to_hash); Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( (size_t)64U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, size_t); uint8_t ret[32U]; libcrux_ml_kem_hash_functions_portable_H_f1_1a( Eurydice_array_to_slice((size_t)1184U, libcrux_ml_kem_types_as_slice_cb_50(public_key), uint8_t), ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)32U, ret, uint8_t), uint8_t); uint8_t hashed[64U]; libcrux_ml_kem_hash_functions_portable_G_f1_e4( Eurydice_array_to_slice((size_t)64U, to_hash, uint8_t), hashed); Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice shared_secret = uu____1.fst; Eurydice_slice pseudorandomness = uu____1.snd; Eurydice_slice uu____2 = Eurydice_array_to_slice( (size_t)1184U, libcrux_ml_kem_types_as_slice_cb_50(public_key), uint8_t); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[32U]; memcpy(copy_of_randomness, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[1088U]; libcrux_ml_kem_ind_cpa_encrypt_60(uu____2, copy_of_randomness, pseudorandomness, ciphertext); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_ciphertext[1088U]; memcpy(copy_of_ciphertext, ciphertext, (size_t)1088U * sizeof(uint8_t)); libcrux_ml_kem_mlkem768_MlKem768Ciphertext ciphertext0 = libcrux_ml_kem_types_from_01_9f(copy_of_ciphertext); uint8_t shared_secret_array[32U]; libcrux_ml_kem_variant_kdf_d8_41(shared_secret, &ciphertext0, shared_secret_array); libcrux_ml_kem_mlkem768_MlKem768Ciphertext uu____5 = ciphertext0; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_shared_secret_array[32U]; memcpy(copy_of_shared_secret_array, shared_secret_array, (size_t)32U * sizeof(uint8_t)); tuple_3c lit; lit.fst = uu____5; memcpy(lit.snd, copy_of_shared_secret_array, (size_t)32U * sizeof(uint8_t)); return lit; } /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.encapsulate with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - PUBLIC_KEY_SIZE= 1184 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - VECTOR_U_BLOCK_LEN= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 */ static inline tuple_3c libcrux_ml_kem_ind_cca_instantiations_portable_encapsulate_c6( libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, uint8_t randomness[32U]) { libcrux_ml_kem_types_MlKemPublicKey_15 *uu____0 = public_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[32U]; memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_encapsulate_cd(uu____0, copy_of_randomness); } /** Encapsulate ML-KEM 768 Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] bytes of `randomness`. */ static inline tuple_3c libcrux_ml_kem_mlkem768_portable_encapsulate( libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, uint8_t randomness[32U]) { libcrux_ml_kem_types_MlKemPublicKey_15 *uu____0 = public_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[32U]; memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_instantiations_portable_encapsulate_c6( uu____0, copy_of_randomness); } /** This function found in impl {(libcrux_ml_kem::variant::Variant for libcrux_ml_kem::variant::MlKem)#1} */ /** A monomorphic instance of libcrux_ml_kem.variant.cpa_keygen_seed_d8 with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_variant_cpa_keygen_seed_d8_0e( Eurydice_slice key_generation_seed, uint8_t ret[64U]) { uint8_t seed[33U] = {0U}; Eurydice_slice_copy( Eurydice_array_to_subslice2( seed, (size_t)0U, LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t), key_generation_seed, uint8_t); seed[LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE] = (uint8_t)(size_t)3U; uint8_t ret0[64U]; libcrux_ml_kem_hash_functions_portable_G_f1_e4( Eurydice_array_to_slice((size_t)33U, seed, uint8_t), ret0); memcpy(ret, ret0, (size_t)64U * sizeof(uint8_t)); } /** A monomorphic instance of libcrux_ml_kem.matrix.compute_As_plus_e.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_matrix_compute_As_plus_e_closure_87(size_t _i) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** A monomorphic instance of libcrux_ml_kem.vector.traits.to_standard_domain with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_traits_to_standard_domain_59( libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return libcrux_ml_kem_vector_portable_montgomery_multiply_by_constant_0d( v, LIBCRUX_ML_KEM_VECTOR_TRAITS_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS); } /** This function found in impl {libcrux_ml_kem::polynomial::PolynomialRingElement[TraitClause@0]} */ /** A monomorphic instance of libcrux_ml_kem.polynomial.add_standard_error_reduce_89 with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_polynomial_add_standard_error_reduce_89_03( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *self, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t j = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient_normal_form = libcrux_ml_kem_vector_traits_to_standard_domain_59( self->coefficients[j]); libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = libcrux_ml_kem_vector_portable_barrett_reduce_0d( libcrux_ml_kem_vector_portable_add_0d(coefficient_normal_form, &error->coefficients[j])); self->coefficients[j] = uu____0; } } /** Compute  ◦ ŝ + ê */ /** A monomorphic instance of libcrux_ml_kem.matrix.compute_As_plus_e with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_matrix_compute_As_plus_e_60( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 (*matrix_A)[3U], libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *s_as_ntt, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *error_as_ntt, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 result[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { result[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } for (size_t i0 = (size_t)0U; i0 < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)3U, matrix_A, libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]), libcrux_ml_kem_polynomial_PolynomialRingElement_f0[3U]); i0++) { size_t i1 = i0; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *row = matrix_A[i1]; for (size_t i = (size_t)0U; i < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)3U, row, libcrux_ml_kem_polynomial_PolynomialRingElement_f0), libcrux_ml_kem_polynomial_PolynomialRingElement_f0); i++) { size_t j = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *matrix_element = &row[j]; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 product = libcrux_ml_kem_polynomial_ntt_multiply_89_2a(matrix_element, &s_as_ntt[j]); libcrux_ml_kem_polynomial_add_to_ring_element_89_84(&result[i1], &product); } libcrux_ml_kem_polynomial_add_standard_error_reduce_89_03( &result[i1], &error_as_ntt[i1]); } memcpy( ret, result, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); } /** A monomorphic instance of libcrux_ml_kem.serialize.serialize_uncompressed_ring_element with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_serialize_uncompressed_ring_element_5b( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *re, uint8_t ret[384U]) { uint8_t serialized[384U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = libcrux_ml_kem_vector_traits_to_unsigned_representative_db( re->coefficients[i0]); uint8_t bytes[24U]; libcrux_ml_kem_vector_portable_serialize_12_0d(coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice2( serialized, (size_t)24U * i0, (size_t)24U * i0 + (size_t)24U, uint8_t); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)24U, bytes, uint8_t), uint8_t); } memcpy(ret, serialized, (size_t)384U * sizeof(uint8_t)); } /** Call [`serialize_uncompressed_ring_element`] for each ring element. */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_secret_key with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - OUT_LEN= 1152 */ static KRML_MUSTINLINE void libcrux_ml_kem_ind_cpa_serialize_secret_key_b5( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *key, uint8_t ret[1152U]) { uint8_t out[1152U] = {0U}; for (size_t i = (size_t)0U; i < Eurydice_slice_len( Eurydice_array_to_slice( (size_t)3U, key, libcrux_ml_kem_polynomial_PolynomialRingElement_f0), libcrux_ml_kem_polynomial_PolynomialRingElement_f0); i++) { size_t i0 = i; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 re = key[i0]; Eurydice_slice uu____0 = Eurydice_array_to_subslice2( out, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, (i0 + (size_t)1U) * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, uint8_t); uint8_t ret0[384U]; libcrux_ml_kem_serialize_serialize_uncompressed_ring_element_5b(&re, ret0); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)384U, ret0, uint8_t), uint8_t); } memcpy(ret, out, (size_t)1152U * sizeof(uint8_t)); } /** Concatenate `t` and `ρ` into the public key. */ /** A monomorphic instance of libcrux_ml_kem.ind_cpa.serialize_public_key with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - RANKED_BYTES_PER_RING_ELEMENT= 1152 - PUBLIC_KEY_SIZE= 1184 */ static KRML_MUSTINLINE void libcrux_ml_kem_ind_cpa_serialize_public_key_79( libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *t_as_ntt, Eurydice_slice seed_for_a, uint8_t ret[1184U]) { uint8_t public_key_serialized[1184U] = {0U}; Eurydice_slice uu____0 = Eurydice_array_to_subslice2( public_key_serialized, (size_t)0U, (size_t)1152U, uint8_t); uint8_t ret0[1152U]; libcrux_ml_kem_ind_cpa_serialize_secret_key_b5(t_as_ntt, ret0); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)1152U, ret0, uint8_t), uint8_t); Eurydice_slice_copy( Eurydice_array_to_subslice_from((size_t)1184U, public_key_serialized, (size_t)1152U, uint8_t, size_t), seed_for_a, uint8_t); memcpy(ret, public_key_serialized, (size_t)1184U * sizeof(uint8_t)); } /** A monomorphic instance of libcrux_ml_kem.ind_cpa.generate_keypair with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_MlKem with const generics - K= 3 - PRIVATE_KEY_SIZE= 1152 - PUBLIC_KEY_SIZE= 1184 - RANKED_BYTES_PER_RING_ELEMENT= 1152 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 */ static inline libcrux_ml_kem_utils_extraction_helper_Keypair768 libcrux_ml_kem_ind_cpa_generate_keypair_fc(Eurydice_slice key_generation_seed) { uint8_t hashed[64U]; libcrux_ml_kem_variant_cpa_keygen_seed_d8_0e(key_generation_seed, hashed); Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), (size_t)32U, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice seed_for_A0 = uu____0.fst; Eurydice_slice seed_for_secret_and_error = uu____0.snd; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[3U][3U]; uint8_t ret[34U]; libcrux_ml_kem_utils_into_padded_array_ea1(seed_for_A0, ret); libcrux_ml_kem_matrix_sample_matrix_A_38(ret, true, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array_ea2(seed_for_secret_and_error, prf_input); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input0[33U]; memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); tuple_b0 uu____2 = libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_fc( copy_of_prf_input0, 0U); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; memcpy( secret_as_ntt, uu____2.fst, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); uint8_t domain_separator = uu____2.snd; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input[33U]; memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_as_ntt[3U]; memcpy( error_as_ntt, libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_fc(copy_of_prf_input, domain_separator) .fst, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[3U]; libcrux_ml_kem_matrix_compute_As_plus_e_60(A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); uint8_t seed_for_A[32U]; Result_00 dst; Eurydice_slice_to_array2(&dst, seed_for_A0, Eurydice_slice, uint8_t[32U]); unwrap_41_83(dst, seed_for_A); uint8_t public_key_serialized[1184U]; libcrux_ml_kem_ind_cpa_serialize_public_key_79( t_as_ntt, Eurydice_array_to_slice((size_t)32U, seed_for_A, uint8_t), public_key_serialized); uint8_t secret_key_serialized[1152U]; libcrux_ml_kem_ind_cpa_serialize_secret_key_b5(secret_as_ntt, secret_key_serialized); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_secret_key_serialized[1152U]; memcpy(copy_of_secret_key_serialized, secret_key_serialized, (size_t)1152U * sizeof(uint8_t)); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_public_key_serialized[1184U]; memcpy(copy_of_public_key_serialized, public_key_serialized, (size_t)1184U * sizeof(uint8_t)); libcrux_ml_kem_utils_extraction_helper_Keypair768 lit; memcpy(lit.fst, copy_of_secret_key_serialized, (size_t)1152U * sizeof(uint8_t)); memcpy(lit.snd, copy_of_public_key_serialized, (size_t)1184U * sizeof(uint8_t)); return lit; } /** Serialize the secret key. */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.serialize_kem_secret_key with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - SERIALIZED_KEY_LEN= 2400 */ static KRML_MUSTINLINE void libcrux_ml_kem_ind_cca_serialize_kem_secret_key_48( Eurydice_slice private_key, Eurydice_slice public_key, Eurydice_slice implicit_rejection_value, uint8_t ret[2400U]) { uint8_t out[2400U] = {0U}; size_t pointer = (size_t)0U; uint8_t *uu____0 = out; size_t uu____1 = pointer; size_t uu____2 = pointer; Eurydice_slice_copy( Eurydice_array_to_subslice2( uu____0, uu____1, uu____2 + Eurydice_slice_len(private_key, uint8_t), uint8_t), private_key, uint8_t); pointer = pointer + Eurydice_slice_len(private_key, uint8_t); uint8_t *uu____3 = out; size_t uu____4 = pointer; size_t uu____5 = pointer; Eurydice_slice_copy( Eurydice_array_to_subslice2( uu____3, uu____4, uu____5 + Eurydice_slice_len(public_key, uint8_t), uint8_t), public_key, uint8_t); pointer = pointer + Eurydice_slice_len(public_key, uint8_t); Eurydice_slice uu____6 = Eurydice_array_to_subslice2( out, pointer, pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t); uint8_t ret0[32U]; libcrux_ml_kem_hash_functions_portable_H_f1_1a(public_key, ret0); Eurydice_slice_copy( uu____6, Eurydice_array_to_slice((size_t)32U, ret0, uint8_t), uint8_t); pointer = pointer + LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE; uint8_t *uu____7 = out; size_t uu____8 = pointer; size_t uu____9 = pointer; Eurydice_slice_copy( Eurydice_array_to_subslice2( uu____7, uu____8, uu____9 + Eurydice_slice_len(implicit_rejection_value, uint8_t), uint8_t), implicit_rejection_value, uint8_t); memcpy(ret, out, (size_t)2400U * sizeof(uint8_t)); } /** Packed API Generate a key pair. Depending on the `Vector` and `Hasher` used, this requires different hardware features */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_MlKem with const generics - K= 3 - CPA_PRIVATE_KEY_SIZE= 1152 - PRIVATE_KEY_SIZE= 2400 - PUBLIC_KEY_SIZE= 1184 - BYTES_PER_RING_ELEMENT= 1152 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 */ static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_ind_cca_generate_keypair_8c(uint8_t randomness[64U]) { Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice2( randomness, (size_t)0U, LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t); Eurydice_slice implicit_rejection_value = Eurydice_array_to_subslice_from( (size_t)64U, randomness, LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, size_t); libcrux_ml_kem_utils_extraction_helper_Keypair768 uu____0 = libcrux_ml_kem_ind_cpa_generate_keypair_fc(ind_cpa_keypair_randomness); uint8_t ind_cpa_private_key[1152U]; memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); uint8_t public_key[1184U]; memcpy(public_key, uu____0.snd, (size_t)1184U * sizeof(uint8_t)); uint8_t secret_key_serialized[2400U]; libcrux_ml_kem_ind_cca_serialize_kem_secret_key_48( Eurydice_array_to_slice((size_t)1152U, ind_cpa_private_key, uint8_t), Eurydice_array_to_slice((size_t)1184U, public_key, uint8_t), implicit_rejection_value, secret_key_serialized); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_secret_key_serialized[2400U]; memcpy(copy_of_secret_key_serialized, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey_55 private_key = libcrux_ml_kem_types_from_05_f2(copy_of_secret_key_serialized); libcrux_ml_kem_types_MlKemPrivateKey_55 uu____2 = private_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_public_key[1184U]; memcpy(copy_of_public_key, public_key, (size_t)1184U * sizeof(uint8_t)); return libcrux_ml_kem_types_from_17_35( uu____2, libcrux_ml_kem_types_from_b6_da(copy_of_public_key)); } /** Portable generate key pair. */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.generate_keypair with const generics - K= 3 - CPA_PRIVATE_KEY_SIZE= 1152 - PRIVATE_KEY_SIZE= 2400 - PUBLIC_KEY_SIZE= 1184 - BYTES_PER_RING_ELEMENT= 1152 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 */ static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_ind_cca_instantiations_portable_generate_keypair_d5( uint8_t randomness[64U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[64U]; memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_generate_keypair_8c(copy_of_randomness); } /** Generate ML-KEM 768 Key Pair */ static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_mlkem768_portable_generate_key_pair(uint8_t randomness[64U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[64U]; memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_instantiations_portable_generate_keypair_d5( copy_of_randomness); } /** This function found in impl {(libcrux_ml_kem::variant::Variant for libcrux_ml_kem::variant::Kyber)} */ /** A monomorphic instance of libcrux_ml_kem.variant.kdf_33 with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 */ static KRML_MUSTINLINE void libcrux_ml_kem_variant_kdf_33_f0( Eurydice_slice shared_secret, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { uint8_t kdf_input[64U]; libcrux_ml_kem_utils_into_padded_array_ea(shared_secret, kdf_input); Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( (size_t)64U, kdf_input, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, size_t); uint8_t ret0[32U]; libcrux_ml_kem_hash_functions_portable_H_f1_1a( Eurydice_array_to_slice((size_t)1088U, libcrux_ml_kem_types_as_slice_d4_1d(ciphertext), uint8_t), ret0); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)32U, ret0, uint8_t), uint8_t); uint8_t ret1[32U]; libcrux_ml_kem_hash_functions_portable_PRF_f1_ee( Eurydice_array_to_slice((size_t)64U, kdf_input, uint8_t), ret1); memcpy(ret, ret1, (size_t)32U * sizeof(uint8_t)); } /** A monomorphic instance of libcrux_ml_kem.ind_cca.decapsulate with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_Kyber with const generics - K= 3 - SECRET_KEY_SIZE= 2400 - CPA_SECRET_KEY_SIZE= 1152 - PUBLIC_KEY_SIZE= 1184 - CIPHERTEXT_SIZE= 1088 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - C1_BLOCK_SIZE= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 - IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1120 */ static inline void libcrux_ml_kem_ind_cca_decapsulate_700( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)2400U, private_key->value, uint8_t), (size_t)1152U, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice ind_cpa_secret_key = uu____0.fst; Eurydice_slice secret_key0 = uu____0.snd; Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( secret_key0, (size_t)1184U, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice ind_cpa_public_key = uu____1.fst; Eurydice_slice secret_key = uu____1.snd; Eurydice_slice_uint8_t_x2 uu____2 = Eurydice_slice_split_at( secret_key, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; Eurydice_slice implicit_rejection_value = uu____2.snd; uint8_t decrypted[32U]; libcrux_ml_kem_ind_cpa_decrypt_43(ind_cpa_secret_key, ciphertext->value, decrypted); uint8_t to_hash0[64U]; libcrux_ml_kem_utils_into_padded_array_ea( Eurydice_array_to_slice((size_t)32U, decrypted, uint8_t), to_hash0); Eurydice_slice_copy( Eurydice_array_to_subslice_from( (size_t)64U, to_hash0, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, size_t), ind_cpa_public_key_hash, uint8_t); uint8_t hashed[64U]; libcrux_ml_kem_hash_functions_portable_G_f1_e4( Eurydice_array_to_slice((size_t)64U, to_hash0, uint8_t), hashed); Eurydice_slice_uint8_t_x2 uu____3 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice shared_secret0 = uu____3.fst; Eurydice_slice pseudorandomness = uu____3.snd; uint8_t to_hash[1120U]; libcrux_ml_kem_utils_into_padded_array_ea0(implicit_rejection_value, to_hash); Eurydice_slice uu____4 = Eurydice_array_to_subslice_from( (size_t)1120U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, size_t); Eurydice_slice_copy(uu____4, libcrux_ml_kem_types_as_ref_00_24(ciphertext), uint8_t); uint8_t implicit_rejection_shared_secret0[32U]; libcrux_ml_kem_hash_functions_portable_PRF_f1_ee( Eurydice_array_to_slice((size_t)1120U, to_hash, uint8_t), implicit_rejection_shared_secret0); Eurydice_slice uu____5 = ind_cpa_public_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_decrypted[32U]; memcpy(copy_of_decrypted, decrypted, (size_t)32U * sizeof(uint8_t)); uint8_t expected_ciphertext[1088U]; libcrux_ml_kem_ind_cpa_encrypt_60(uu____5, copy_of_decrypted, pseudorandomness, expected_ciphertext); uint8_t implicit_rejection_shared_secret[32U]; libcrux_ml_kem_variant_kdf_33_f0( Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret0, uint8_t), ciphertext, implicit_rejection_shared_secret); uint8_t shared_secret[32U]; libcrux_ml_kem_variant_kdf_33_f0(shared_secret0, ciphertext, shared_secret); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_compare_ciphertexts_select_shared_secret_in_constant_time( libcrux_ml_kem_types_as_ref_00_24(ciphertext), Eurydice_array_to_slice((size_t)1088U, expected_ciphertext, uint8_t), Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t), ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } /** Portable decapsulate */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.kyber_decapsulate with const generics - K= 3 - SECRET_KEY_SIZE= 2400 - CPA_SECRET_KEY_SIZE= 1152 - PUBLIC_KEY_SIZE= 1184 - CIPHERTEXT_SIZE= 1088 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - C1_BLOCK_SIZE= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 - IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1120 */ static inline void libcrux_ml_kem_ind_cca_instantiations_portable_kyber_decapsulate_fc( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { libcrux_ml_kem_ind_cca_decapsulate_700(private_key, ciphertext, ret); } /** Decapsulate Kyber 768 Generates an [`MlKemSharedSecret`]. The input is a reference to an [`MlKem768PrivateKey`] and an [`MlKem768Ciphertext`]. */ static inline void libcrux_ml_kem_mlkem768_portable_kyber_decapsulate( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { libcrux_ml_kem_ind_cca_instantiations_portable_kyber_decapsulate_fc( private_key, ciphertext, ret); } /** This function found in impl {(libcrux_ml_kem::variant::Variant for libcrux_ml_kem::variant::Kyber)} */ /** A monomorphic instance of libcrux_ml_kem.variant.entropy_preprocess_33 with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_variant_entropy_preprocess_33_8a( Eurydice_slice randomness, uint8_t ret[32U]) { libcrux_ml_kem_hash_functions_portable_H_f1_1a(randomness, ret); } /** A monomorphic instance of libcrux_ml_kem.ind_cca.encapsulate with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_Kyber with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - PUBLIC_KEY_SIZE= 1184 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - VECTOR_U_BLOCK_LEN= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 */ static inline tuple_3c libcrux_ml_kem_ind_cca_encapsulate_cd0( libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, uint8_t randomness[32U]) { uint8_t randomness0[32U]; libcrux_ml_kem_variant_entropy_preprocess_33_8a( Eurydice_array_to_slice((size_t)32U, randomness, uint8_t), randomness0); uint8_t to_hash[64U]; libcrux_ml_kem_utils_into_padded_array_ea( Eurydice_array_to_slice((size_t)32U, randomness0, uint8_t), to_hash); Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( (size_t)64U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, size_t); uint8_t ret[32U]; libcrux_ml_kem_hash_functions_portable_H_f1_1a( Eurydice_array_to_slice((size_t)1184U, libcrux_ml_kem_types_as_slice_cb_50(public_key), uint8_t), ret); Eurydice_slice_copy( uu____0, Eurydice_array_to_slice((size_t)32U, ret, uint8_t), uint8_t); uint8_t hashed[64U]; libcrux_ml_kem_hash_functions_portable_G_f1_e4( Eurydice_array_to_slice((size_t)64U, to_hash, uint8_t), hashed); Eurydice_slice_uint8_t_x2 uu____1 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice shared_secret = uu____1.fst; Eurydice_slice pseudorandomness = uu____1.snd; Eurydice_slice uu____2 = Eurydice_array_to_slice( (size_t)1184U, libcrux_ml_kem_types_as_slice_cb_50(public_key), uint8_t); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[32U]; memcpy(copy_of_randomness, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[1088U]; libcrux_ml_kem_ind_cpa_encrypt_60(uu____2, copy_of_randomness, pseudorandomness, ciphertext); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_ciphertext[1088U]; memcpy(copy_of_ciphertext, ciphertext, (size_t)1088U * sizeof(uint8_t)); libcrux_ml_kem_mlkem768_MlKem768Ciphertext ciphertext0 = libcrux_ml_kem_types_from_01_9f(copy_of_ciphertext); uint8_t shared_secret_array[32U]; libcrux_ml_kem_variant_kdf_33_f0(shared_secret, &ciphertext0, shared_secret_array); libcrux_ml_kem_mlkem768_MlKem768Ciphertext uu____5 = ciphertext0; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_shared_secret_array[32U]; memcpy(copy_of_shared_secret_array, shared_secret_array, (size_t)32U * sizeof(uint8_t)); tuple_3c lit; lit.fst = uu____5; memcpy(lit.snd, copy_of_shared_secret_array, (size_t)32U * sizeof(uint8_t)); return lit; } /** Portable encapsulate */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.kyber_encapsulate with const generics - K= 3 - CIPHERTEXT_SIZE= 1088 - PUBLIC_KEY_SIZE= 1184 - T_AS_NTT_ENCODED_SIZE= 1152 - C1_SIZE= 960 - C2_SIZE= 128 - VECTOR_U_COMPRESSION_FACTOR= 10 - VECTOR_V_COMPRESSION_FACTOR= 4 - VECTOR_U_BLOCK_LEN= 320 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 - ETA2= 2 - ETA2_RANDOMNESS_SIZE= 128 */ static inline tuple_3c libcrux_ml_kem_ind_cca_instantiations_portable_kyber_encapsulate_7a( libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, uint8_t randomness[32U]) { libcrux_ml_kem_types_MlKemPublicKey_15 *uu____0 = public_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[32U]; memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_encapsulate_cd0(uu____0, copy_of_randomness); } /** Encapsulate Kyber 768 Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] bytes of `randomness`. */ static inline tuple_3c libcrux_ml_kem_mlkem768_portable_kyber_encapsulate( libcrux_ml_kem_types_MlKemPublicKey_15 *public_key, uint8_t randomness[32U]) { libcrux_ml_kem_types_MlKemPublicKey_15 *uu____0 = public_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[32U]; memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_instantiations_portable_kyber_encapsulate_7a( uu____0, copy_of_randomness); } /** This function found in impl {(libcrux_ml_kem::variant::Variant for libcrux_ml_kem::variant::Kyber)} */ /** A monomorphic instance of libcrux_ml_kem.variant.cpa_keygen_seed_33 with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_variant_cpa_keygen_seed_33_b6( Eurydice_slice key_generation_seed, uint8_t ret[64U]) { libcrux_ml_kem_hash_functions_portable_G_f1_e4(key_generation_seed, ret); } /** A monomorphic instance of libcrux_ml_kem.ind_cpa.generate_keypair with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_Kyber with const generics - K= 3 - PRIVATE_KEY_SIZE= 1152 - PUBLIC_KEY_SIZE= 1184 - RANKED_BYTES_PER_RING_ELEMENT= 1152 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 */ static inline libcrux_ml_kem_utils_extraction_helper_Keypair768 libcrux_ml_kem_ind_cpa_generate_keypair_fc0( Eurydice_slice key_generation_seed) { uint8_t hashed[64U]; libcrux_ml_kem_variant_cpa_keygen_seed_33_b6(key_generation_seed, hashed); Eurydice_slice_uint8_t_x2 uu____0 = Eurydice_slice_split_at( Eurydice_array_to_slice((size_t)64U, hashed, uint8_t), (size_t)32U, uint8_t, Eurydice_slice_uint8_t_x2); Eurydice_slice seed_for_A0 = uu____0.fst; Eurydice_slice seed_for_secret_and_error = uu____0.snd; libcrux_ml_kem_polynomial_PolynomialRingElement_f0 A_transpose[3U][3U]; uint8_t ret[34U]; libcrux_ml_kem_utils_into_padded_array_ea1(seed_for_A0, ret); libcrux_ml_kem_matrix_sample_matrix_A_38(ret, true, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array_ea2(seed_for_secret_and_error, prf_input); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input0[33U]; memcpy(copy_of_prf_input0, prf_input, (size_t)33U * sizeof(uint8_t)); tuple_b0 uu____2 = libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_fc( copy_of_prf_input0, 0U); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 secret_as_ntt[3U]; memcpy( secret_as_ntt, uu____2.fst, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); uint8_t domain_separator = uu____2.snd; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_prf_input[33U]; memcpy(copy_of_prf_input, prf_input, (size_t)33U * sizeof(uint8_t)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 error_as_ntt[3U]; memcpy( error_as_ntt, libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_fc(copy_of_prf_input, domain_separator) .fst, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 t_as_ntt[3U]; libcrux_ml_kem_matrix_compute_As_plus_e_60(A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); uint8_t seed_for_A[32U]; Result_00 dst; Eurydice_slice_to_array2(&dst, seed_for_A0, Eurydice_slice, uint8_t[32U]); unwrap_41_83(dst, seed_for_A); uint8_t public_key_serialized[1184U]; libcrux_ml_kem_ind_cpa_serialize_public_key_79( t_as_ntt, Eurydice_array_to_slice((size_t)32U, seed_for_A, uint8_t), public_key_serialized); uint8_t secret_key_serialized[1152U]; libcrux_ml_kem_ind_cpa_serialize_secret_key_b5(secret_as_ntt, secret_key_serialized); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_secret_key_serialized[1152U]; memcpy(copy_of_secret_key_serialized, secret_key_serialized, (size_t)1152U * sizeof(uint8_t)); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_public_key_serialized[1184U]; memcpy(copy_of_public_key_serialized, public_key_serialized, (size_t)1184U * sizeof(uint8_t)); libcrux_ml_kem_utils_extraction_helper_Keypair768 lit; memcpy(lit.fst, copy_of_secret_key_serialized, (size_t)1152U * sizeof(uint8_t)); memcpy(lit.snd, copy_of_public_key_serialized, (size_t)1184U * sizeof(uint8_t)); return lit; } /** Packed API Generate a key pair. Depending on the `Vector` and `Hasher` used, this requires different hardware features */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.generate_keypair with types libcrux_ml_kem_vector_portable_vector_type_PortableVector, libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]], libcrux_ml_kem_variant_Kyber with const generics - K= 3 - CPA_PRIVATE_KEY_SIZE= 1152 - PRIVATE_KEY_SIZE= 2400 - PUBLIC_KEY_SIZE= 1184 - BYTES_PER_RING_ELEMENT= 1152 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 */ static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_ind_cca_generate_keypair_8c0(uint8_t randomness[64U]) { Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice2( randomness, (size_t)0U, LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t); Eurydice_slice implicit_rejection_value = Eurydice_array_to_subslice_from( (size_t)64U, randomness, LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, size_t); libcrux_ml_kem_utils_extraction_helper_Keypair768 uu____0 = libcrux_ml_kem_ind_cpa_generate_keypair_fc0(ind_cpa_keypair_randomness); uint8_t ind_cpa_private_key[1152U]; memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); uint8_t public_key[1184U]; memcpy(public_key, uu____0.snd, (size_t)1184U * sizeof(uint8_t)); uint8_t secret_key_serialized[2400U]; libcrux_ml_kem_ind_cca_serialize_kem_secret_key_48( Eurydice_array_to_slice((size_t)1152U, ind_cpa_private_key, uint8_t), Eurydice_array_to_slice((size_t)1184U, public_key, uint8_t), implicit_rejection_value, secret_key_serialized); /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_secret_key_serialized[2400U]; memcpy(copy_of_secret_key_serialized, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey_55 private_key = libcrux_ml_kem_types_from_05_f2(copy_of_secret_key_serialized); libcrux_ml_kem_types_MlKemPrivateKey_55 uu____2 = private_key; /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_public_key[1184U]; memcpy(copy_of_public_key, public_key, (size_t)1184U * sizeof(uint8_t)); return libcrux_ml_kem_types_from_17_35( uu____2, libcrux_ml_kem_types_from_b6_da(copy_of_public_key)); } /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.kyber_generate_keypair with const generics - K= 3 - CPA_PRIVATE_KEY_SIZE= 1152 - PRIVATE_KEY_SIZE= 2400 - PUBLIC_KEY_SIZE= 1184 - BYTES_PER_RING_ELEMENT= 1152 - ETA1= 2 - ETA1_RANDOMNESS_SIZE= 128 */ static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_ind_cca_instantiations_portable_kyber_generate_keypair_9b( uint8_t randomness[64U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[64U]; memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_generate_keypair_8c0(copy_of_randomness); } /** Generate Kyber 768 Key Pair */ static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair libcrux_ml_kem_mlkem768_portable_kyber_generate_key_pair( uint8_t randomness[64U]) { /* Passing arrays by value in Rust generates a copy in C */ uint8_t copy_of_randomness[64U]; memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t)); return libcrux_ml_kem_ind_cca_instantiations_portable_kyber_generate_keypair_9b( copy_of_randomness); } /** Validate an ML-KEM private key. This implements the Hash check in 7.3 3. Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE` and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types. */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.validate_private_key with types libcrux_ml_kem_hash_functions_portable_PortableHash[[$3size_t]] with const generics - K= 3 - SECRET_KEY_SIZE= 2400 - CIPHERTEXT_SIZE= 1088 */ static KRML_MUSTINLINE bool libcrux_ml_kem_ind_cca_validate_private_key_e7( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *_ciphertext) { uint8_t t[32U]; libcrux_ml_kem_hash_functions_portable_H_f1_1a( Eurydice_array_to_subslice2(private_key->value, (size_t)384U * (size_t)3U, (size_t)768U * (size_t)3U + (size_t)32U, uint8_t), t); Eurydice_slice expected = Eurydice_array_to_subslice2( private_key->value, (size_t)768U * (size_t)3U + (size_t)32U, (size_t)768U * (size_t)3U + (size_t)64U, uint8_t); return core_array_equality___core__cmp__PartialEq__0___Slice_U____for__Array_T__N___3__eq( (size_t)32U, t, &expected, uint8_t, uint8_t, bool); } /** Portable private key validation */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.validate_private_key with const generics - K= 3 - SECRET_KEY_SIZE= 2400 - CIPHERTEXT_SIZE= 1088 */ static KRML_MUSTINLINE bool libcrux_ml_kem_ind_cca_instantiations_portable_validate_private_key_9c( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext) { return libcrux_ml_kem_ind_cca_validate_private_key_e7(private_key, ciphertext); } /** Validate a private key. Returns `true` if valid, and `false` otherwise. */ static inline bool libcrux_ml_kem_mlkem768_portable_validate_private_key( libcrux_ml_kem_types_MlKemPrivateKey_55 *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext) { return libcrux_ml_kem_ind_cca_instantiations_portable_validate_private_key_9c( private_key, ciphertext); } /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_ring_elements_reduced.closure with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - PUBLIC_KEY_SIZE= 1184 - K= 3 */ static inline libcrux_ml_kem_polynomial_PolynomialRingElement_f0 libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_closure_cd0( size_t _i) { return libcrux_ml_kem_polynomial_ZERO_89_ea(); } /** This function deserializes ring elements and reduces the result by the field modulus. This function MUST NOT be used on secret inputs. */ /** A monomorphic instance of libcrux_ml_kem.serialize.deserialize_ring_elements_reduced with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - PUBLIC_KEY_SIZE= 1184 - K= 3 */ static KRML_MUSTINLINE void libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_330( Eurydice_slice public_key, libcrux_ml_kem_polynomial_PolynomialRingElement_f0 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[3U]; for (size_t i = (size_t)0U; i < (size_t)3U; i++) { deserialized_pk[i] = libcrux_ml_kem_polynomial_ZERO_89_ea(); } for (size_t i = (size_t)0U; i < Eurydice_slice_len(public_key, uint8_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; i++) { size_t i0 = i; Eurydice_slice ring_element = Eurydice_slice_subslice2( public_key, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT, uint8_t); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 uu____0 = libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element_4c( ring_element); deserialized_pk[i0] = uu____0; } memcpy( ret, deserialized_pk, (size_t)3U * sizeof(libcrux_ml_kem_polynomial_PolynomialRingElement_f0)); } /** Validate an ML-KEM public key. This implements the Modulus check in 7.2 2. Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the `public_key` type. */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.validate_public_key with types libcrux_ml_kem_vector_portable_vector_type_PortableVector with const generics - K= 3 - RANKED_BYTES_PER_RING_ELEMENT= 1152 - PUBLIC_KEY_SIZE= 1184 */ static KRML_MUSTINLINE bool libcrux_ml_kem_ind_cca_validate_public_key_19( uint8_t *public_key) { libcrux_ml_kem_polynomial_PolynomialRingElement_f0 deserialized_pk[3U]; libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_330( Eurydice_array_to_subslice_to((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t), deserialized_pk); libcrux_ml_kem_polynomial_PolynomialRingElement_f0 *uu____0 = deserialized_pk; uint8_t public_key_serialized[1184U]; libcrux_ml_kem_ind_cpa_serialize_public_key_79( uu____0, Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t), public_key_serialized); return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)1184U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } /** Portable public key validation */ /** A monomorphic instance of libcrux_ml_kem.ind_cca.instantiations.portable.validate_public_key with const generics - K= 3 - RANKED_BYTES_PER_RING_ELEMENT= 1152 - PUBLIC_KEY_SIZE= 1184 */ static KRML_MUSTINLINE bool libcrux_ml_kem_ind_cca_instantiations_portable_validate_public_key_4b( uint8_t *public_key) { return libcrux_ml_kem_ind_cca_validate_public_key_19(public_key); } /** Validate a public key. Returns `true` if valid, and `false` otherwise. */ static inline bool libcrux_ml_kem_mlkem768_portable_validate_public_key( libcrux_ml_kem_types_MlKemPublicKey_15 *public_key) { return libcrux_ml_kem_ind_cca_instantiations_portable_validate_public_key_4b( public_key->value); } /** This function found in impl {(core::clone::Clone for libcrux_ml_kem::vector::portable::vector_type::PortableVector)} */ static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector libcrux_ml_kem_vector_portable_vector_type_clone_3b( libcrux_ml_kem_vector_portable_vector_type_PortableVector *self) { return self[0U]; } typedef int16_t libcrux_ml_kem_vector_portable_vector_type_FieldElement; typedef int16_t libcrux_ml_kem_vector_portable_arithmetic_MontgomeryFieldElement; typedef int16_t libcrux_ml_kem_vector_portable_arithmetic_FieldElementTimesMontgomeryR; #if defined(__cplusplus) } #endif #define __libcrux_mlkem768_portable_H_DEFINED #endif /* rename some types to be a bit more ergonomic */ #define libcrux_mlkem768_keypair libcrux_ml_kem_mlkem768_MlKem768KeyPair_s #define libcrux_mlkem768_pk_valid_result Option_92_s #define libcrux_mlkem768_pk libcrux_ml_kem_types_MlKemPublicKey_15_s #define libcrux_mlkem768_sk libcrux_ml_kem_types_MlKemPrivateKey_55_s #define libcrux_mlkem768_ciphertext libcrux_ml_kem_mlkem768_MlKem768Ciphertext_s #define libcrux_mlkem768_enc_result tuple_3c_s /* defines for PRNG inputs */ #define LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN 64 #define LIBCRUX_ML_KEM_ENC_PRNG_LEN 32 openssh-10.0p1/PaxHeaders.10889/log.c100644 001750 001750 0000000003614775415623 0014101xustar0030 atime=1744182234.578929748 openssh-10.0p1/log.c010064400017500001750000000413111477541562300124640ustar00djmdjm/* $OpenBSD: log.c,v 1.64 2024/12/07 10:05:36 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) # include #endif #include "log.h" #include "match.h" static LogLevel log_level = SYSLOG_LEVEL_INFO; static int log_on_stderr = 1; static int log_stderr_fd = STDERR_FILENO; static int log_facility = LOG_AUTH; static const char *argv0; static log_handler_fn *log_handler; static void *log_handler_ctx; static char **log_verbose; static size_t nlog_verbose; extern char *__progname; #define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) /* textual representation of log-facilities/levels */ static struct { const char *name; SyslogFacility val; } log_facilities[] = { { "DAEMON", SYSLOG_FACILITY_DAEMON }, { "USER", SYSLOG_FACILITY_USER }, { "AUTH", SYSLOG_FACILITY_AUTH }, #ifdef LOG_AUTHPRIV { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, #endif { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, { NULL, SYSLOG_FACILITY_NOT_SET } }; static struct { const char *name; LogLevel val; } log_levels[] = { { "QUIET", SYSLOG_LEVEL_QUIET }, { "FATAL", SYSLOG_LEVEL_FATAL }, { "ERROR", SYSLOG_LEVEL_ERROR }, { "INFO", SYSLOG_LEVEL_INFO }, { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, { NULL, SYSLOG_LEVEL_NOT_SET } }; LogLevel log_level_get(void) { return log_level; } SyslogFacility log_facility_number(char *name) { int i; if (name != NULL) for (i = 0; log_facilities[i].name; i++) if (strcasecmp(log_facilities[i].name, name) == 0) return log_facilities[i].val; return SYSLOG_FACILITY_NOT_SET; } const char * log_facility_name(SyslogFacility facility) { u_int i; for (i = 0; log_facilities[i].name; i++) if (log_facilities[i].val == facility) return log_facilities[i].name; return NULL; } LogLevel log_level_number(char *name) { int i; if (name != NULL) for (i = 0; log_levels[i].name; i++) if (strcasecmp(log_levels[i].name, name) == 0) return log_levels[i].val; return SYSLOG_LEVEL_NOT_SET; } const char * log_level_name(LogLevel level) { u_int i; for (i = 0; log_levels[i].name != NULL; i++) if (log_levels[i].val == level) return log_levels[i].name; return NULL; } void log_verbose_add(const char *s) { char **tmp; /* Ignore failures here */ if ((tmp = recallocarray(log_verbose, nlog_verbose, nlog_verbose + 1, sizeof(*log_verbose))) != NULL) { log_verbose = tmp; if ((log_verbose[nlog_verbose] = strdup(s)) != NULL) nlog_verbose++; } } void log_verbose_reset(void) { size_t i; for (i = 0; i < nlog_verbose; i++) free(log_verbose[i]); free(log_verbose); log_verbose = NULL; nlog_verbose = 0; } /* * Initialize the log. */ void log_init(const char *av0, LogLevel level, SyslogFacility facility, int on_stderr) { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) struct syslog_data sdata = SYSLOG_DATA_INIT; #endif argv0 = av0; if (log_change_level(level) != 0) { fprintf(stderr, "Unrecognized internal syslog level code %d\n", (int) level); exit(1); } log_handler = NULL; log_handler_ctx = NULL; log_on_stderr = on_stderr; if (on_stderr) return; switch (facility) { case SYSLOG_FACILITY_DAEMON: log_facility = LOG_DAEMON; break; case SYSLOG_FACILITY_USER: log_facility = LOG_USER; break; case SYSLOG_FACILITY_AUTH: log_facility = LOG_AUTH; break; #ifdef LOG_AUTHPRIV case SYSLOG_FACILITY_AUTHPRIV: log_facility = LOG_AUTHPRIV; break; #endif case SYSLOG_FACILITY_LOCAL0: log_facility = LOG_LOCAL0; break; case SYSLOG_FACILITY_LOCAL1: log_facility = LOG_LOCAL1; break; case SYSLOG_FACILITY_LOCAL2: log_facility = LOG_LOCAL2; break; case SYSLOG_FACILITY_LOCAL3: log_facility = LOG_LOCAL3; break; case SYSLOG_FACILITY_LOCAL4: log_facility = LOG_LOCAL4; break; case SYSLOG_FACILITY_LOCAL5: log_facility = LOG_LOCAL5; break; case SYSLOG_FACILITY_LOCAL6: log_facility = LOG_LOCAL6; break; case SYSLOG_FACILITY_LOCAL7: log_facility = LOG_LOCAL7; break; default: fprintf(stderr, "Unrecognized internal syslog facility code %d\n", (int) facility); exit(1); } /* * If an external library (eg libwrap) attempts to use syslog * immediately after reexec, syslog may be pointing to the wrong * facility, so we force an open/close of syslog here. */ #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); closelog_r(&sdata); #else openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); closelog(); #endif } int log_change_level(LogLevel new_log_level) { /* no-op if log_init has not been called */ if (argv0 == NULL) return 0; switch (new_log_level) { case SYSLOG_LEVEL_QUIET: case SYSLOG_LEVEL_FATAL: case SYSLOG_LEVEL_ERROR: case SYSLOG_LEVEL_INFO: case SYSLOG_LEVEL_VERBOSE: case SYSLOG_LEVEL_DEBUG1: case SYSLOG_LEVEL_DEBUG2: case SYSLOG_LEVEL_DEBUG3: log_level = new_log_level; return 0; default: return -1; } } int log_is_on_stderr(void) { return log_on_stderr && log_stderr_fd == STDERR_FILENO; } /* redirect what would usually get written to stderr to specified file */ void log_redirect_stderr_to(const char *logfile) { int fd; if (logfile == NULL) { if (log_stderr_fd != STDERR_FILENO) { close(log_stderr_fd); log_stderr_fd = STDERR_FILENO; } return; } if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) { fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile, strerror(errno)); exit(1); } log_stderr_fd = fd; } #define MSGBUFSIZ 1024 void set_log_handler(log_handler_fn *handler, void *ctx) { log_handler = handler; log_handler_ctx = ctx; } static void do_log(LogLevel level, int force, const char *suffix, const char *fmt, va_list args) { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) struct syslog_data sdata = SYSLOG_DATA_INIT; #endif char msgbuf[MSGBUFSIZ]; char fmtbuf[MSGBUFSIZ]; char *txt = NULL; int pri = LOG_INFO; int saved_errno = errno; log_handler_fn *tmp_handler; const char *progname = argv0 != NULL ? argv0 : __progname; if (!force && level > log_level) return; switch (level) { case SYSLOG_LEVEL_FATAL: if (!log_on_stderr) txt = "fatal"; pri = LOG_CRIT; break; case SYSLOG_LEVEL_ERROR: if (!log_on_stderr) txt = "error"; pri = LOG_ERR; break; case SYSLOG_LEVEL_INFO: pri = LOG_INFO; break; case SYSLOG_LEVEL_VERBOSE: pri = LOG_INFO; break; case SYSLOG_LEVEL_DEBUG1: txt = "debug1"; pri = LOG_DEBUG; break; case SYSLOG_LEVEL_DEBUG2: txt = "debug2"; pri = LOG_DEBUG; break; case SYSLOG_LEVEL_DEBUG3: txt = "debug3"; pri = LOG_DEBUG; break; default: txt = "internal error"; pri = LOG_ERR; break; } if (txt != NULL && log_handler == NULL) { snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args); } else { vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); } if (suffix != NULL) { snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix); strlcpy(msgbuf, fmtbuf, sizeof(msgbuf)); } strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); if (log_handler != NULL) { /* Avoid recursion */ tmp_handler = log_handler; log_handler = NULL; tmp_handler(level, force, fmtbuf, log_handler_ctx); log_handler = tmp_handler; } else if (log_on_stderr) { snprintf(msgbuf, sizeof msgbuf, "%s%s%.*s\r\n", (log_on_stderr > 1) ? progname : "", (log_on_stderr > 1) ? ": " : "", (int)sizeof msgbuf - 3, fmtbuf); (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); } else { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) openlog_r(progname, LOG_PID, log_facility, &sdata); syslog_r(pri, &sdata, "%.500s", fmtbuf); closelog_r(&sdata); #else openlog(progname, LOG_PID, log_facility); syslog(pri, "%.500s", fmtbuf); closelog(); #endif } errno = saved_errno; } void sshlog(const char *file, const char *func, int line, int showfunc, LogLevel level, const char *suffix, const char *fmt, ...) { va_list args; va_start(args, fmt); sshlogv(file, func, line, showfunc, level, suffix, fmt, args); va_end(args); } void sshlogdie(const char *file, const char *func, int line, int showfunc, LogLevel level, const char *suffix, const char *fmt, ...) { va_list args; va_start(args, fmt); sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_INFO, suffix, fmt, args); va_end(args); cleanup_exit(255); } void sshlogv(const char *file, const char *func, int line, int showfunc, LogLevel level, const char *suffix, const char *fmt, va_list args) { char tag[128], fmt2[MSGBUFSIZ + 128]; int forced = 0; const char *cp; size_t i; /* short circuit processing early if we're not going to log anything */ if (nlog_verbose == 0 && level > log_level) return; snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (bin=%s, pid=%ld)", (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line, argv0 == NULL ? "UNKNOWN" : argv0, (long)getpid()); for (i = 0; i < nlog_verbose; i++) { if (match_pattern_list(tag, log_verbose[i], 0) == 1) { forced = 1; break; } } if (forced) snprintf(fmt2, sizeof(fmt2), "%s: %s", tag, fmt); else if (showfunc) snprintf(fmt2, sizeof(fmt2), "%s: %s", func, fmt); else strlcpy(fmt2, fmt, sizeof(fmt2)); do_log(level, forced, suffix, fmt2, args); } void sshlogdirect(LogLevel level, int forced, const char *fmt, ...) { va_list args; va_start(args, fmt); do_log(level, forced, NULL, fmt, args); va_end(args); } /* * A simple system for ratelimiting aperiodic events such as logs, without * needing to be hooked into a mainloop/timer. A running total of events is * maintained and when it exceeds a threshold further events are dropped * until the rate falls back below that threshold. * * To prevent flipping in and out of rate-limiting, there is a hysteresis * timer that delays leaving the rate-limited state. * * While in the rate-limited state, events can be periodically allowed though * and the number of dropped events since the last log obtained. * * XXX a moving average rate of events might be a better approach here rather * than linear decay, which can suppress events for a while after large * bursts. */ /* #define RATELIMIT_DEBUG 1 */ #ifdef RATELIMIT_DEBUG # define RLDBG(x) do { \ printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ printf x; \ printf("\n"); \ fflush(stdout); \ } while (0) #else # define RLDBG(x) #endif /* set up a ratelimit */ void log_ratelimit_init(struct log_ratelimit_ctx *rl, u_int threshold, u_int max_accum, u_int hysteresis, u_int log_every) { memset(rl, 0, sizeof(*rl)); rl->threshold = threshold; rl->max_accum = max_accum; rl->hysteresis = hysteresis; rl->log_every = log_every; RLDBG(("called: rl=%p thresh=%u max=%u hys=%u log_every=%u", rl, rl->threshold, rl->max_accum, rl->hysteresis, rl->log_every)); } /* * check whether a log event should be dropped because of rate-limiting. * returns non-zero if the event should be dropped. If events_since_last * is supplied then, for periodic logs, it will be set to the number of * dropped events since the last message. */ int log_ratelimit(struct log_ratelimit_ctx *rl, time_t now, int *active, u_int *events_dropped) { time_t olast_event; RLDBG(("called: rl=%p thresh=%u max=%u hys=%u log_every=%u " "accum=%u since=%ld since_last=%u", rl, rl->threshold, rl->max_accum, rl->hysteresis, rl->log_every, rl->accumulated_events, rl->last_event == 0 ? -1 : (long)(now - rl->last_event), rl->ratelimited_events)); if (now < 0) return 0; if (events_dropped != NULL) *events_dropped = 0; if (active != NULL) *active = rl->ratelimit_active; /* First, decay accumulated events */ if (rl->last_event <= 0) rl->last_event = now; if (now > rl->last_event) { uint64_t n = now - rl->last_event; if (n > UINT_MAX) n = UINT_MAX; if (rl->accumulated_events < (u_int)n) rl->accumulated_events = 0; else rl->accumulated_events -= (u_int)n; RLDBG(("decay: accum=%u", rl->accumulated_events)); } rl->accumulated_events++; /* add this event */ if (rl->accumulated_events > rl->max_accum) rl->accumulated_events = rl->max_accum; olast_event = rl->last_event; rl->last_event = now; RLDBG(("check threshold: accum=%u vs thresh=%u", rl->accumulated_events, rl->threshold)); /* Are we under threshold? */ if (rl->accumulated_events < rl->threshold) { if (!rl->ratelimit_active) return 0; RLDBG(("under threshold: hys=%u since_hys=%ld since_last=%ld", rl->hysteresis, rl->hysteresis_start == 0 ? -1 : (long)(now - rl->hysteresis_start), olast_event == 0 ? -1 : (long)(now - olast_event))); if (rl->hysteresis_start == 0) { /* active, but under threshold; hysteresis */ if (olast_event + rl->hysteresis < now) { /* hysteresis expired before this event */ RLDBG(("hysteresis preexpired")); goto inactive; } RLDBG(("start hysteresis")); rl->hysteresis_start = now; } else if (rl->hysteresis_start + rl->hysteresis < now) { /* Hysteresis period expired, transition to inactive */ RLDBG(("complete hysteresis")); inactive: if (events_dropped != NULL) *events_dropped = rl->ratelimited_events; if (active != NULL) *active = 0; rl->ratelimit_active = 0; rl->ratelimit_start = 0; rl->last_log = 0; rl->hysteresis_start = 0; rl->ratelimited_events = 0; return 0; } /* ratelimiting active, but in hysteresis period */ } else if (!rl->ratelimit_active) { /* Transition to rate-limiting */ RLDBG(("start ratelimit")); rl->ratelimit_active = 1; rl->ratelimit_start = now; rl->last_log = now; rl->hysteresis_start = 0; rl->ratelimited_events = 1; if (active != NULL) *active = 1; return 1; } else if (rl->hysteresis_start != 0) { /* active and over threshold; reset hysteresis timer */ RLDBG(("clear hysteresis")); rl->hysteresis_start = 0; } /* over threshold or in hysteresis period; log periodically */ if (active != NULL) *active = 1; RLDBG(("log_every=%u since_log=%ld", rl->log_every, (long)(now - rl->last_log))); if (rl->log_every > 0 && now >= rl->last_log + rl->log_every) { RLDBG(("periodic: since_last=%u", rl->ratelimited_events)); rl->last_log = now; if (events_dropped != NULL) { *events_dropped = rl->ratelimited_events; rl->ratelimited_events = 0; } return 0; } /* drop event */ rl->ratelimited_events++; RLDBG(("drop: ratelimited_events=%u", rl->ratelimited_events)); return 1; } openssh-10.0p1/PaxHeaders.10889/log.h100644 001750 001750 0000000003614775415623 0014106xustar0030 atime=1744182234.579905794 openssh-10.0p1/log.h010064400017500001750000000161301477541562300124720ustar00djmdjm/* $OpenBSD: log.h,v 1.35 2024/12/07 10:05:37 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef SSH_LOG_H #define SSH_LOG_H #include /* va_list */ #include "ssherr.h" /* ssh_err() */ /* Supported syslog facilities and levels. */ typedef enum { SYSLOG_FACILITY_DAEMON, SYSLOG_FACILITY_USER, SYSLOG_FACILITY_AUTH, #ifdef LOG_AUTHPRIV SYSLOG_FACILITY_AUTHPRIV, #endif SYSLOG_FACILITY_LOCAL0, SYSLOG_FACILITY_LOCAL1, SYSLOG_FACILITY_LOCAL2, SYSLOG_FACILITY_LOCAL3, SYSLOG_FACILITY_LOCAL4, SYSLOG_FACILITY_LOCAL5, SYSLOG_FACILITY_LOCAL6, SYSLOG_FACILITY_LOCAL7, SYSLOG_FACILITY_NOT_SET = -1 } SyslogFacility; typedef enum { SYSLOG_LEVEL_QUIET, SYSLOG_LEVEL_FATAL, SYSLOG_LEVEL_ERROR, SYSLOG_LEVEL_INFO, SYSLOG_LEVEL_VERBOSE, SYSLOG_LEVEL_DEBUG1, SYSLOG_LEVEL_DEBUG2, SYSLOG_LEVEL_DEBUG3, SYSLOG_LEVEL_NOT_SET = -1 } LogLevel; typedef void (log_handler_fn)(LogLevel, int, const char *, void *); void log_init(const char *, LogLevel, SyslogFacility, int); LogLevel log_level_get(void); int log_change_level(LogLevel); int log_is_on_stderr(void); void log_redirect_stderr_to(const char *); void log_verbose_add(const char *); void log_verbose_reset(void); SyslogFacility log_facility_number(char *); const char * log_facility_name(SyslogFacility); LogLevel log_level_number(char *); const char * log_level_name(LogLevel); void set_log_handler(log_handler_fn *, void *); void cleanup_exit(int) __attribute__((noreturn)); void sshlog(const char *, const char *, int, int, LogLevel, const char *, const char *, ...) __attribute__((format(printf, 7, 8))); void sshlogv(const char *, const char *, int, int, LogLevel, const char *, const char *, va_list); void sshlogdie(const char *, const char *, int, int, LogLevel, const char *, const char *, ...) __attribute__((noreturn)) __attribute__((format(printf, 7, 8))); void sshfatal(const char *, const char *, int, int, LogLevel, const char *, const char *, ...) __attribute__((noreturn)) __attribute__((format(printf, 7, 8))); void sshlogdirect(LogLevel, int, const char *, ...) __attribute__((format(printf, 3, 4))); struct log_ratelimit_ctx { /* configuration */ u_int threshold; /* events per second */ u_int max_accum; /* max events to accumulate */ u_int hysteresis; /* seconds */ u_int log_every; /* seconds */ /* state */ time_t last_event; u_int accumulated_events; /* used for threshold comparisons */ /* state while actively rate-limiting */ int ratelimit_active; time_t ratelimit_start; time_t last_log; time_t hysteresis_start; u_int ratelimited_events; }; void log_ratelimit_init(struct log_ratelimit_ctx *rl, u_int threshold, u_int max_accum, u_int hysteresis, u_int log_every); int log_ratelimit(struct log_ratelimit_ctx *rl, time_t now, int *active, u_int *events_dropped); #define do_log2(level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, NULL, __VA_ARGS__) #define debug3(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__) #define debug2(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__) #define debug(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__) #define verbose(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__) #define logit(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__) #define error(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) #define fatal(...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__) #define logdie(...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) /* Variants that prepend the caller's function */ #define do_log2_f(level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, NULL, __VA_ARGS__) #define debug3_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__) #define debug2_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__) #define debug_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__) #define verbose_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__) #define logit_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__) #define error_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) #define fatal_f(...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__) #define logdie_f(...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) /* Variants that appends a ssh_err message */ #define do_log2_r(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, ssh_err(r), __VA_ARGS__) #define debug3_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__) #define debug2_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__) #define debug_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__) #define verbose_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__) #define logit_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__) #define error_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) #define fatal_r(r, ...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__) #define logdie_r(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) #define do_log2_fr(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, ssh_err(r), __VA_ARGS__) #define debug3_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__) #define debug2_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__) #define debug_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__) #define verbose_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__) #define logit_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__) #define error_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) #define fatal_fr(r, ...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__) #define logdie_fr(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) #endif openssh-10.0p1/PaxHeaders.10889/loginrec.c100644 001750 001750 0000000003614775415623 0015122xustar0030 atime=1744182234.580883002 openssh-10.0p1/loginrec.c010064400017500001750000001236401477541562300135130ustar00djmdjm/* * Copyright (c) 2000 Andre Lucas. All rights reserved. * Portions copyright (c) 1998 Todd C. Miller * Portions copyright (c) 1996 Jason Downs * Portions copyright (c) 1996 Theo de Raadt * * 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. */ /** ** loginrec.c: platform-independent login recording and lastlog retrieval **/ /* * The new login code explained * ============================ * * This code attempts to provide a common interface to login recording * (utmp and friends) and last login time retrieval. * * Its primary means of achieving this is to use 'struct logininfo', a * union of all the useful fields in the various different types of * system login record structures one finds on UNIX variants. * * We depend on autoconf to define which recording methods are to be * used, and which fields are contained in the relevant data structures * on the local system. Many C preprocessor symbols affect which code * gets compiled here. * * The code is designed to make it easy to modify a particular * recording method, without affecting other methods nor requiring so * many nested conditional compilation blocks as were commonplace in * the old code. * * For login recording, we try to use the local system's libraries as * these are clearly most likely to work correctly. For utmp systems * this usually means login() and logout() or setutent() etc., probably * in libutil, along with logwtmp() etc. On these systems, we fall back * to writing the files directly if we have to, though this method * requires very thorough testing so we do not corrupt local auditing * information. These files and their access methods are very system * specific indeed. * * For utmpx systems, the corresponding library functions are * setutxent() etc. To the author's knowledge, all utmpx systems have * these library functions and so no direct write is attempted. If such * a system exists and needs support, direct analogues of the [uw]tmp * code should suffice. * * Retrieving the time of last login ('lastlog') is in some ways even * more problemmatic than login recording. Some systems provide a * simple table of all users which we seek based on uid and retrieve a * relatively standard structure. Others record the same information in * a directory with a separate file, and others don't record the * information separately at all. For systems in the latter category, * we look backwards in the wtmp or wtmpx file for the last login entry * for our user. Naturally this is slower and on busy systems could * incur a significant performance penalty. * * Calling the new code * -------------------- * * In OpenSSH all login recording and retrieval is performed in * login.c. Here you'll find working examples. Also, in the logintest.c * program there are more examples. * * Internal handler calling method * ------------------------------- * * When a call is made to login_login() or login_logout(), both * routines set a struct logininfo flag defining which action (log in, * or log out) is to be taken. They both then call login_write(), which * calls whichever of the many structure-specific handlers autoconf * selects for the local system. * * The handlers themselves handle system data structure specifics. Both * struct utmp and struct utmpx have utility functions (see * construct_utmp*()) to try to make it simpler to add extra systems * that introduce new features to either structure. * * While it may seem terribly wasteful to replicate so much similar * code for each method, experience has shown that maintaining code to * write both struct utmp and utmpx in one function, whilst maintaining * support for all systems whether they have library support or not, is * a difficult and time-consuming task. * * Lastlog support proceeds similarly. Functions login_get_lastlog() * (and its OpenSSH-tuned friend login_get_lastlog_time()) call * getlast_entry(), which tries one of three methods to find the last * login time. It uses local system lastlog support if it can, * otherwise it tries wtmp or wtmpx before giving up and returning 0, * meaning "tilt". * * Maintenance * ----------- * * In many cases it's possible to tweak autoconf to select the correct * methods for a particular platform, either by improving the detection * code (best), or by presetting DISABLE_ or CONF__FILE * symbols for the platform. * * Use logintest to check which symbols are defined before modifying * configure.ac and loginrec.c. (You have to build logintest yourself * with 'make logintest' as it's not built by default.) * * Otherwise, patches to the specific method(s) are very helpful! */ #include "includes.h" #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #include "xmalloc.h" #include "sshkey.h" #include "hostfile.h" #include "ssh.h" #include "loginrec.h" #include "log.h" #include "atomicio.h" #include "packet.h" #include "canohost.h" #include "auth.h" #include "sshbuf.h" #include "ssherr.h" #include "misc.h" #ifdef HAVE_UTIL_H # include #endif #ifdef USE_WTMPDB # include #endif /** ** prototypes for helper functions in this file **/ #if HAVE_UTMP_H void set_utmp_time(struct logininfo *li, struct utmp *ut); void construct_utmp(struct logininfo *li, struct utmp *ut); #endif #ifdef HAVE_UTMPX_H void set_utmpx_time(struct logininfo *li, struct utmpx *ut); void construct_utmpx(struct logininfo *li, struct utmpx *ut); #endif int utmp_write_entry(struct logininfo *li); int utmpx_write_entry(struct logininfo *li); int wtmp_write_entry(struct logininfo *li); int wtmpx_write_entry(struct logininfo *li); int lastlog_write_entry(struct logininfo *li); int syslogin_write_entry(struct logininfo *li); #ifdef USE_WTMPDB int wtmpdb_write_entry(struct logininfo *li); #endif int getlast_entry(struct logininfo *li); int lastlog_get_entry(struct logininfo *li); int utmpx_get_entry(struct logininfo *li); int wtmp_get_entry(struct logininfo *li); int wtmpx_get_entry(struct logininfo *li); extern struct sshbuf *loginmsg; /* pick the shortest string */ #define MIN_SIZEOF(s1,s2) (sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2)) /** ** platform-independent login functions **/ /* * login_login(struct logininfo *) - Record a login * * Call with a pointer to a struct logininfo initialised with * login_init_entry() or login_alloc_entry() * * Returns: * >0 if successful * 0 on failure (will use OpenSSH's logging facilities for diagnostics) */ int login_login(struct logininfo *li) { li->type = LTYPE_LOGIN; return (login_write(li)); } /* * login_logout(struct logininfo *) - Record a logout * * Call as with login_login() * * Returns: * >0 if successful * 0 on failure (will use OpenSSH's logging facilities for diagnostics) */ int login_logout(struct logininfo *li) { li->type = LTYPE_LOGOUT; return (login_write(li)); } /* * login_get_lastlog_time(int) - Retrieve the last login time * * Retrieve the last login time for the given uid. Will try to use the * system lastlog facilities if they are available, but will fall back * to looking in wtmp/wtmpx if necessary * * Returns: * 0 on failure, or if user has never logged in * Time in seconds from the epoch if successful * * Useful preprocessor symbols: * DISABLE_LASTLOG: If set, *never* even try to retrieve lastlog * info * USE_LASTLOG: If set, indicates the presence of system lastlog * facilities. If this and DISABLE_LASTLOG are not set, * try to retrieve lastlog information from wtmp/wtmpx. */ unsigned int login_get_lastlog_time(const uid_t uid) { struct logininfo li; if (login_get_lastlog(&li, uid)) return (li.tv_sec); else return (0); } /* * login_get_lastlog(struct logininfo *, int) - Retrieve a lastlog entry * * Retrieve a logininfo structure populated (only partially) with * information from the system lastlog data, or from wtmp/wtmpx if no * system lastlog information exists. * * Note this routine must be given a pre-allocated logininfo. * * Returns: * >0: A pointer to your struct logininfo if successful * 0 on failure (will use OpenSSH's logging facilities for diagnostics) */ struct logininfo * login_get_lastlog(struct logininfo *li, const uid_t uid) { struct passwd *pw; memset(li, '\0', sizeof(*li)); li->uid = uid; /* * If we don't have a 'real' lastlog, we need the username to * reliably search wtmp(x) for the last login (see * wtmp_get_entry().) */ pw = getpwuid(uid); if (pw == NULL) fatal("%s: Cannot find account for uid %ld", __func__, (long)uid); if (strlcpy(li->username, pw->pw_name, sizeof(li->username)) >= sizeof(li->username)) { error("%s: username too long (%lu > max %lu)", __func__, (unsigned long)strlen(pw->pw_name), (unsigned long)sizeof(li->username) - 1); return NULL; } if (getlast_entry(li)) return (li); else return (NULL); } /* * login_alloc_entry(int, char*, char*, char*) - Allocate and initialise * a logininfo structure * * This function creates a new struct logininfo, a data structure * meant to carry the information required to portably record login info. * * Returns a pointer to a newly created struct logininfo. If memory * allocation fails, the program halts. */ struct logininfo *login_alloc_entry(pid_t pid, const char *username, const char *hostname, const char *line) { struct logininfo *newli; newli = xmalloc(sizeof(*newli)); login_init_entry(newli, pid, username, hostname, line); return (newli); } /* login_free_entry(struct logininfo *) - free struct memory */ void login_free_entry(struct logininfo *li) { free(li); } /* login_init_entry(struct logininfo *, int, char*, char*, char*) * - initialise a struct logininfo * * Populates a new struct logininfo, a data structure meant to carry * the information required to portably record login info. * * Returns: 1 */ int login_init_entry(struct logininfo *li, pid_t pid, const char *username, const char *hostname, const char *line) { struct passwd *pw; memset(li, 0, sizeof(*li)); li->pid = pid; /* set the line information */ if (line) line_fullname(li->line, line, sizeof(li->line)); if (username) { strlcpy(li->username, username, sizeof(li->username)); pw = getpwnam(li->username); if (pw == NULL) { fatal("%s: Cannot find user \"%s\"", __func__, li->username); } li->uid = pw->pw_uid; } if (hostname) strlcpy(li->hostname, hostname, sizeof(li->hostname)); return (1); } /* * login_set_current_time(struct logininfo *) - set the current time * * Set the current time in a logininfo structure. This function is * meant to eliminate the need to deal with system dependencies for * time handling. */ void login_set_current_time(struct logininfo *li) { struct timeval tv; gettimeofday(&tv, NULL); li->tv_sec = tv.tv_sec; li->tv_usec = tv.tv_usec; } /* copy a sockaddr_* into our logininfo */ void login_set_addr(struct logininfo *li, const struct sockaddr *sa, const unsigned int sa_size) { unsigned int bufsize = sa_size; /* make sure we don't overrun our union */ if (sizeof(li->hostaddr) < sa_size) bufsize = sizeof(li->hostaddr); memcpy(&li->hostaddr.sa, sa, bufsize); } /** ** login_write: Call low-level recording functions based on autoconf ** results **/ int login_write(struct logininfo *li) { #ifndef HAVE_CYGWIN if (geteuid() != 0) { logit("Attempt to write login records by non-root user (aborting)"); return (1); } #endif /* set the timestamp */ login_set_current_time(li); #ifdef USE_LOGIN syslogin_write_entry(li); #endif #ifdef USE_LASTLOG if (li->type == LTYPE_LOGIN) lastlog_write_entry(li); #endif #ifdef USE_UTMP utmp_write_entry(li); #endif #ifdef USE_WTMP wtmp_write_entry(li); #endif #ifdef USE_UTMPX utmpx_write_entry(li); #endif #ifdef USE_WTMPX wtmpx_write_entry(li); #endif #ifdef USE_WTMPDB wtmpdb_write_entry(li); #endif #ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN if (li->type == LTYPE_LOGIN && !sys_auth_record_login(li->username,li->hostname,li->line, loginmsg)) logit("Writing login record failed for %s", li->username); #endif #ifdef SSH_AUDIT_EVENTS if (li->type == LTYPE_LOGIN) audit_session_open(li); else if (li->type == LTYPE_LOGOUT) audit_session_close(li); #endif return (0); } #ifdef LOGIN_NEEDS_UTMPX int login_utmp_only(struct logininfo *li) { li->type = LTYPE_LOGIN; login_set_current_time(li); # ifdef USE_UTMP utmp_write_entry(li); # endif # ifdef USE_WTMP wtmp_write_entry(li); # endif # ifdef USE_UTMPX utmpx_write_entry(li); # endif # ifdef USE_WTMPX wtmpx_write_entry(li); # endif return (0); } #endif /** ** getlast_entry: Call low-level functions to retrieve the last login ** time. **/ /* take the uid in li and return the last login time */ int getlast_entry(struct logininfo *li) { #ifdef USE_LASTLOG return(lastlog_get_entry(li)); #else /* !USE_LASTLOG */ #if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \ defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER) return (utmpx_get_entry(li)); #endif #if defined(DISABLE_LASTLOG) /* On some systems we shouldn't even try to obtain last login * time, e.g. AIX */ return (0); # elif defined(USE_WTMP) && \ (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) /* retrieve last login time from utmp */ return (wtmp_get_entry(li)); # elif defined(USE_WTMPX) && \ (defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX)) /* If wtmp isn't available, try wtmpx */ return (wtmpx_get_entry(li)); # else /* Give up: No means of retrieving last login time */ return (0); # endif /* DISABLE_LASTLOG */ #endif /* USE_LASTLOG */ } /* * 'line' string utility functions * * These functions process the 'line' string into one of three forms: * * 1. The full filename (including '/dev') * 2. The stripped name (excluding '/dev') * 3. The abbreviated name (e.g. /dev/ttyp00 -> yp00 * /dev/pts/1 -> ts/1 ) * * Form 3 is used on some systems to identify a .tmp.? entry when * attempting to remove it. Typically both addition and removal is * performed by one application - say, sshd - so as long as the choice * uniquely identifies a terminal it's ok. */ /* * line_fullname(): add the leading '/dev/' if it doesn't exist make * sure dst has enough space, if not just copy src (ugh) */ char * line_fullname(char *dst, const char *src, u_int dstsize) { memset(dst, '\0', dstsize); if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5))) strlcpy(dst, src, dstsize); else { strlcpy(dst, "/dev/", dstsize); strlcat(dst, src, dstsize); } return (dst); } /* line_stripname(): strip the leading '/dev' if it exists, return dst */ char * line_stripname(char *dst, const char *src, int dstsize) { memset(dst, '\0', dstsize); if (strncmp(src, "/dev/", 5) == 0) strlcpy(dst, src + 5, dstsize); else strlcpy(dst, src, dstsize); return (dst); } /* * line_abbrevname(): Return the abbreviated (usually four-character) * form of the line (Just use the last characters of the * full name.) * * NOTE: use strncpy because we do NOT necessarily want zero * termination */ char * line_abbrevname(char *dst, const char *src, int dstsize) { size_t len; memset(dst, '\0', dstsize); if (strcmp(src, "ssh:notty") == 0) return dst; /* Always skip prefix if present */ if (strncmp(src, "/dev/", 5) == 0) src += 5; #ifdef WITH_ABBREV_NO_TTY if (strncmp(src, "tty", 3) == 0) src += 3; #endif len = strlen(src); if (len > 0) { if (((int)len - dstsize) > 0) src += ((int)len - dstsize); /* note: _don't_ change this to strlcpy */ strncpy(dst, src, (size_t)dstsize); } return (dst); } /** ** utmp utility functions ** ** These functions manipulate struct utmp, taking system differences ** into account. **/ #if defined(USE_BTMP) || defined(USE_UTMP) || defined (USE_WTMP) || defined (USE_LOGIN) /* build the utmp structure */ void set_utmp_time(struct logininfo *li, struct utmp *ut) { # if defined(HAVE_TV_IN_UTMP) ut->ut_tv.tv_sec = li->tv_sec; ut->ut_tv.tv_usec = li->tv_usec; # elif defined(HAVE_TIME_IN_UTMP) ut->ut_time = li->tv_sec; # endif } void construct_utmp(struct logininfo *li, struct utmp *ut) { # ifdef HAVE_ADDR_V6_IN_UTMP struct sockaddr_in6 *sa6; # endif memset(ut, '\0', sizeof(*ut)); /* First fill out fields used for both logins and logouts */ # ifdef HAVE_ID_IN_UTMP line_abbrevname(ut->ut_id, li->line, sizeof(ut->ut_id)); # endif # ifdef HAVE_TYPE_IN_UTMP /* This is done here to keep utmp constants out of struct logininfo */ switch (li->type) { case LTYPE_LOGIN: ut->ut_type = USER_PROCESS; break; case LTYPE_LOGOUT: ut->ut_type = DEAD_PROCESS; break; } # endif set_utmp_time(li, ut); line_stripname(ut->ut_line, li->line, sizeof(ut->ut_line)); # ifdef HAVE_PID_IN_UTMP ut->ut_pid = li->pid; # endif /* If we're logging out, leave all other fields blank */ if (li->type == LTYPE_LOGOUT) return; /* * These fields are only used when logging in, and are blank * for logouts. */ /* Use strncpy because we don't necessarily want null termination */ strncpy(ut->ut_name, li->username, MIN_SIZEOF(ut->ut_name, li->username)); # ifdef HAVE_HOST_IN_UTMP strncpy(ut->ut_host, li->hostname, MIN_SIZEOF(ut->ut_host, li->hostname)); # endif # ifdef HAVE_ADDR_IN_UTMP /* this is just a 32-bit IP address */ if (li->hostaddr.sa.sa_family == AF_INET) ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; # endif # ifdef HAVE_ADDR_V6_IN_UTMP /* this is just a 128-bit IPv6 address */ if (li->hostaddr.sa.sa_family == AF_INET6) { sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa); memcpy(ut->ut_addr_v6, sa6->sin6_addr.s6_addr, 16); if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { ut->ut_addr_v6[0] = ut->ut_addr_v6[3]; ut->ut_addr_v6[1] = 0; ut->ut_addr_v6[2] = 0; ut->ut_addr_v6[3] = 0; } } # endif } #endif /* USE_BTMP || USE_UTMP || USE_WTMP || USE_LOGIN */ /** ** utmpx utility functions ** ** These functions manipulate struct utmpx, accounting for system ** variations. **/ #if defined(USE_UTMPX) || defined (USE_WTMPX) /* build the utmpx structure */ void set_utmpx_time(struct logininfo *li, struct utmpx *utx) { # if defined(HAVE_TV_IN_UTMPX) utx->ut_tv.tv_sec = li->tv_sec; utx->ut_tv.tv_usec = li->tv_usec; # elif defined(HAVE_TIME_IN_UTMPX) utx->ut_time = li->tv_sec; # endif } void construct_utmpx(struct logininfo *li, struct utmpx *utx) { # ifdef HAVE_ADDR_V6_IN_UTMPX struct sockaddr_in6 *sa6; # endif memset(utx, '\0', sizeof(*utx)); # ifdef HAVE_ID_IN_UTMPX line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id)); # endif /* this is done here to keep utmp constants out of loginrec.h */ switch (li->type) { case LTYPE_LOGIN: utx->ut_type = USER_PROCESS; break; case LTYPE_LOGOUT: utx->ut_type = DEAD_PROCESS; break; } line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line)); set_utmpx_time(li, utx); utx->ut_pid = li->pid; /* strncpy(): Don't necessarily want null termination */ strncpy(utx->ut_user, li->username, MIN_SIZEOF(utx->ut_user, li->username)); if (li->type == LTYPE_LOGOUT) return; /* * These fields are only used when logging in, and are blank * for logouts. */ # ifdef HAVE_HOST_IN_UTMPX strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname)); # endif # ifdef HAVE_SS_IN_UTMPX utx->ut_ss = li->hostaddr.sa_storage; # endif # ifdef HAVE_ADDR_IN_UTMPX /* this is just a 32-bit IP address */ if (li->hostaddr.sa.sa_family == AF_INET) utx->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; # endif # ifdef HAVE_ADDR_V6_IN_UTMPX /* this is just a 128-bit IPv6 address */ if (li->hostaddr.sa.sa_family == AF_INET6) { sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa); memcpy(utx->ut_addr_v6, sa6->sin6_addr.s6_addr, 16); if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { utx->ut_addr_v6[0] = utx->ut_addr_v6[3]; utx->ut_addr_v6[1] = 0; utx->ut_addr_v6[2] = 0; utx->ut_addr_v6[3] = 0; } } # endif # ifdef HAVE_SYSLEN_IN_UTMPX /* ut_syslen is the length of the utx_host string */ utx->ut_syslen = MINIMUM(strlen(li->hostname), sizeof(utx->ut_host)); # endif } #endif /* USE_UTMPX || USE_WTMPX */ /** ** Low-level utmp functions **/ /* FIXME: (ATL) utmp_write_direct needs testing */ #ifdef USE_UTMP /* if we can, use pututline() etc. */ # if !defined(DISABLE_PUTUTLINE) && defined(HAVE_SETUTENT) && \ defined(HAVE_PUTUTLINE) # define UTMP_USE_LIBRARY # endif /* write a utmp entry with the system's help (pututline() and pals) */ # ifdef UTMP_USE_LIBRARY static int utmp_write_library(struct logininfo *li, struct utmp *ut) { setutent(); pututline(ut); # ifdef HAVE_ENDUTENT endutent(); # endif return (1); } # else /* UTMP_USE_LIBRARY */ /* * Write a utmp entry direct to the file * This is a slightly modification of code in OpenBSD's login.c */ static int utmp_write_direct(struct logininfo *li, struct utmp *ut) { struct utmp old_ut; register int fd; int tty; /* FIXME: (ATL) ttyslot() needs local implementation */ #if defined(HAVE_GETTTYENT) struct ttyent *ty; tty=0; setttyent(); while (NULL != (ty = getttyent())) { tty++; if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line))) break; } endttyent(); if (NULL == ty) { logit("%s: tty not found", __func__); return (0); } #else /* FIXME */ tty = ttyslot(); /* seems only to work for /dev/ttyp? style names */ #endif /* HAVE_GETTTYENT */ if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) >= 0) { off_t pos, ret; pos = (off_t)tty * sizeof(struct utmp); if ((ret = lseek(fd, pos, SEEK_SET)) == -1) { logit("%s: lseek: %s", __func__, strerror(errno)); close(fd); return (0); } if (ret != pos) { logit("%s: Couldn't seek to tty %d slot in %s", __func__, tty, UTMP_FILE); close(fd); return (0); } /* * Prevent luser from zero'ing out ut_host. * If the new ut_line is empty but the old one is not * and ut_line and ut_name match, preserve the old ut_line. */ if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) && (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') && (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) && (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0)) memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); if ((ret = lseek(fd, pos, SEEK_SET)) == -1) { logit("%s: lseek: %s", __func__, strerror(errno)); close(fd); return (0); } if (ret != pos) { logit("%s: Couldn't seek to tty %d slot in %s", __func__, tty, UTMP_FILE); close(fd); return (0); } if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) { logit("%s: error writing %s: %s", __func__, UTMP_FILE, strerror(errno)); close(fd); return (0); } close(fd); return (1); } else { return (0); } } # endif /* UTMP_USE_LIBRARY */ static int utmp_perform_login(struct logininfo *li) { struct utmp ut; construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { logit("%s: utmp_write_library() failed", __func__); return (0); } # else if (!utmp_write_direct(li, &ut)) { logit("%s: utmp_write_direct() failed", __func__); return (0); } # endif return (1); } static int utmp_perform_logout(struct logininfo *li) { struct utmp ut; construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { logit("%s: utmp_write_library() failed", __func__); return (0); } # else if (!utmp_write_direct(li, &ut)) { logit("%s: utmp_write_direct() failed", __func__); return (0); } # endif return (1); } int utmp_write_entry(struct logininfo *li) { switch(li->type) { case LTYPE_LOGIN: return (utmp_perform_login(li)); case LTYPE_LOGOUT: return (utmp_perform_logout(li)); default: logit("%s: invalid type field", __func__); return (0); } } #endif /* USE_UTMP */ /** ** Low-level utmpx functions **/ /* not much point if we don't want utmpx entries */ #ifdef USE_UTMPX /* if we have the wherewithall, use pututxline etc. */ # if !defined(DISABLE_PUTUTXLINE) && defined(HAVE_SETUTXENT) && \ defined(HAVE_PUTUTXLINE) # define UTMPX_USE_LIBRARY # endif /* write a utmpx entry with the system's help (pututxline() and pals) */ # ifdef UTMPX_USE_LIBRARY static int utmpx_write_library(struct logininfo *li, struct utmpx *utx) { setutxent(); pututxline(utx); # ifdef HAVE_ENDUTXENT endutxent(); # endif return (1); } # else /* UTMPX_USE_LIBRARY */ /* write a utmp entry direct to the file */ static int utmpx_write_direct(struct logininfo *li, struct utmpx *utx) { logit("%s: not implemented!", __func__); return (0); } # endif /* UTMPX_USE_LIBRARY */ static int utmpx_perform_login(struct logininfo *li) { struct utmpx utx; construct_utmpx(li, &utx); # ifdef UTMPX_USE_LIBRARY if (!utmpx_write_library(li, &utx)) { logit("%s: utmp_write_library() failed", __func__); return (0); } # else if (!utmpx_write_direct(li, &utx)) { logit("%s: utmp_write_direct() failed", __func__); return (0); } # endif return (1); } static int utmpx_perform_logout(struct logininfo *li) { struct utmpx utx; construct_utmpx(li, &utx); # ifdef HAVE_ID_IN_UTMPX line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id)); # endif # ifdef HAVE_TYPE_IN_UTMPX utx.ut_type = DEAD_PROCESS; # endif # ifdef UTMPX_USE_LIBRARY utmpx_write_library(li, &utx); # else utmpx_write_direct(li, &utx); # endif return (1); } int utmpx_write_entry(struct logininfo *li) { switch(li->type) { case LTYPE_LOGIN: return (utmpx_perform_login(li)); case LTYPE_LOGOUT: return (utmpx_perform_logout(li)); default: logit("%s: invalid type field", __func__); return (0); } } #endif /* USE_UTMPX */ /** ** Low-level wtmp functions **/ #ifdef USE_WTMP /* * Write a wtmp entry direct to the end of the file * This is a slight modification of code in OpenBSD's logwtmp.c */ static int wtmp_write(struct logininfo *li, struct utmp *ut) { struct stat buf; int fd, ret = 1; if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) { logit("%s: problem writing %s: %s", __func__, WTMP_FILE, strerror(errno)); return (0); } if (fstat(fd, &buf) == 0) if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) { ftruncate(fd, buf.st_size); logit("%s: problem writing %s: %s", __func__, WTMP_FILE, strerror(errno)); ret = 0; } close(fd); return (ret); } static int wtmp_perform_login(struct logininfo *li) { struct utmp ut; construct_utmp(li, &ut); return (wtmp_write(li, &ut)); } static int wtmp_perform_logout(struct logininfo *li) { struct utmp ut; construct_utmp(li, &ut); return (wtmp_write(li, &ut)); } int wtmp_write_entry(struct logininfo *li) { switch(li->type) { case LTYPE_LOGIN: return (wtmp_perform_login(li)); case LTYPE_LOGOUT: return (wtmp_perform_logout(li)); default: logit("%s: invalid type field", __func__); return (0); } } /* * Notes on fetching login data from wtmp/wtmpx * * Logouts are usually recorded with (amongst other things) a blank * username on a given tty line. However, some systems (HP-UX is one) * leave all fields set, but change the ut_type field to DEAD_PROCESS. * * Since we're only looking for logins here, we know that the username * must be set correctly. On systems that leave it in, we check for * ut_type==USER_PROCESS (indicating a login.) * * Portability: Some systems may set something other than USER_PROCESS * to indicate a login process. I don't know of any as I write. Also, * it's possible that some systems may both leave the username in * place and not have ut_type. */ /* return true if this wtmp entry indicates a login */ static int wtmp_islogin(struct logininfo *li, struct utmp *ut) { if (strncmp(li->username, ut->ut_name, MIN_SIZEOF(li->username, ut->ut_name)) == 0) { # ifdef HAVE_TYPE_IN_UTMP if (ut->ut_type & USER_PROCESS) return (1); # else return (1); # endif } return (0); } int wtmp_get_entry(struct logininfo *li) { struct stat st; struct utmp ut; int fd, found = 0; /* Clear the time entries in our logininfo */ li->tv_sec = li->tv_usec = 0; if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) { logit("%s: problem opening %s: %s", __func__, WTMP_FILE, strerror(errno)); return (0); } if (fstat(fd, &st) != 0) { logit("%s: couldn't stat %s: %s", __func__, WTMP_FILE, strerror(errno)); close(fd); return (0); } /* Seek to the start of the last struct utmp */ if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) { /* Looks like we've got a fresh wtmp file */ close(fd); return (0); } while (!found) { if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) { logit("%s: read of %s failed: %s", __func__, WTMP_FILE, strerror(errno)); close (fd); return (0); } if (wtmp_islogin(li, &ut) ) { found = 1; /* * We've already checked for a time in struct * utmp, in login_getlast() */ # ifdef HAVE_TIME_IN_UTMP li->tv_sec = ut.ut_time; # else # if HAVE_TV_IN_UTMP li->tv_sec = ut.ut_tv.tv_sec; # endif # endif line_fullname(li->line, ut.ut_line, MIN_SIZEOF(li->line, ut.ut_line)); # ifdef HAVE_HOST_IN_UTMP strlcpy(li->hostname, ut.ut_host, MIN_SIZEOF(li->hostname, ut.ut_host)); # endif continue; } /* Seek back 2 x struct utmp */ if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) { /* We've found the start of the file, so quit */ close(fd); return (0); } } /* We found an entry. Tidy up and return */ close(fd); return (1); } # endif /* USE_WTMP */ /** ** Low-level wtmpx functions **/ #ifdef USE_WTMPX /* * Write a wtmpx entry direct to the end of the file * This is a slight modification of code in OpenBSD's logwtmp.c */ static int wtmpx_write(struct logininfo *li, struct utmpx *utx) { #ifndef HAVE_UPDWTMPX struct stat buf; int fd, ret = 1; if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) { logit("%s: problem opening %s: %s", __func__, WTMPX_FILE, strerror(errno)); return (0); } if (fstat(fd, &buf) == 0) if (atomicio(vwrite, fd, utx, sizeof(*utx)) != sizeof(*utx)) { ftruncate(fd, buf.st_size); logit("%s: problem writing %s: %s", __func__, WTMPX_FILE, strerror(errno)); ret = 0; } close(fd); return (ret); #else updwtmpx(WTMPX_FILE, utx); return (1); #endif } static int wtmpx_perform_login(struct logininfo *li) { struct utmpx utx; construct_utmpx(li, &utx); return (wtmpx_write(li, &utx)); } static int wtmpx_perform_logout(struct logininfo *li) { struct utmpx utx; construct_utmpx(li, &utx); return (wtmpx_write(li, &utx)); } int wtmpx_write_entry(struct logininfo *li) { switch(li->type) { case LTYPE_LOGIN: return (wtmpx_perform_login(li)); case LTYPE_LOGOUT: return (wtmpx_perform_logout(li)); default: logit("%s: invalid type field", __func__); return (0); } } /* Please see the notes above wtmp_islogin() for information about the next two functions */ /* Return true if this wtmpx entry indicates a login */ static int wtmpx_islogin(struct logininfo *li, struct utmpx *utx) { if (strncmp(li->username, utx->ut_user, MIN_SIZEOF(li->username, utx->ut_user)) == 0 ) { # ifdef HAVE_TYPE_IN_UTMPX if (utx->ut_type == USER_PROCESS) return (1); # else return (1); # endif } return (0); } int wtmpx_get_entry(struct logininfo *li) { struct stat st; struct utmpx utx; int fd, found=0; /* Clear the time entries */ li->tv_sec = li->tv_usec = 0; if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) { logit("%s: problem opening %s: %s", __func__, WTMPX_FILE, strerror(errno)); return (0); } if (fstat(fd, &st) != 0) { logit("%s: couldn't stat %s: %s", __func__, WTMPX_FILE, strerror(errno)); close(fd); return (0); } /* Seek to the start of the last struct utmpx */ if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) { /* probably a newly rotated wtmpx file */ close(fd); return (0); } while (!found) { if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) { logit("%s: read of %s failed: %s", __func__, WTMPX_FILE, strerror(errno)); close (fd); return (0); } /* * Logouts are recorded as a blank username on a particular * line. So, we just need to find the username in struct utmpx */ if (wtmpx_islogin(li, &utx)) { found = 1; # if defined(HAVE_TV_IN_UTMPX) li->tv_sec = utx.ut_tv.tv_sec; # elif defined(HAVE_TIME_IN_UTMPX) li->tv_sec = utx.ut_time; # endif line_fullname(li->line, utx.ut_line, sizeof(li->line)); # if defined(HAVE_HOST_IN_UTMPX) strlcpy(li->hostname, utx.ut_host, MIN_SIZEOF(li->hostname, utx.ut_host)); # endif continue; } if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) { close(fd); return (0); } } close(fd); return (1); } #endif /* USE_WTMPX */ #ifdef USE_WTMPDB static int wtmpdb_perform_login(struct logininfo *li) { uint64_t login_time = li->tv_sec * ((uint64_t) 1000000ULL) + li->tv_usec; const char *tty; if (strncmp(li->line, "/dev/", 5) == 0) tty = &(li->line[5]); else tty = li->line; li->wtmpdb_id = wtmpdb_login(NULL, USER_PROCESS, li->username, login_time, tty, li->hostname, 0, 0); if (li->wtmpdb_id < 0) return (0); return (1); } static int wtmpdb_perform_logout(struct logininfo *li) { uint64_t logout_time = li->tv_sec * ((uint64_t) 1000000ULL) + li->tv_usec; if (li->wtmpdb_id == 0) { const char *tty; if (strncmp(li->line, "/dev/", 5) == 0) tty = &(li->line[5]); else tty = li->line; li->wtmpdb_id = wtmpdb_get_id(NULL, tty, NULL); } wtmpdb_logout(NULL, li->wtmpdb_id, logout_time, NULL); return (1); } int wtmpdb_write_entry(struct logininfo *li) { switch(li->type) { case LTYPE_LOGIN: return (wtmpdb_perform_login(li)); case LTYPE_LOGOUT: return (wtmpdb_perform_logout(li)); default: logit("%s: invalid type field", __func__); return (0); } } #endif /** ** Low-level libutil login() functions **/ #ifdef USE_LOGIN static int syslogin_perform_login(struct logininfo *li) { struct utmp *ut; ut = xmalloc(sizeof(*ut)); construct_utmp(li, ut); login(ut); free(ut); return (1); } static int syslogin_perform_logout(struct logininfo *li) { # ifdef HAVE_LOGOUT char line[UT_LINESIZE]; (void)line_stripname(line, li->line, sizeof(line)); if (!logout(line)) logit("%s: logout() returned an error", __func__); # ifdef HAVE_LOGWTMP else logwtmp(line, "", ""); # endif /* FIXME: (ATL - if the need arises) What to do if we have * login, but no logout? what if logout but no logwtmp? All * routines are in libutil so they should all be there, * but... */ # endif return (1); } int syslogin_write_entry(struct logininfo *li) { switch (li->type) { case LTYPE_LOGIN: return (syslogin_perform_login(li)); case LTYPE_LOGOUT: return (syslogin_perform_logout(li)); default: logit("%s: Invalid type field", __func__); return (0); } } #endif /* USE_LOGIN */ /* end of file log-syslogin.c */ /** ** Low-level lastlog functions **/ #ifdef USE_LASTLOG #if !defined(LASTLOG_WRITE_PUTUTXLINE) || !defined(HAVE_GETLASTLOGXBYNAME) /* open the file (using filemode) and seek to the login entry */ static int lastlog_openseek(struct logininfo *li, int *fd, int filemode) { off_t offset; char lastlog_file[1024]; struct stat st; if (stat(LASTLOG_FILE, &st) != 0) { logit("%s: Couldn't stat %s: %s", __func__, LASTLOG_FILE, strerror(errno)); return (0); } if (S_ISDIR(st.st_mode)) { snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s", LASTLOG_FILE, li->username); } else if (S_ISREG(st.st_mode)) { strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file)); } else { logit("%s: %.100s is not a file or directory!", __func__, LASTLOG_FILE); return (0); } *fd = open(lastlog_file, filemode, 0600); if (*fd < 0) { debug("%s: Couldn't open %s: %s", __func__, lastlog_file, strerror(errno)); return (0); } if (S_ISREG(st.st_mode)) { /* find this uid's offset in the lastlog file */ offset = (off_t) ((u_long)li->uid * sizeof(struct lastlog)); if (lseek(*fd, offset, SEEK_SET) != offset) { logit("%s: %s->lseek(): %s", __func__, lastlog_file, strerror(errno)); close(*fd); return (0); } } return (1); } #endif /* !LASTLOG_WRITE_PUTUTXLINE || !HAVE_GETLASTLOGXBYNAME */ #ifdef LASTLOG_WRITE_PUTUTXLINE int lastlog_write_entry(struct logininfo *li) { switch(li->type) { case LTYPE_LOGIN: return 1; /* lastlog written by pututxline */ default: logit("lastlog_write_entry: Invalid type field"); return 0; } } #else /* LASTLOG_WRITE_PUTUTXLINE */ int lastlog_write_entry(struct logininfo *li) { struct lastlog last; int fd; switch(li->type) { case LTYPE_LOGIN: /* create our struct lastlog */ memset(&last, '\0', sizeof(last)); line_stripname(last.ll_line, li->line, sizeof(last.ll_line)); strlcpy(last.ll_host, li->hostname, MIN_SIZEOF(last.ll_host, li->hostname)); last.ll_time = li->tv_sec; if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) return (0); /* write the entry */ if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { close(fd); logit("%s: Error writing to %s: %s", __func__, LASTLOG_FILE, strerror(errno)); return (0); } close(fd); return (1); default: logit("%s: Invalid type field", __func__); return (0); } } #endif /* LASTLOG_WRITE_PUTUTXLINE */ #ifdef HAVE_GETLASTLOGXBYNAME int lastlog_get_entry(struct logininfo *li) { struct lastlogx l, *ll; if ((ll = getlastlogxbyname(li->username, &l)) == NULL) { memset(&l, '\0', sizeof(l)); ll = &l; } line_fullname(li->line, ll->ll_line, sizeof(li->line)); strlcpy(li->hostname, ll->ll_host, MIN_SIZEOF(li->hostname, ll->ll_host)); li->tv_sec = ll->ll_tv.tv_sec; li->tv_usec = ll->ll_tv.tv_usec; return (1); } #else /* HAVE_GETLASTLOGXBYNAME */ int lastlog_get_entry(struct logininfo *li) { struct lastlog last; int fd, ret; if (!lastlog_openseek(li, &fd, O_RDONLY)) return (0); ret = atomicio(read, fd, &last, sizeof(last)); close(fd); switch (ret) { case 0: memset(&last, '\0', sizeof(last)); /* FALLTHRU */ case sizeof(last): line_fullname(li->line, last.ll_line, sizeof(li->line)); strlcpy(li->hostname, last.ll_host, MIN_SIZEOF(li->hostname, last.ll_host)); li->tv_sec = last.ll_time; return (1); case -1: error("%s: Error reading from %s: %s", __func__, LASTLOG_FILE, strerror(errno)); return (0); default: error("%s: Error reading from %s: Expecting %d, got %d", __func__, LASTLOG_FILE, (int)sizeof(last), ret); return (0); } /* NOTREACHED */ return (0); } #endif /* HAVE_GETLASTLOGXBYNAME */ #endif /* USE_LASTLOG */ #if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \ defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER) int utmpx_get_entry(struct logininfo *li) { struct utmpx *utx; if (setutxdb(UTXDB_LASTLOGIN, NULL) != 0) return (0); utx = getutxuser(li->username); if (utx == NULL) { endutxent(); return (0); } line_fullname(li->line, utx->ut_line, MIN_SIZEOF(li->line, utx->ut_line)); strlcpy(li->hostname, utx->ut_host, MIN_SIZEOF(li->hostname, utx->ut_host)); li->tv_sec = utx->ut_tv.tv_sec; li->tv_usec = utx->ut_tv.tv_usec; endutxent(); return (1); } #endif /* USE_UTMPX && HAVE_SETUTXDB && UTXDB_LASTLOGIN && HAVE_GETUTXUSER */ #ifdef USE_BTMP /* * Logs failed login attempts in _PATH_BTMP if that exists. * The most common login failure is to give password instead of username. * So the _PATH_BTMP file checked for the correct permission, so that only * root can read it. */ void record_failed_login(struct ssh *ssh, const char *username, const char *hostname, const char *ttyn) { int fd; struct utmp ut; struct logininfo li; socklen_t fromlen = sizeof(li.hostaddr); time_t t; struct stat fst; if (geteuid() != 0) return; if ((fd = open(_PATH_BTMP, O_WRONLY | O_APPEND)) < 0) { debug("Unable to open the btmp file %s: %s", _PATH_BTMP, strerror(errno)); return; } if (fstat(fd, &fst) < 0) { logit("%s: fstat of %s failed: %s", __func__, _PATH_BTMP, strerror(errno)); goto out; } if ((fst.st_mode & (S_IXGRP | S_IRWXO)) || fst.st_uid != 0) { logit("Excess permission or bad ownership on file %s", _PATH_BTMP); goto out; } /* Construct a logininfo and turn it into a utmp */ memset(&li, 0, sizeof(li)); li.type = LTYPE_LOGIN; li.pid = getpid(); strlcpy(li.line, "ssh:notty", sizeof(li.line)); strlcpy(li.username, username, sizeof(li.username)); strlcpy(li.hostname, hostname, sizeof(li.hostname)); time(&t); li.tv_sec = t > 0 ? (unsigned long)t : 0; if (ssh_packet_connection_is_on_socket(ssh)) { (void)getpeername(ssh_packet_get_connection_in(ssh), &li.hostaddr.sa, &fromlen); } construct_utmp(&li, &ut); if (atomicio(vwrite, fd, &ut, sizeof(ut)) != sizeof(ut)) { error("Failed to write to %s: %s", _PATH_BTMP, strerror(errno)); } out: close(fd); } #endif /* USE_BTMP */ openssh-10.0p1/PaxHeaders.10889/loginrec.h100644 001750 001750 0000000003614775415623 0015127xustar0030 atime=1744182234.580883002 openssh-10.0p1/loginrec.h010064400017500001750000000113351477541562300135150ustar00djmdjm#ifndef _HAVE_LOGINREC_H_ #define _HAVE_LOGINREC_H_ /* * Copyright (c) 2000 Andre Lucas. 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. */ /** ** loginrec.h: platform-independent login recording and lastlog retrieval **/ #include "includes.h" struct ssh; /** ** you should use the login_* calls to work around platform dependencies **/ /* * login_netinfo structure */ union login_netinfo { struct sockaddr sa; struct sockaddr_in sa_in; struct sockaddr_storage sa_storage; }; /* * * logininfo structure * */ /* types - different to utmp.h 'type' macros */ /* (though set to the same value as linux, openbsd and others...) */ #define LTYPE_LOGIN 7 #define LTYPE_LOGOUT 8 /* string lengths - set very long */ #define LINFO_PROGSIZE 64 #define LINFO_LINESIZE 64 #define LINFO_NAMESIZE 512 #define LINFO_HOSTSIZE 256 struct logininfo { char progname[LINFO_PROGSIZE]; /* name of program (for PAM) */ int progname_null; short int type; /* type of login (LTYPE_*) */ pid_t pid; /* PID of login process */ uid_t uid; /* UID of this user */ char line[LINFO_LINESIZE]; /* tty/pty name */ char username[LINFO_NAMESIZE]; /* login username */ char hostname[LINFO_HOSTSIZE]; /* remote hostname */ /* 'exit_status' structure components */ int exit; /* process exit status */ int termination; /* process termination status */ /* struct timeval (sys/time.h) isn't always available, if it isn't we'll * use time_t's value as tv_sec and set tv_usec to 0 */ unsigned int tv_sec; unsigned int tv_usec; union login_netinfo hostaddr; /* caller's host address(es) */ #ifdef USE_WTMPDB int64_t wtmpdb_id; /* ID for wtmpdb_logout */ #endif }; /* struct logininfo */ /* * login recording functions */ /** 'public' functions */ /* construct a new login entry */ struct logininfo *login_alloc_entry(pid_t pid, const char *username, const char *hostname, const char *line); /* free a structure */ void login_free_entry(struct logininfo *li); /* fill out a pre-allocated structure with useful information */ int login_init_entry(struct logininfo *li, pid_t pid, const char *username, const char *hostname, const char *line); /* place the current time in a logininfo struct */ void login_set_current_time(struct logininfo *li); /* record the entry */ int login_login (struct logininfo *li); int login_logout(struct logininfo *li); #ifdef LOGIN_NEEDS_UTMPX int login_utmp_only(struct logininfo *li); #endif /** End of public functions */ /* record the entry */ int login_write (struct logininfo *li); int login_log_entry(struct logininfo *li); /* set the network address based on network address type */ void login_set_addr(struct logininfo *li, const struct sockaddr *sa, const unsigned int sa_size); /* * lastlog retrieval functions */ /* lastlog *entry* functions fill out a logininfo */ struct logininfo *login_get_lastlog(struct logininfo *li, const uid_t uid); /* lastlog *time* functions return time_t equivalent (uint) */ unsigned int login_get_lastlog_time(const uid_t uid); /* produce various forms of the line filename */ 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(struct ssh *, const char *, const char *, const char *); #endif /* _HAVE_LOGINREC_H_ */ openssh-10.0p1/PaxHeaders.10889/logintest.c100644 001750 001750 0000000003614775415623 0015330xustar0030 atime=1744182234.580883002 openssh-10.0p1/logintest.c010064400017500001750000000207721477541562300137230ustar00djmdjm/* * Copyright (c) 2000 Andre Lucas. 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. */ /** ** logintest.c: simple test driver for platform-independent login recording ** and lastlog retrieval **/ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_TIME_H #include #endif #include "loginrec.h" extern char *__progname; #define PAUSE_BEFORE_LOGOUT 3 int nologtest = 0; int compile_opts_only = 0; int be_verbose = 0; /* Dump a logininfo to stdout. Assumes a tab size of 8 chars. */ void dump_logininfo(struct logininfo *li, char *descname) { /* yes I know how nasty this is */ printf("struct logininfo %s = {\n\t" "progname\t'%s'\n\ttype\t\t%d\n\t" "pid\t\t%d\n\tuid\t\t%d\n\t" "line\t\t'%s'\n\tusername\t'%s'\n\t" "hostname\t'%s'\n\texit\t\t%d\n\ttermination\t%d\n\t" "tv_sec\t%d\n\ttv_usec\t%d\n\t" "struct login_netinfo hostaddr {\n\t\t" "struct sockaddr sa {\n" "\t\t\tfamily\t%d\n\t\t}\n" "\t}\n" "}\n", descname, li->progname, li->type, li->pid, li->uid, li->line, li->username, li->hostname, li->exit, li->termination, li->tv_sec, li->tv_usec, li->hostaddr.sa.sa_family); } int testAPI() { struct logininfo *li1; struct passwd *pw; struct hostent *he; struct sockaddr_in sa_in4; char cmdstring[256], stripline[8]; char username[32]; #ifdef HAVE_TIME_H time_t t0, t1, t2, logintime, logouttime; char s_t0[64],s_t1[64],s_t2[64]; char s_logintime[64], s_logouttime[64]; /* ctime() strings */ #endif printf("**\n** Testing the API...\n**\n"); pw = getpwuid(getuid()); strlcpy(username, pw->pw_name, sizeof(username)); /* gethostname(hostname, sizeof(hostname)); */ printf("login_alloc_entry test (no host info):\n"); /* FIXME fake tty more effectively - this could upset some platforms */ li1 = login_alloc_entry((int)getpid(), username, NULL, ttyname(0)); strlcpy(li1->progname, "OpenSSH-logintest", sizeof(li1->progname)); if (be_verbose) dump_logininfo(li1, "li1"); printf("Setting host address info for 'localhost' (may call out):\n"); if (! (he = gethostbyname("localhost"))) { printf("Couldn't set hostname(lookup failed)\n"); } else { /* NOTE: this is messy, but typically a program wouldn't have to set * any of this, a sockaddr_in* would be already prepared */ memcpy((void *)&(sa_in4.sin_addr), (void *)&(he->h_addr_list[0][0]), sizeof(struct in_addr)); login_set_addr(li1, (struct sockaddr *) &sa_in4, sizeof(sa_in4)); strlcpy(li1->hostname, "localhost", sizeof(li1->hostname)); } if (be_verbose) dump_logininfo(li1, "li1"); if ((int)geteuid() != 0) { printf("NOT RUNNING LOGIN TESTS - you are not root!\n"); return 1; } if (nologtest) return 1; line_stripname(stripline, li1->line, sizeof(stripline)); printf("Performing an invalid login attempt (no type field)\n--\n"); login_write(li1); printf("--\n(Should have written errors to stderr)\n"); #ifdef HAVE_TIME_H (void)time(&t0); strlcpy(s_t0, ctime(&t0), sizeof(s_t0)); t1 = login_get_lastlog_time(getuid()); strlcpy(s_t1, ctime(&t1), sizeof(s_t1)); printf("Before logging in:\n\tcurrent time is %d - %s\t" "lastlog time is %d - %s\n", (int)t0, s_t0, (int)t1, s_t1); #endif printf("Performing a login on line %s ", stripline); #ifdef HAVE_TIME_H (void)time(&logintime); strlcpy(s_logintime, ctime(&logintime), sizeof(s_logintime)); printf("at %d - %s", (int)logintime, s_logintime); #endif printf("--\n"); login_login(li1); snprintf(cmdstring, sizeof(cmdstring), "who | grep '%s '", stripline); system(cmdstring); printf("--\nPausing for %d second(s)...\n", PAUSE_BEFORE_LOGOUT); sleep(PAUSE_BEFORE_LOGOUT); printf("Performing a logout "); #ifdef HAVE_TIME_H (void)time(&logouttime); strlcpy(s_logouttime, ctime(&logouttime), sizeof(s_logouttime)); printf("at %d - %s", (int)logouttime, s_logouttime); #endif printf("\nThe root login shown above should be gone.\n" "If the root login hasn't gone, but another user on the same\n" "pty has, this is OK - we're hacking it here, and there\n" "shouldn't be two users on one pty in reality...\n" "-- ('who' output follows)\n"); login_logout(li1); system(cmdstring); printf("-- ('who' output ends)\n"); #ifdef HAVE_TIME_H t2 = login_get_lastlog_time(getuid()); strlcpy(s_t2, ctime(&t2), sizeof(s_t2)); printf("After logging in, lastlog time is %d - %s\n", (int)t2, s_t2); if (t1 == t2) printf("The lastlog times before and after logging in are the " "same.\nThis indicates that lastlog is ** NOT WORKING " "CORRECTLY **\n"); else if (t0 != t2) /* We can be off by a second or so, even when recording works fine. * I'm not 100% sure why, but it's true. */ printf("** The login time and the lastlog time differ.\n" "** This indicates that lastlog is either recording the " "wrong time,\n** or retrieving the wrong entry.\n" "If it's off by less than %d second(s) " "run the test again.\n", PAUSE_BEFORE_LOGOUT); else printf("lastlog agrees with the login time. This is a good thing.\n"); #endif printf("--\nThe output of 'last' shown next should have " "an entry for root \n on %s for the time shown above:\n--\n", stripline); snprintf(cmdstring, sizeof(cmdstring), "last | grep '%s ' | head -3", stripline); system(cmdstring); printf("--\nEnd of login test.\n"); login_free_entry(li1); return 1; } /* testAPI() */ void testLineName(char *line) { /* have to null-terminate - these functions are designed for * structures with fixed-length char arrays, and don't null-term.*/ char full[17], strip[9], abbrev[5]; memset(full, '\0', sizeof(full)); memset(strip, '\0', sizeof(strip)); memset(abbrev, '\0', sizeof(abbrev)); line_fullname(full, line, sizeof(full)-1); line_stripname(strip, full, sizeof(strip)-1); line_abbrevname(abbrev, full, sizeof(abbrev)-1); printf("%s: %s, %s, %s\n", line, full, strip, abbrev); } /* testLineName() */ int testOutput() { printf("**\n** Testing linename functions\n**\n"); testLineName("/dev/pts/1"); testLineName("pts/1"); testLineName("pts/999"); testLineName("/dev/ttyp00"); testLineName("ttyp00"); return 1; } /* testOutput() */ /* show which options got compiled in */ void showOptions(void) { printf("**\n** Compile-time options\n**\n"); printf("login recording methods selected:\n"); #ifdef USE_LOGIN printf("\tUSE_LOGIN\n"); #endif #ifdef USE_UTMP printf("\tUSE_UTMP (UTMP_FILE=%s)\n", UTMP_FILE); #endif #ifdef USE_UTMPX printf("\tUSE_UTMPX\n"); #endif #ifdef USE_WTMP printf("\tUSE_WTMP (WTMP_FILE=%s)\n", WTMP_FILE); #endif #ifdef USE_WTMPX printf("\tUSE_WTMPX (WTMPX_FILE=%s)\n", WTMPX_FILE); #endif #ifdef USE_LASTLOG printf("\tUSE_LASTLOG (LASTLOG_FILE=%s)\n", LASTLOG_FILE); #endif printf("\n"); } /* showOptions() */ int main(int argc, char *argv[]) { printf("Platform-independent login recording test driver\n"); __progname = ssh_get_progname(argv[0]); if (argc == 2) { if (strncmp(argv[1], "-i", 3) == 0) compile_opts_only = 1; else if (strncmp(argv[1], "-v", 3) == 0) be_verbose=1; } if (!compile_opts_only) { if (be_verbose && !testOutput()) return 1; if (!testAPI()) return 1; } showOptions(); return 0; } /* main() */ openssh-10.0p1/PaxHeaders.10889/mac.c100644 001750 001750 0000000003614775415623 0014060xustar0030 atime=1744182234.581860772 openssh-10.0p1/mac.c010064400017500001750000000163111477541562300124450ustar00djmdjm/* $OpenBSD: mac.c,v 1.35 2019/09/06 04:53:27 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 #include #include #include #include "digest.h" #include "hmac.h" #include "umac.h" #include "mac.h" #include "misc.h" #include "ssherr.h" #include "sshbuf.h" #include "openbsd-compat/openssl-compat.h" #define SSH_DIGEST 1 /* SSH_DIGEST_XXX */ #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ #define SSH_UMAC128 3 struct macalg { char *name; int type; int alg; int truncatebits; /* truncate digest if != 0 */ int key_len; /* just for UMAC */ int len; /* just for UMAC */ int etm; /* Encrypt-then-MAC */ }; 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 }, { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 }, { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, { "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 }, { "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 }, { "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 }, { "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 }, { "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 }, { "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 }, { NULL, 0, 0, 0, 0, 0, 0 } }; /* Returns a list of supported MACs separated by the specified char. */ char * mac_alg_list(char sep) { char *ret = NULL, *tmp; size_t nlen, rlen = 0; const struct macalg *m; for (m = macs; m->name != NULL; m++) { if (ret != NULL) ret[rlen++] = sep; nlen = strlen(m->name); if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { free(ret); return NULL; } ret = tmp; memcpy(ret + rlen, m->name, nlen + 1); rlen += nlen; } return ret; } static int mac_setup_by_alg(struct sshmac *mac, const struct macalg *macalg) { mac->type = macalg->type; if (mac->type == SSH_DIGEST) { if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL) return SSH_ERR_ALLOC_FAIL; mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg); } else { mac->mac_len = macalg->len / 8; mac->key_len = macalg->key_len / 8; mac->umac_ctx = NULL; } if (macalg->truncatebits != 0) mac->mac_len = macalg->truncatebits / 8; mac->etm = macalg->etm; return 0; } int mac_setup(struct sshmac *mac, char *name) { const struct macalg *m; for (m = macs; m->name != NULL; m++) { if (strcmp(name, m->name) != 0) continue; if (mac != NULL) return mac_setup_by_alg(mac, m); return 0; } return SSH_ERR_INVALID_ARGUMENT; } int mac_init(struct sshmac *mac) { if (mac->key == NULL) return SSH_ERR_INVALID_ARGUMENT; switch (mac->type) { case SSH_DIGEST: if (mac->hmac_ctx == NULL || ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0) return SSH_ERR_INVALID_ARGUMENT; return 0; case SSH_UMAC: if ((mac->umac_ctx = umac_new(mac->key)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; case SSH_UMAC128: if ((mac->umac_ctx = umac128_new(mac->key)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; default: return SSH_ERR_INVALID_ARGUMENT; } } int mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen, u_char *digest, size_t dlen) { static union { u_char m[SSH_DIGEST_MAX_LENGTH]; u_int64_t for_align; } u; u_char b[4]; u_char nonce[8]; if (mac->mac_len > sizeof(u)) return SSH_ERR_INTERNAL_ERROR; switch (mac->type) { case SSH_DIGEST: put_u32(b, seqno); /* reset HMAC context */ if (ssh_hmac_init(mac->hmac_ctx, NULL, 0) < 0 || ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 || ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 || ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0) return SSH_ERR_LIBCRYPTO_ERROR; break; case SSH_UMAC: POKE_U64(nonce, seqno); umac_update(mac->umac_ctx, data, datalen); umac_final(mac->umac_ctx, u.m, nonce); break; case SSH_UMAC128: put_u64(nonce, seqno); umac128_update(mac->umac_ctx, data, datalen); umac128_final(mac->umac_ctx, u.m, nonce); break; default: return SSH_ERR_INVALID_ARGUMENT; } if (digest != NULL) { if (dlen > mac->mac_len) dlen = mac->mac_len; memcpy(digest, u.m, dlen); } 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) { if (mac->type == SSH_UMAC) { if (mac->umac_ctx != NULL) umac_delete(mac->umac_ctx); } else if (mac->type == SSH_UMAC128) { if (mac->umac_ctx != NULL) umac128_delete(mac->umac_ctx); } else if (mac->hmac_ctx != NULL) ssh_hmac_free(mac->hmac_ctx); mac->hmac_ctx = NULL; mac->umac_ctx = NULL; } /* XXX copied from ciphers_valid */ #define MAC_SEP "," int mac_valid(const char *names) { char *maclist, *cp, *p; if (names == NULL || strcmp(names, "") == 0) return 0; if ((maclist = cp = strdup(names)) == NULL) return 0; for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0'; (p = strsep(&cp, MAC_SEP))) { if (mac_setup(NULL, p) < 0) { free(maclist); return 0; } } free(maclist); return 1; } openssh-10.0p1/PaxHeaders.10889/mac.h100644 001750 001750 0000000003614775415623 0014065xustar0030 atime=1744182234.581860772 openssh-10.0p1/mac.h010064400017500001750000000037251477541562300124570ustar00djmdjm/* $OpenBSD: mac.h,v 1.10 2016/07/08 03:44:42 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. */ #ifndef SSHMAC_H #define SSHMAC_H #include struct sshmac { char *name; int enabled; u_int mac_len; u_char *key; u_int key_len; int type; int etm; /* Encrypt-then-MAC */ struct ssh_hmac_ctx *hmac_ctx; struct umac_ctx *umac_ctx; }; int mac_valid(const char *); char *mac_alg_list(char); 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 */ openssh-10.0p1/PaxHeaders.10889/match.c100644 001750 001750 0000000003614775415623 0014414xustar0030 atime=1744182234.581860772 openssh-10.0p1/match.c010064400017500001750000000231541477541562300130040ustar00djmdjm/* $OpenBSD: match.c,v 1.45 2024/09/06 02:30:44 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Simple pattern matching, with '*' and '?' as wildcards. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include "xmalloc.h" #include "match.h" #include "misc.h" /* * Returns true if the given string matches the pattern (which may contain ? * and * as wildcards), and zero if it does not match. */ int match_pattern(const char *s, const char *pattern) { for (;;) { /* If at end of pattern, accept if also at end of string. */ if (!*pattern) return !*s; if (*pattern == '*') { /* Skip this and any consecutive asterisks. */ while (*pattern == '*') 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 != '?' && *pattern != *s) return 0; /* Move to the next character, both in string and in pattern. */ s++; pattern++; } /* NOTREACHED */ } /* * 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 match_pattern_list(const char *string, const char *pattern, int dolower) { 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] = dolower && isupper((u_char)pattern[i]) ? tolower((u_char)pattern[i]) : 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; } /* 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 * indicate negation). Returns -1 if negation matches, 1 if there is * a positive match, 0 if there is no match at all. */ int match_hostname(const char *host, const char *pattern) { char *hostcopy = xstrdup(host); int r; lowercase(hostcopy); r = match_pattern_list(hostcopy, pattern, 1); free(hostcopy); return r; } /* * returns 0 if we get a negative match for the hostname or the ip * or if we get no match at all. returns -1 on error, or 1 on * successful match. */ int match_host_and_ip(const char *host, const char *ipaddr, const char *patterns) { int mhost, mip; if ((mip = addr_match_list(ipaddr, patterns)) == -2) 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)) == -1) return 0; /* no match at all */ if (mhost == 0 && mip == 0) return 0; return 1; } /* * 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, const char *pattern) { char *p, *pat; int ret; /* test mode */ if (user == NULL && host == NULL && ipaddr == NULL) { if ((p = strrchr(pattern, '@')) != NULL && match_host_and_ip(NULL, NULL, p + 1) < 0) return -1; return 0; } if (user == NULL) return 0; /* shouldn't happen */ if (strrchr(pattern, '@') == NULL) return match_pattern(user, pattern); pat = xstrdup(pattern); p = strrchr(pat, '@'); *p++ = '\0'; if ((ret = match_pattern(user, pat)) == 1) ret = match_host_and_ip(host, ipaddr, p); free(pat); return ret; } /* * Returns first item from client-list that is also supported by server-list, * caller must free the returned string. */ #define MAX_PROP 40 #define SEP "," char * match_list(const char *client, const char *server, u_int *next) { char *sproposals[MAX_PROP]; char *c, *s, *p, *ret, *cp, *sp; int i, j, nproposals; c = cp = xstrdup(client); s = sp = xstrdup(server); for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0'; (p = strsep(&sp, SEP)), i++) { if (i < MAX_PROP) sproposals[i] = p; else break; } nproposals = i; for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0'; (p = strsep(&cp, SEP)), i++) { for (j = 0; j < nproposals; j++) { if (strcmp(p, sproposals[j]) == 0) { ret = xstrdup(p); if (next != NULL) *next = (cp == NULL) ? strlen(c) : (u_int)(cp - c); free(c); free(s); return ret; } } } if (next != NULL) *next = strlen(c); free(c); free(s); return NULL; } /* * Filter proposal using pattern-list filter. * "denylist" determines sense of filter: * non-zero indicates that items matching filter should be excluded. * zero indicates that only items matching filter should be included. * returns NULL on allocation error, otherwise caller must free result. */ static char * filter_list(const char *proposal, const char *filter, int denylist) { 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 ((denylist && r != 1) || (!denylist && 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_denylist(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_allowlist(const char *proposal, const char *filter) { return filter_list(proposal, filter, 0); } openssh-10.0p1/PaxHeaders.10889/match.h100644 001750 001750 0000000003614775415623 0014421xustar0030 atime=1744182234.581860772 openssh-10.0p1/match.h010064400017500001750000000023431477541562300130060ustar00djmdjm/* $OpenBSD: match.h,v 1.20 2020/07/05 23:59:45 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef MATCH_H #define MATCH_H int match_pattern(const char *, const char *); 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_denylist(const char *, const char *); char *match_filter_allowlist(const char *, const char *); /* addrmatch.c */ int addr_match_list(const char *, const char *); int addr_match_cidr_list(const char *, const char *); #endif openssh-10.0p1/PaxHeaders.10889/mdoc2man.awk100644 001750 001750 0000000003614775415623 0015360xustar0030 atime=1744182234.581860772 openssh-10.0p1/mdoc2man.awk010064400017500001750000000206231477541562300137460ustar00djmdjm#!/usr/bin/awk # # Version history: # v4+ Adapted for OpenSSH Portable (see cvs Id and history) # v3, I put the program under a proper license # Dan Nelson added .An, .Aq and fixed a typo # v2, fixed to work on GNU awk --posix and MacOS X # v1, first attempt, didn't work on MacOS X # # Copyright (c) 2003 Peter Stuge # # 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. BEGIN { optlist=0 oldoptlist=0 nospace=0 synopsis=0 reference=0 block=0 ext=0 extopt=0 literal=0 prenl=0 breakw=0 line="" } function wtail() { retval="" while(w0;i--) { add(refauthors[i]) if(i>1) add(", ") } if(nrefauthors>1) add(" and ") if(nrefauthors>0) add(refauthors[0] ", ") add("\\fI" reftitle "\\fP") if(length(refissue)) add(", " refissue) if(length(refreport)) { add(", " refreport) } if(length(refdate)) add(", " refdate) if(length(refopt)) add(", " refopt) add(".") reference=0 } else if(reference) { if(match(words[w],"^%A$")) { refauthors[nrefauthors++]=wtail() } if(match(words[w],"^%T$")) { reftitle=wtail() sub("^\"","",reftitle) sub("\"$","",reftitle) } if(match(words[w],"^%N$")) { refissue=wtail() } if(match(words[w],"^%D$")) { refdate=wtail() } if(match(words[w],"^%O$")) { refopt=wtail() } if(match(words[w],"^%R$")) { refreport=wtail() } } else if(match(words[w],"^Nm$")) { if(synopsis) { add(".br") prenl++ } n=words[++w] if(!length(name)) name=n if(!length(n)) n=name add("\\fB" n "\\fP") if(!nospace&&match(words[w+1],"^[\\.,]")) nospace=1 } else if(match(words[w],"^Nd$")) { add("\\- " wtail()) } else if(match(words[w],"^Fl$")) { add("\\fB\\-" words[++w] "\\fP") if(!nospace&&match(words[w+1],"^[\\.,]")) nospace=1 } else if(match(words[w],"^Ar$")) { add("\\fI") if(w==nwords) add("file ...\\fP") else { add(words[++w] "\\fP") while(match(words[w+1],"^\\|$")) add(OFS words[++w] " \\fI" words[++w] "\\fP") } if(!nospace&&match(words[w+1],"^[\\.,]")) nospace=1 } else if(match(words[w],"^Cm$")) { add("\\fB" words[++w] "\\fP") while(w") for(;option;option--) add("]") if(ext&&!extopt&&!match(line," $")) add(OFS) if(!ext&&!extopt&&length(line)) { print line prenl=0 line="" } } openssh-10.0p1/PaxHeaders.10889/misc.c100644 001750 001750 0000000003614775415623 0014253xustar0030 atime=1744182234.604320775 openssh-10.0p1/misc.c010064400017500001750000002060271477541562300126450ustar00djmdjm/* $OpenBSD: misc.c,v 1.198 2024/10/24 03:14:37 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005-2020 Damien Miller. All rights reserved. * Copyright (c) 2004 Henning Brauer * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBGEN_H # include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_NLIST_H #include #endif #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H # include #include #include #endif #ifdef SSH_TUN_OPENBSD #include #endif #include "xmalloc.h" #include "misc.h" #include "log.h" #include "ssh.h" #include "sshbuf.h" #include "ssherr.h" #include "platform.h" /* remove newline at end of string */ char * chop(char *s) { char *t = s; while (*t) { if (*t == '\n' || *t == '\r') { *t = '\0'; return s; } t++; } return s; } /* remove whitespace from end of string */ void rtrim(char *s) { size_t i; if ((i = strlen(s)) == 0) return; for (i--; i > 0; i--) { if (isspace((unsigned char)s[i])) s[i] = '\0'; } } /* * returns pointer to character after 'prefix' in 's' or otherwise NULL * if the prefix is not present. */ const char * strprefix(const char *s, const char *prefix, int ignorecase) { size_t prefixlen; if ((prefixlen = strlen(prefix)) == 0) return s; if (ignorecase) { if (strncasecmp(s, prefix, prefixlen) != 0) return NULL; } else { if (strncmp(s, prefix, prefixlen) != 0) return NULL; } return s + prefixlen; } /* set/unset filedescriptor to non-blocking */ int set_nonblock(int fd) { int val; val = fcntl(fd, F_GETFL); if (val == -1) { error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); return (-1); } if (val & O_NONBLOCK) { debug3("fd %d is O_NONBLOCK", fd); return (0); } debug2("fd %d setting O_NONBLOCK", fd); val |= O_NONBLOCK; if (fcntl(fd, F_SETFL, val) == -1) { debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, strerror(errno)); return (-1); } return (0); } int unset_nonblock(int fd) { int val; val = fcntl(fd, F_GETFL); if (val == -1) { error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); return (-1); } if (!(val & O_NONBLOCK)) { debug3("fd %d is not O_NONBLOCK", fd); return (0); } debug("fd %d clearing O_NONBLOCK", fd); val &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, val) == -1) { debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", fd, strerror(errno)); return (-1); } return (0); } const char * ssh_gai_strerror(int gaierr) { if (gaierr == EAI_SYSTEM && errno != 0) return strerror(errno); return gai_strerror(gaierr); } /* disable nagle on socket */ void set_nodelay(int fd) { int opt; socklen_t optlen; optlen = sizeof opt; if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); return; } if (opt == 1) { debug2("fd %d is TCP_NODELAY", fd); return; } opt = 1; debug2("fd %d setting TCP_NODELAY", fd); if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); } /* Allow local port reuse in TIME_WAIT */ int set_reuseaddr(int fd) { int on = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno)); return -1; } return 0; } /* Get/set routing domain */ char * get_rdomain(int fd) { #if defined(HAVE_SYS_GET_RDOMAIN) return sys_get_rdomain(fd); #elif defined(__OpenBSD__) int rtable; char *ret; socklen_t len = sizeof(rtable); if (getsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, &len) == -1) { error("Failed to get routing domain for fd %d: %s", fd, strerror(errno)); return NULL; } xasprintf(&ret, "%d", rtable); return ret; #else /* defined(__OpenBSD__) */ return NULL; #endif } int set_rdomain(int fd, const char *name) { #if defined(HAVE_SYS_SET_RDOMAIN) return sys_set_rdomain(fd, name); #elif defined(__OpenBSD__) int rtable; const char *errstr; if (name == NULL) return 0; /* default table */ rtable = (int)strtonum(name, 0, 255, &errstr); if (errstr != NULL) { /* Shouldn't happen */ error("Invalid routing domain \"%s\": %s", name, errstr); return -1; } if (setsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, sizeof(rtable)) == -1) { error("Failed to set routing domain %d on fd %d: %s", rtable, fd, strerror(errno)); return -1; } return 0; #else /* defined(__OpenBSD__) */ error("Setting routing domain is not supported on this platform"); return -1; #endif } int get_sock_af(int fd) { struct sockaddr_storage to; socklen_t tolen = sizeof(to); memset(&to, 0, sizeof(to)); if (getsockname(fd, (struct sockaddr *)&to, &tolen) == -1) return -1; #ifdef IPV4_IN_IPV6 if (to.ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) return AF_INET; #endif return to.ss_family; } void set_sock_tos(int fd, int tos) { #ifndef IP_TOS_IS_BROKEN int af; switch ((af = get_sock_af(fd))) { case -1: /* assume not a socket */ break; case AF_INET: # ifdef IP_TOS debug3_f("set socket %d IP_TOS 0x%02x", fd, tos); if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) { error("setsockopt socket %d IP_TOS %d: %s", fd, tos, strerror(errno)); } # endif /* IP_TOS */ break; case AF_INET6: # ifdef IPV6_TCLASS debug3_f("set socket %d IPV6_TCLASS 0x%02x", fd, tos); if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) == -1) { error("setsockopt socket %d IPV6_TCLASS %d: %s", fd, tos, strerror(errno)); } # endif /* IPV6_TCLASS */ break; default: debug2_f("unsupported socket family %d", af); break; } #endif /* IP_TOS_IS_BROKEN */ } /* * Wait up to *timeoutp milliseconds for events on fd. Updates * *timeoutp with time remaining. * Returns 0 if fd ready or -1 on timeout or error (see errno). */ static int waitfd(int fd, int *timeoutp, short events, volatile sig_atomic_t *stop) { struct pollfd pfd; struct timespec timeout; int oerrno, r; sigset_t nsigset, osigset; if (timeoutp && *timeoutp == -1) timeoutp = NULL; pfd.fd = fd; pfd.events = events; ptimeout_init(&timeout); if (timeoutp != NULL) ptimeout_deadline_ms(&timeout, *timeoutp); if (stop != NULL) sigfillset(&nsigset); for (; timeoutp == NULL || *timeoutp >= 0;) { if (stop != NULL) { sigprocmask(SIG_BLOCK, &nsigset, &osigset); if (*stop) { sigprocmask(SIG_SETMASK, &osigset, NULL); errno = EINTR; return -1; } } r = ppoll(&pfd, 1, ptimeout_get_tsp(&timeout), stop != NULL ? &osigset : NULL); oerrno = errno; if (stop != NULL) sigprocmask(SIG_SETMASK, &osigset, NULL); if (timeoutp) *timeoutp = ptimeout_get_ms(&timeout); errno = oerrno; if (r > 0) return 0; else if (r == -1 && errno != EAGAIN && errno != EINTR) return -1; else if (r == 0) break; } /* timeout */ errno = ETIMEDOUT; return -1; } /* * Wait up to *timeoutp milliseconds for fd to be readable. Updates * *timeoutp with time remaining. * Returns 0 if fd ready or -1 on timeout or error (see errno). */ int waitrfd(int fd, int *timeoutp, volatile sig_atomic_t *stop) { return waitfd(fd, timeoutp, POLLIN, stop); } /* * Attempt a non-blocking connect(2) to the specified address, waiting up to * *timeoutp milliseconds for the connection to complete. If the timeout is * <=0, then wait indefinitely. * * Returns 0 on success or -1 on failure. */ int timeout_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen, int *timeoutp) { int optval = 0; socklen_t optlen = sizeof(optval); /* No timeout: just do a blocking connect() */ if (timeoutp == NULL || *timeoutp <= 0) return connect(sockfd, serv_addr, addrlen); set_nonblock(sockfd); for (;;) { if (connect(sockfd, serv_addr, addrlen) == 0) { /* Succeeded already? */ unset_nonblock(sockfd); return 0; } else if (errno == EINTR) continue; else if (errno != EINPROGRESS) return -1; break; } if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT, NULL) == -1) return -1; /* Completed or failed */ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { debug("getsockopt: %s", strerror(errno)); return -1; } if (optval != 0) { errno = optval; return -1; } unset_nonblock(sockfd); return 0; } /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" #define QUOTE "\"" /* return next token in configuration line */ static char * strdelim_internal(char **s, int split_equals) { char *old; int wspace = 0; if (*s == NULL) return NULL; old = *s; *s = strpbrk(*s, split_equals ? WHITESPACE QUOTE "=" : WHITESPACE QUOTE); if (*s == NULL) return (old); if (*s[0] == '\"') { memmove(*s, *s + 1, strlen(*s)); /* move nul too */ /* Find matching quote */ if ((*s = strpbrk(*s, QUOTE)) == NULL) { return (NULL); /* no matching quote */ } else { *s[0] = '\0'; *s += strspn(*s + 1, WHITESPACE) + 1; return (old); } } /* Allow only one '=' to be skipped */ if (split_equals && *s[0] == '=') wspace = 1; *s[0] = '\0'; /* Skip any extra whitespace after first token */ *s += strspn(*s + 1, WHITESPACE) + 1; if (split_equals && *s[0] == '=' && !wspace) *s += strspn(*s + 1, WHITESPACE) + 1; return (old); } /* * Return next token in configuration line; splts on whitespace or a * single '=' character. */ char * strdelim(char **s) { return strdelim_internal(s, 1); } /* * Return next token in configuration line; splts on whitespace only. */ char * strdelimw(char **s) { return strdelim_internal(s, 0); } struct passwd * pwcopy(struct passwd *pw) { struct passwd *copy = xcalloc(1, sizeof(*copy)); copy->pw_name = xstrdup(pw->pw_name); copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd); #ifdef HAVE_STRUCT_PASSWD_PW_GECOS copy->pw_gecos = xstrdup(pw->pw_gecos); #endif copy->pw_uid = pw->pw_uid; copy->pw_gid = pw->pw_gid; #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE copy->pw_expire = pw->pw_expire; #endif #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE copy->pw_change = pw->pw_change; #endif #ifdef HAVE_STRUCT_PASSWD_PW_CLASS copy->pw_class = xstrdup(pw->pw_class); #endif copy->pw_dir = xstrdup(pw->pw_dir); copy->pw_shell = xstrdup(pw->pw_shell); return copy; } /* * Convert ASCII string to TCP/IP port number. * Port must be >=0 and <=65535. * Return -1 if invalid. */ int a2port(const char *s) { struct servent *se; long long port; const char *errstr; port = strtonum(s, 0, 65535, &errstr); if (errstr == NULL) return (int)port; if ((se = getservbyname(s, "tcp")) != NULL) return ntohs(se->s_port); return -1; } int a2tun(const char *s, int *remote) { const char *errstr = NULL; char *sp, *ep; int tun; if (remote != NULL) { *remote = SSH_TUNID_ANY; sp = xstrdup(s); if ((ep = strchr(sp, ':')) == NULL) { free(sp); return (a2tun(s, NULL)); } ep[0] = '\0'; ep++; *remote = a2tun(ep, NULL); tun = a2tun(sp, NULL); free(sp); return (*remote == SSH_TUNID_ERR ? *remote : tun); } if (strcasecmp(s, "any") == 0) return (SSH_TUNID_ANY); tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); if (errstr != NULL) return (SSH_TUNID_ERR); return (tun); } #define SECONDS 1 #define MINUTES (SECONDS * 60) #define HOURS (MINUTES * 60) #define DAYS (HOURS * 24) #define WEEKS (DAYS * 7) static char * scandigits(char *s) { while (isdigit((unsigned char)*s)) s++; return s; } /* * Convert a time string into seconds; format is * a sequence of: * time[qualifier] * * Valid time qualifiers are: * seconds * s|S seconds * m|M minutes * h|H hours * d|D days * w|W weeks * * Examples: * 90m 90 minutes * 1h30m 90 minutes * 2d 2 days * 1w 1 week * * Return -1 if time string is invalid. */ int convtime(const char *s) { int secs, total = 0, multiplier; char *p, *os, *np, c = 0; const char *errstr; if (s == NULL || *s == '\0') return -1; p = os = strdup(s); /* deal with const */ if (os == NULL) return -1; while (*p) { np = scandigits(p); if (np) { c = *np; *np = '\0'; } secs = (int)strtonum(p, 0, INT_MAX, &errstr); if (errstr) goto fail; *np = c; multiplier = 1; switch (c) { case '\0': np--; /* back up */ break; case 's': case 'S': break; case 'm': case 'M': multiplier = MINUTES; break; case 'h': case 'H': multiplier = HOURS; break; case 'd': case 'D': multiplier = DAYS; break; case 'w': case 'W': multiplier = WEEKS; break; default: goto fail; } if (secs > INT_MAX / multiplier) goto fail; secs *= multiplier; if (total > INT_MAX - secs) goto fail; total += secs; if (total < 0) goto fail; p = ++np; } free(os); return total; fail: free(os); return -1; } #define TF_BUFS 8 #define TF_LEN 9 const char * fmt_timeframe(time_t t) { char *buf; static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ static int idx = 0; unsigned int sec, min, hrs, day; unsigned long long week; buf = tfbuf[idx++]; if (idx == TF_BUFS) idx = 0; week = t; sec = week % 60; week /= 60; min = week % 60; week /= 60; hrs = week % 24; week /= 24; day = week % 7; week /= 7; if (week > 0) snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs); else if (day > 0) snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); else snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); return (buf); } /* * Returns a standardized host+port identifier string. * Caller must free returned string. */ char * put_host_port(const char *host, u_short port) { char *hoststr; if (port == 0 || port == SSH_DEFAULT_PORT) return(xstrdup(host)); if (asprintf(&hoststr, "[%s]:%d", host, (int)port) == -1) fatal("put_host_port: asprintf: %s", strerror(errno)); debug3("put_host_port: %s", hoststr); return hoststr; } /* * Search for next delimiter between hostnames/addresses and ports. * Argument may be modified (for termination). * Returns *cp if parsing succeeds. * *cp is set to the start of the next field, if one was found. * The delimiter char, if present, is stored in delim. * If this is the last field, *cp is set to NULL. */ char * hpdelim2(char **cp, char *delim) { char *s, *old; if (cp == NULL || *cp == NULL) return NULL; old = s = *cp; if (*s == '[') { if ((s = strchr(s, ']')) == NULL) return NULL; else s++; } else if ((s = strpbrk(s, ":/")) == NULL) s = *cp + strlen(*cp); /* skip to end (see first case below) */ switch (*s) { case '\0': *cp = NULL; /* no more fields*/ break; case ':': case '/': if (delim != NULL) *delim = *s; *s = '\0'; /* terminate */ *cp = s + 1; break; default: return NULL; } return old; } /* The common case: only accept colon as delimiter. */ char * hpdelim(char **cp) { char *r, delim = '\0'; r = hpdelim2(cp, &delim); if (delim == '/') return NULL; return r; } char * cleanhostname(char *host) { if (*host == '[' && host[strlen(host) - 1] == ']') { host[strlen(host) - 1] = '\0'; return (host + 1); } else return host; } char * colon(char *cp) { int flag = 0; if (*cp == ':') /* Leading colon is part of file name. */ return NULL; if (*cp == '[') flag = 1; for (; *cp; ++cp) { if (*cp == '@' && *(cp+1) == '[') flag = 1; if (*cp == ']' && *(cp+1) == ':' && flag) return (cp+1); if (*cp == ':' && !flag) return (cp); if (*cp == '/') return NULL; } return NULL; } /* * Parse a [user@]host:[path] string. * Caller must free returned user, host and path. * Any of the pointer return arguments may be NULL (useful for syntax checking). * If user was not specified then *userp will be set to NULL. * If host was not specified then *hostp will be set to NULL. * If path was not specified then *pathp will be set to ".". * Returns 0 on success, -1 on failure. */ int parse_user_host_path(const char *s, char **userp, char **hostp, char **pathp) { char *user = NULL, *host = NULL, *path = NULL; char *sdup, *tmp; int ret = -1; if (userp != NULL) *userp = NULL; if (hostp != NULL) *hostp = NULL; if (pathp != NULL) *pathp = NULL; sdup = xstrdup(s); /* Check for remote syntax: [user@]host:[path] */ if ((tmp = colon(sdup)) == NULL) goto out; /* Extract optional path */ *tmp++ = '\0'; if (*tmp == '\0') tmp = "."; path = xstrdup(tmp); /* Extract optional user and mandatory host */ tmp = strrchr(sdup, '@'); if (tmp != NULL) { *tmp++ = '\0'; host = xstrdup(cleanhostname(tmp)); if (*sdup != '\0') user = xstrdup(sdup); } else { host = xstrdup(cleanhostname(sdup)); user = NULL; } /* Success */ if (userp != NULL) { *userp = user; user = NULL; } if (hostp != NULL) { *hostp = host; host = NULL; } if (pathp != NULL) { *pathp = path; path = NULL; } ret = 0; out: free(sdup); free(user); free(host); free(path); return ret; } /* * Parse a [user@]host[:port] string. * Caller must free returned user and host. * Any of the pointer return arguments may be NULL (useful for syntax checking). * If user was not specified then *userp will be set to NULL. * If port was not specified then *portp will be -1. * Returns 0 on success, -1 on failure. */ int parse_user_host_port(const char *s, char **userp, char **hostp, int *portp) { char *sdup, *cp, *tmp; char *user = NULL, *host = NULL; int port = -1, ret = -1; if (userp != NULL) *userp = NULL; if (hostp != NULL) *hostp = NULL; if (portp != NULL) *portp = -1; if ((sdup = tmp = strdup(s)) == NULL) return -1; /* Extract optional username */ if ((cp = strrchr(tmp, '@')) != NULL) { *cp = '\0'; if (*tmp == '\0') goto out; if ((user = strdup(tmp)) == NULL) goto out; tmp = cp + 1; } /* Extract mandatory hostname */ if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0') goto out; host = xstrdup(cleanhostname(cp)); /* Convert and verify optional port */ if (tmp != NULL && *tmp != '\0') { if ((port = a2port(tmp)) <= 0) goto out; } /* Success */ if (userp != NULL) { *userp = user; user = NULL; } if (hostp != NULL) { *hostp = host; host = NULL; } if (portp != NULL) *portp = port; ret = 0; out: free(sdup); free(user); free(host); return ret; } /* * Converts a two-byte hex string to decimal. * Returns the decimal value or -1 for invalid input. */ static int hexchar(const char *s) { unsigned char result[2]; int i; for (i = 0; i < 2; i++) { if (s[i] >= '0' && s[i] <= '9') result[i] = (unsigned char)(s[i] - '0'); else if (s[i] >= 'a' && s[i] <= 'f') result[i] = (unsigned char)(s[i] - 'a') + 10; else if (s[i] >= 'A' && s[i] <= 'F') result[i] = (unsigned char)(s[i] - 'A') + 10; else return -1; } return (result[0] << 4) | result[1]; } /* * Decode an url-encoded string. * Returns a newly allocated string on success or NULL on failure. */ static char * urldecode(const char *src) { char *ret, *dst; int ch; size_t srclen; if ((srclen = strlen(src)) >= SIZE_MAX) fatal_f("input too large"); ret = xmalloc(srclen + 1); for (dst = ret; *src != '\0'; src++) { switch (*src) { case '+': *dst++ = ' '; break; case '%': if (!isxdigit((unsigned char)src[1]) || !isxdigit((unsigned char)src[2]) || (ch = hexchar(src + 1)) == -1) { free(ret); return NULL; } *dst++ = ch; src += 2; break; default: *dst++ = *src; break; } } *dst = '\0'; return ret; } /* * Parse an (scp|ssh|sftp)://[user@]host[:port][/path] URI. * See https://tools.ietf.org/html/draft-ietf-secsh-scp-sftp-ssh-uri-04 * Either user or path may be url-encoded (but not host or port). * Caller must free returned user, host and path. * Any of the pointer return arguments may be NULL (useful for syntax checking) * but the scheme must always be specified. * If user was not specified then *userp will be set to NULL. * If port was not specified then *portp will be -1. * If path was not specified then *pathp will be set to NULL. * Returns 0 on success, 1 if non-uri/wrong scheme, -1 on error/invalid uri. */ int parse_uri(const char *scheme, const char *uri, char **userp, char **hostp, int *portp, char **pathp) { char *uridup, *cp, *tmp, ch; char *user = NULL, *host = NULL, *path = NULL; int port = -1, ret = -1; size_t len; len = strlen(scheme); if (strncmp(uri, scheme, len) != 0 || strncmp(uri + len, "://", 3) != 0) return 1; uri += len + 3; if (userp != NULL) *userp = NULL; if (hostp != NULL) *hostp = NULL; if (portp != NULL) *portp = -1; if (pathp != NULL) *pathp = NULL; uridup = tmp = xstrdup(uri); /* Extract optional ssh-info (username + connection params) */ if ((cp = strchr(tmp, '@')) != NULL) { char *delim; *cp = '\0'; /* Extract username and connection params */ if ((delim = strchr(tmp, ';')) != NULL) { /* Just ignore connection params for now */ *delim = '\0'; } if (*tmp == '\0') { /* Empty username */ goto out; } if ((user = urldecode(tmp)) == NULL) goto out; tmp = cp + 1; } /* Extract mandatory hostname */ if ((cp = hpdelim2(&tmp, &ch)) == NULL || *cp == '\0') goto out; host = xstrdup(cleanhostname(cp)); if (!valid_domain(host, 0, NULL)) goto out; if (tmp != NULL && *tmp != '\0') { if (ch == ':') { /* Convert and verify port. */ if ((cp = strchr(tmp, '/')) != NULL) *cp = '\0'; if ((port = a2port(tmp)) <= 0) goto out; tmp = cp ? cp + 1 : NULL; } if (tmp != NULL && *tmp != '\0') { /* Extract optional path */ if ((path = urldecode(tmp)) == NULL) goto out; } } /* Success */ if (userp != NULL) { *userp = user; user = NULL; } if (hostp != NULL) { *hostp = host; host = NULL; } if (portp != NULL) *portp = port; if (pathp != NULL) { *pathp = path; path = NULL; } ret = 0; out: free(uridup); free(user); free(host); free(path); return ret; } /* function to assist building execv() arguments */ void addargs(arglist *args, char *fmt, ...) { va_list ap; char *cp; u_int nalloc; int r; va_start(ap, fmt); r = vasprintf(&cp, fmt, ap); va_end(ap); if (r == -1) fatal_f("argument too long"); nalloc = args->nalloc; if (args->list == NULL) { nalloc = 32; args->num = 0; } else if (args->num > (256 * 1024)) fatal_f("too many arguments"); else if (args->num >= args->nalloc) fatal_f("arglist corrupt"); else if (args->num+2 >= nalloc) nalloc *= 2; args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *)); args->nalloc = nalloc; args->list[args->num++] = cp; args->list[args->num] = NULL; } void replacearg(arglist *args, u_int which, char *fmt, ...) { va_list ap; char *cp; int r; va_start(ap, fmt); r = vasprintf(&cp, fmt, ap); va_end(ap); if (r == -1) fatal_f("argument too long"); if (args->list == NULL || args->num >= args->nalloc) fatal_f("arglist corrupt"); if (which >= args->num) fatal_f("tried to replace invalid arg %d >= %d", which, args->num); free(args->list[which]); args->list[which] = cp; } void freeargs(arglist *args) { u_int i; if (args == NULL) return; if (args->list != NULL && args->num < args->nalloc) { for (i = 0; i < args->num; i++) free(args->list[i]); free(args->list); } args->nalloc = args->num = 0; args->list = NULL; } /* * Expands tildes in the file name. Returns data allocated by xmalloc. * Warning: this calls getpw*. */ int tilde_expand(const char *filename, uid_t uid, char **retp) { char *ocopy = NULL, *copy, *s = NULL; const char *path = NULL, *user = NULL; struct passwd *pw; size_t len; int ret = -1, r, slash; *retp = NULL; if (*filename != '~') { *retp = xstrdup(filename); return 0; } ocopy = copy = xstrdup(filename + 1); if (*copy == '\0') /* ~ */ path = NULL; else if (*copy == '/') { copy += strspn(copy, "/"); if (*copy == '\0') path = NULL; /* ~/ */ else path = copy; /* ~/path */ } else { user = copy; if ((path = strchr(copy, '/')) != NULL) { copy[path - copy] = '\0'; path++; path += strspn(path, "/"); if (*path == '\0') /* ~user/ */ path = NULL; /* else ~user/path */ } /* else ~user */ } if (user != NULL) { if ((pw = getpwnam(user)) == NULL) { error_f("No such user %s", user); goto out; } } else if ((pw = getpwuid(uid)) == NULL) { error_f("No such uid %ld", (long)uid); goto out; } /* Make sure directory has a trailing '/' */ slash = (len = strlen(pw->pw_dir)) == 0 || pw->pw_dir[len - 1] != '/'; if ((r = xasprintf(&s, "%s%s%s", pw->pw_dir, slash ? "/" : "", path != NULL ? path : "")) <= 0) { error_f("xasprintf failed"); goto out; } if (r >= PATH_MAX) { error_f("Path too long"); goto out; } /* success */ ret = 0; *retp = s; s = NULL; out: free(s); free(ocopy); return ret; } char * tilde_expand_filename(const char *filename, uid_t uid) { char *ret; if (tilde_expand(filename, uid, &ret) != 0) cleanup_exit(255); return ret; } /* * Expand a string with a set of %[char] escapes and/or ${ENVIRONMENT} * substitutions. A number of escapes may be specified as * (char *escape_chars, char *replacement) pairs. The list must be terminated * by a NULL escape_char. Returns replaced string in memory allocated by * xmalloc which the caller must free. */ static char * vdollar_percent_expand(int *parseerror, int dollar, int percent, const char *string, va_list ap) { #define EXPAND_MAX_KEYS 64 u_int num_keys = 0, i; struct { const char *key; const char *repl; } keys[EXPAND_MAX_KEYS]; struct sshbuf *buf; int r, missingvar = 0; char *ret = NULL, *var, *varend, *val; size_t len; if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (parseerror == NULL) fatal_f("null parseerror arg"); *parseerror = 1; /* Gather keys if we're doing percent expansion. */ if (percent) { for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { keys[num_keys].key = va_arg(ap, char *); if (keys[num_keys].key == NULL) break; keys[num_keys].repl = va_arg(ap, char *); if (keys[num_keys].repl == NULL) { fatal_f("NULL replacement for token %s", keys[num_keys].key); } } if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) fatal_f("too many keys"); if (num_keys == 0) fatal_f("percent expansion without token list"); } /* Expand string */ for (i = 0; *string != '\0'; string++) { /* Optionally process ${ENVIRONMENT} expansions. */ if (dollar && string[0] == '$' && string[1] == '{') { string += 2; /* skip over '${' */ if ((varend = strchr(string, '}')) == NULL) { error_f("environment variable '%s' missing " "closing '}'", string); goto out; } len = varend - string; if (len == 0) { error_f("zero-length environment variable"); goto out; } var = xmalloc(len + 1); (void)strlcpy(var, string, len + 1); if ((val = getenv(var)) == NULL) { error_f("env var ${%s} has no value", var); missingvar = 1; } else { debug3_f("expand ${%s} -> '%s'", var, val); if ((r = sshbuf_put(buf, val, strlen(val))) !=0) fatal_fr(r, "sshbuf_put ${}"); } free(var); string += len; continue; } /* * Process percent expansions if we have a list of TOKENs. * If we're not doing percent expansion everything just gets * appended here. */ if (*string != '%' || !percent) { append: if ((r = sshbuf_put_u8(buf, *string)) != 0) fatal_fr(r, "sshbuf_put_u8 %%"); continue; } string++; /* %% case */ if (*string == '%') goto append; if (*string == '\0') { error_f("invalid format"); goto out; } for (i = 0; i < num_keys; i++) { if (strchr(keys[i].key, *string) != NULL) { if ((r = sshbuf_put(buf, keys[i].repl, strlen(keys[i].repl))) != 0) fatal_fr(r, "sshbuf_put %%-repl"); break; } } if (i >= num_keys) { error_f("unknown key %%%c", *string); goto out; } } if (!missingvar && (ret = sshbuf_dup_string(buf)) == NULL) fatal_f("sshbuf_dup_string failed"); *parseerror = 0; out: sshbuf_free(buf); return *parseerror ? NULL : ret; #undef EXPAND_MAX_KEYS } /* * Expand only environment variables. * Note that although this function is variadic like the other similar * functions, any such arguments will be unused. */ char * dollar_expand(int *parseerr, const char *string, ...) { char *ret; int err; va_list ap; va_start(ap, string); ret = vdollar_percent_expand(&err, 1, 0, string, ap); va_end(ap); if (parseerr != NULL) *parseerr = err; return ret; } /* * Returns expanded string or NULL if a specified environment variable is * not defined, or calls fatal if the string is invalid. */ char * percent_expand(const char *string, ...) { char *ret; int err; va_list ap; va_start(ap, string); ret = vdollar_percent_expand(&err, 0, 1, string, ap); va_end(ap); if (err) fatal_f("failed"); return ret; } /* * Returns expanded string or NULL if a specified environment variable is * not defined, or calls fatal if the string is invalid. */ char * percent_dollar_expand(const char *string, ...) { char *ret; int err; va_list ap; va_start(ap, string); ret = vdollar_percent_expand(&err, 1, 1, string, ap); va_end(ap); if (err) fatal_f("failed"); return ret; } int tun_open(int tun, int mode, char **ifname) { #if defined(CUSTOM_SYS_TUN_OPEN) return (sys_tun_open(tun, mode, ifname)); #elif defined(SSH_TUN_OPENBSD) struct ifreq ifr; char name[100]; int fd = -1, sock; const char *tunbase = "tun"; if (ifname != NULL) *ifname = NULL; if (mode == SSH_TUNMODE_ETHERNET) tunbase = "tap"; /* Open the tunnel device */ if (tun <= SSH_TUNID_MAX) { snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); fd = open(name, O_RDWR); } else if (tun == SSH_TUNID_ANY) { for (tun = 100; tun >= 0; tun--) { snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); if ((fd = open(name, O_RDWR)) >= 0) break; } } else { debug_f("invalid tunnel %u", tun); return -1; } if (fd == -1) { debug_f("%s open: %s", name, strerror(errno)); return -1; } debug_f("%s mode %d fd %d", name, mode, fd); /* Bring interface up if it is not already */ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) goto failed; if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { debug_f("get interface %s flags: %s", ifr.ifr_name, strerror(errno)); goto failed; } if (!(ifr.ifr_flags & IFF_UP)) { ifr.ifr_flags |= IFF_UP; if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { debug_f("activate interface %s: %s", ifr.ifr_name, strerror(errno)); goto failed; } } if (ifname != NULL) *ifname = xstrdup(ifr.ifr_name); close(sock); return fd; failed: if (fd >= 0) close(fd); if (sock >= 0) close(sock); return -1; #else error("Tunnel interfaces are not supported on this platform"); return (-1); #endif } void sanitise_stdfd(void) { int nullfd, dupfd; if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { fprintf(stderr, "Couldn't open /dev/null: %s\n", strerror(errno)); exit(1); } while (++dupfd <= STDERR_FILENO) { /* Only populate closed fds. */ if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { if (dup2(nullfd, dupfd) == -1) { fprintf(stderr, "dup2: %s\n", strerror(errno)); exit(1); } } } if (nullfd > STDERR_FILENO) close(nullfd); } char * tohex(const void *vp, size_t l) { const u_char *p = (const u_char *)vp; char b[3], *r; size_t i, hl; if (l > 65536) return xstrdup("tohex: length > 65536"); hl = l * 2 + 1; r = xcalloc(1, hl); for (i = 0; i < l; i++) { snprintf(b, sizeof(b), "%02x", p[i]); strlcat(r, b, hl); } return (r); } /* * Extend string *sp by the specified format. If *sp is not NULL (or empty), * then the separator 'sep' will be prepended before the formatted arguments. * Extended strings are heap allocated. */ void xextendf(char **sp, const char *sep, const char *fmt, ...) { va_list ap; char *tmp1, *tmp2; va_start(ap, fmt); xvasprintf(&tmp1, fmt, ap); va_end(ap); if (*sp == NULL || **sp == '\0') { free(*sp); *sp = tmp1; return; } xasprintf(&tmp2, "%s%s%s", *sp, sep == NULL ? "" : sep, tmp1); free(tmp1); free(*sp); *sp = tmp2; } u_int64_t get_u64(const void *vp) { const u_char *p = (const u_char *)vp; u_int64_t v; v = (u_int64_t)p[0] << 56; v |= (u_int64_t)p[1] << 48; v |= (u_int64_t)p[2] << 40; v |= (u_int64_t)p[3] << 32; v |= (u_int64_t)p[4] << 24; v |= (u_int64_t)p[5] << 16; v |= (u_int64_t)p[6] << 8; v |= (u_int64_t)p[7]; return (v); } u_int32_t get_u32(const void *vp) { const u_char *p = (const u_char *)vp; u_int32_t v; v = (u_int32_t)p[0] << 24; v |= (u_int32_t)p[1] << 16; v |= (u_int32_t)p[2] << 8; v |= (u_int32_t)p[3]; return (v); } u_int32_t get_u32_le(const void *vp) { const u_char *p = (const u_char *)vp; u_int32_t v; v = (u_int32_t)p[0]; v |= (u_int32_t)p[1] << 8; v |= (u_int32_t)p[2] << 16; v |= (u_int32_t)p[3] << 24; return (v); } u_int16_t get_u16(const void *vp) { const u_char *p = (const u_char *)vp; u_int16_t v; v = (u_int16_t)p[0] << 8; v |= (u_int16_t)p[1]; return (v); } void put_u64(void *vp, u_int64_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)(v >> 56) & 0xff; p[1] = (u_char)(v >> 48) & 0xff; p[2] = (u_char)(v >> 40) & 0xff; p[3] = (u_char)(v >> 32) & 0xff; p[4] = (u_char)(v >> 24) & 0xff; p[5] = (u_char)(v >> 16) & 0xff; p[6] = (u_char)(v >> 8) & 0xff; p[7] = (u_char)v & 0xff; } void put_u32(void *vp, u_int32_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)(v >> 24) & 0xff; p[1] = (u_char)(v >> 16) & 0xff; p[2] = (u_char)(v >> 8) & 0xff; p[3] = (u_char)v & 0xff; } void put_u32_le(void *vp, u_int32_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)v & 0xff; p[1] = (u_char)(v >> 8) & 0xff; p[2] = (u_char)(v >> 16) & 0xff; p[3] = (u_char)(v >> 24) & 0xff; } void put_u16(void *vp, u_int16_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)(v >> 8) & 0xff; p[1] = (u_char)v & 0xff; } void ms_subtract_diff(struct timeval *start, int *ms) { struct timeval diff, finish; monotime_tv(&finish); timersub(&finish, start, &diff); *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); } void ms_to_timespec(struct timespec *ts, int ms) { if (ms < 0) ms = 0; ts->tv_sec = ms / 1000; ts->tv_nsec = (ms % 1000) * 1000 * 1000; } void monotime_ts(struct timespec *ts) { struct timeval tv; #if defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_BOOTTIME) || \ defined(CLOCK_MONOTONIC) || defined(CLOCK_REALTIME)) static int gettime_failed = 0; if (!gettime_failed) { # ifdef CLOCK_BOOTTIME if (clock_gettime(CLOCK_BOOTTIME, ts) == 0) return; # endif /* CLOCK_BOOTTIME */ # ifdef CLOCK_MONOTONIC if (clock_gettime(CLOCK_MONOTONIC, ts) == 0) return; # endif /* CLOCK_MONOTONIC */ # ifdef CLOCK_REALTIME /* Not monotonic, but we're almost out of options here. */ if (clock_gettime(CLOCK_REALTIME, ts) == 0) return; # endif /* CLOCK_REALTIME */ debug3("clock_gettime: %s", strerror(errno)); gettime_failed = 1; } #endif /* HAVE_CLOCK_GETTIME && (BOOTTIME || MONOTONIC || REALTIME) */ gettimeofday(&tv, NULL); ts->tv_sec = tv.tv_sec; ts->tv_nsec = (long)tv.tv_usec * 1000; } void monotime_tv(struct timeval *tv) { struct timespec ts; monotime_ts(&ts); tv->tv_sec = ts.tv_sec; tv->tv_usec = ts.tv_nsec / 1000; } time_t monotime(void) { struct timespec ts; monotime_ts(&ts); return ts.tv_sec; } double monotime_double(void) { struct timespec ts; monotime_ts(&ts); return ts.tv_sec + ((double)ts.tv_nsec / 1000000000); } void bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) { bw->buflen = buflen; bw->rate = kbps; bw->thresh = buflen; bw->lamt = 0; timerclear(&bw->bwstart); timerclear(&bw->bwend); } /* Callback from read/write loop to insert bandwidth-limiting delays */ void bandwidth_limit(struct bwlimit *bw, size_t read_len) { u_int64_t waitlen; struct timespec ts, rm; bw->lamt += read_len; if (!timerisset(&bw->bwstart)) { monotime_tv(&bw->bwstart); return; } if (bw->lamt < bw->thresh) return; monotime_tv(&bw->bwend); timersub(&bw->bwend, &bw->bwstart, &bw->bwend); if (!timerisset(&bw->bwend)) return; bw->lamt *= 8; waitlen = (double)1000000L * bw->lamt / bw->rate; bw->bwstart.tv_sec = waitlen / 1000000L; bw->bwstart.tv_usec = waitlen % 1000000L; if (timercmp(&bw->bwstart, &bw->bwend, >)) { timersub(&bw->bwstart, &bw->bwend, &bw->bwend); /* Adjust the wait time */ if (bw->bwend.tv_sec) { bw->thresh /= 2; if (bw->thresh < bw->buflen / 4) bw->thresh = bw->buflen / 4; } else if (bw->bwend.tv_usec < 10000) { bw->thresh *= 2; if (bw->thresh > bw->buflen * 8) bw->thresh = bw->buflen * 8; } TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); while (nanosleep(&ts, &rm) == -1) { if (errno != EINTR) break; ts = rm; } } bw->lamt = 0; monotime_tv(&bw->bwstart); } /* Make a template filename for mk[sd]temp() */ void mktemp_proto(char *s, size_t len) { const char *tmpdir; int r; if ((tmpdir = getenv("TMPDIR")) != NULL) { r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); if (r > 0 && (size_t)r < len) return; } r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); if (r < 0 || (size_t)r >= len) fatal_f("template string too short"); } static const struct { const char *name; int value; } ipqos[] = { { "none", INT_MAX }, /* can't use 0 here; that's CS0 */ { "af11", IPTOS_DSCP_AF11 }, { "af12", IPTOS_DSCP_AF12 }, { "af13", IPTOS_DSCP_AF13 }, { "af21", IPTOS_DSCP_AF21 }, { "af22", IPTOS_DSCP_AF22 }, { "af23", IPTOS_DSCP_AF23 }, { "af31", IPTOS_DSCP_AF31 }, { "af32", IPTOS_DSCP_AF32 }, { "af33", IPTOS_DSCP_AF33 }, { "af41", IPTOS_DSCP_AF41 }, { "af42", IPTOS_DSCP_AF42 }, { "af43", IPTOS_DSCP_AF43 }, { "cs0", IPTOS_DSCP_CS0 }, { "cs1", IPTOS_DSCP_CS1 }, { "cs2", IPTOS_DSCP_CS2 }, { "cs3", IPTOS_DSCP_CS3 }, { "cs4", IPTOS_DSCP_CS4 }, { "cs5", IPTOS_DSCP_CS5 }, { "cs6", IPTOS_DSCP_CS6 }, { "cs7", IPTOS_DSCP_CS7 }, { "ef", IPTOS_DSCP_EF }, { "le", IPTOS_DSCP_LE }, { "lowdelay", IPTOS_LOWDELAY }, { "throughput", IPTOS_THROUGHPUT }, { "reliability", IPTOS_RELIABILITY }, { NULL, -1 } }; int parse_ipqos(const char *cp) { const char *errstr; u_int i; int val; if (cp == NULL) return -1; for (i = 0; ipqos[i].name != NULL; i++) { if (strcasecmp(cp, ipqos[i].name) == 0) return ipqos[i].value; } /* Try parsing as an integer */ val = (int)strtonum(cp, 0, 255, &errstr); if (errstr) return -1; return val; } const char * iptos2str(int iptos) { int i; static char iptos_str[sizeof "0xff"]; for (i = 0; ipqos[i].name != NULL; i++) { if (ipqos[i].value == iptos) return ipqos[i].name; } snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); return iptos_str; } void lowercase(char *s) { for (; *s; s++) *s = tolower((u_char)*s); } int unix_listener(const char *path, int backlog, int unlink_first) { struct sockaddr_un sunaddr; int saved_errno, sock; memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { error_f("path \"%s\" too long for Unix domain socket", path); errno = ENAMETOOLONG; return -1; } sock = socket(PF_UNIX, SOCK_STREAM, 0); if (sock == -1) { saved_errno = errno; error_f("socket: %.100s", strerror(errno)); errno = saved_errno; return -1; } if (unlink_first == 1) { if (unlink(path) != 0 && errno != ENOENT) error("unlink(%s): %.100s", path, strerror(errno)); } if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { saved_errno = errno; error_f("cannot bind to path %s: %s", path, strerror(errno)); close(sock); errno = saved_errno; return -1; } if (listen(sock, backlog) == -1) { saved_errno = errno; error_f("cannot listen on path %s: %s", path, strerror(errno)); close(sock); unlink(path); errno = saved_errno; return -1; } return sock; } void sock_set_v6only(int s) { #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) int on = 1; debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); #endif } /* * Compares two strings that maybe be NULL. Returns non-zero if strings * are both NULL or are identical, returns zero otherwise. */ static int strcmp_maybe_null(const char *a, const char *b) { if ((a == NULL && b != NULL) || (a != NULL && b == NULL)) return 0; if (a != NULL && strcmp(a, b) != 0) return 0; return 1; } /* * Compare two forwards, returning non-zero if they are identical or * zero otherwise. */ int forward_equals(const struct Forward *a, const struct Forward *b) { if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0) return 0; if (a->listen_port != b->listen_port) return 0; if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0) return 0; if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0) return 0; if (a->connect_port != b->connect_port) return 0; if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0) return 0; /* allocated_port and handle are not checked */ return 1; } /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */ int permitopen_port(const char *p) { int port; if (strcmp(p, "*") == 0) return FWD_PERMIT_ANY_PORT; if ((port = a2port(p)) > 0) return port; return -1; } /* returns 1 if process is already daemonized, 0 otherwise */ int daemonized(void) { int fd; if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { close(fd); return 0; /* have controlling terminal */ } if (getppid() != 1) return 0; /* parent is not init */ if (getsid(0) != getpid()) return 0; /* not session leader */ debug3("already daemonized"); return 1; } /* * Splits 's' into an argument vector. Handles quoted string and basic * escape characters (\\, \", \'). Caller must free the argument vector * and its members. */ int argv_split(const char *s, int *argcp, char ***argvp, int terminate_on_comment) { int r = SSH_ERR_INTERNAL_ERROR; int argc = 0, quote, i, j; char *arg, **argv = xcalloc(1, sizeof(*argv)); *argvp = NULL; *argcp = 0; for (i = 0; s[i] != '\0'; i++) { /* Skip leading whitespace */ if (s[i] == ' ' || s[i] == '\t') continue; if (terminate_on_comment && s[i] == '#') break; /* Start of a token */ quote = 0; argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); argv[argc] = NULL; /* Copy the token in, removing escapes */ for (j = 0; s[i] != '\0'; i++) { if (s[i] == '\\') { if (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\' || (quote == 0 && s[i + 1] == ' ')) { i++; /* Skip '\' */ arg[j++] = s[i]; } else { /* Unrecognised escape */ arg[j++] = s[i]; } } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) break; /* done */ else if (quote == 0 && (s[i] == '\"' || s[i] == '\'')) quote = s[i]; /* quote start */ else if (quote != 0 && s[i] == quote) quote = 0; /* quote end */ else arg[j++] = s[i]; } if (s[i] == '\0') { if (quote != 0) { /* Ran out of string looking for close quote */ r = SSH_ERR_INVALID_FORMAT; goto out; } break; } } /* Success */ *argcp = argc; *argvp = argv; argc = 0; argv = NULL; r = 0; out: if (argc != 0 && argv != NULL) { for (i = 0; i < argc; i++) free(argv[i]); free(argv); } return r; } /* * Reassemble an argument vector into a string, quoting and escaping as * necessary. Caller must free returned string. */ char * argv_assemble(int argc, char **argv) { int i, j, ws, r; char c, *ret; struct sshbuf *buf, *arg; if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (i = 0; i < argc; i++) { ws = 0; sshbuf_reset(arg); for (j = 0; argv[i][j] != '\0'; j++) { r = 0; c = argv[i][j]; switch (c) { case ' ': case '\t': ws = 1; r = sshbuf_put_u8(arg, c); break; case '\\': case '\'': case '"': if ((r = sshbuf_put_u8(arg, '\\')) != 0) break; /* FALLTHROUGH */ default: r = sshbuf_put_u8(arg, c); break; } if (r != 0) fatal_fr(r, "sshbuf_put_u8"); } if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || (r = sshbuf_putb(buf, arg)) != 0 || (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) fatal_fr(r, "assemble"); } if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) fatal_f("malloc failed"); memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); ret[sshbuf_len(buf)] = '\0'; sshbuf_free(buf); sshbuf_free(arg); return ret; } char * argv_next(int *argcp, char ***argvp) { char *ret = (*argvp)[0]; if (*argcp > 0 && ret != NULL) { (*argcp)--; (*argvp)++; } return ret; } void argv_consume(int *argcp) { *argcp = 0; } void argv_free(char **av, int ac) { int i; if (av == NULL) return; for (i = 0; i < ac; i++) free(av[i]); free(av); } /* Returns 0 if pid exited cleanly, non-zero otherwise */ int exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) { int status; while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { error("%s waitpid: %s", tag, strerror(errno)); return -1; } } if (WIFSIGNALED(status)) { error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); return -1; } else if (WEXITSTATUS(status) != 0) { do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, "%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); return -1; } return 0; } /* * Check a given path for security. This is defined as all components * of the path to the file must be owned by either the owner of * of the file or root and no directories must be group or world writable. * * XXX Should any specific check be done for sym links ? * * Takes a file name, its stat information (preferably from fstat() to * avoid races), the uid of the expected owner, their home directory and an * error buffer plus max size as arguments. * * Returns 0 on success and -1 on failure */ int safe_path(const char *name, struct stat *stp, const char *pw_dir, uid_t uid, char *err, size_t errlen) { char buf[PATH_MAX], homedir[PATH_MAX]; char *cp; int comparehome = 0; struct stat st; if (realpath(name, buf) == NULL) { snprintf(err, errlen, "realpath %s failed: %s", name, strerror(errno)); return -1; } if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) comparehome = 1; if (!S_ISREG(stp->st_mode)) { snprintf(err, errlen, "%s is not a regular file", buf); return -1; } if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || (stp->st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for file %s", buf); return -1; } /* for each component of the canonical path, walking upwards */ for (;;) { if ((cp = dirname(buf)) == NULL) { snprintf(err, errlen, "dirname() failed"); return -1; } strlcpy(buf, cp, sizeof(buf)); if (stat(buf, &st) == -1 || (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || (st.st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for directory %s", buf); return -1; } /* If are past the homedir then we can stop */ if (comparehome && strcmp(homedir, buf) == 0) break; /* * dirname should always complete with a "/" path, * but we can be paranoid and check for "." too */ if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) break; } return 0; } /* * Version of safe_path() that accepts an open file descriptor to * avoid races. * * Returns 0 on success and -1 on failure */ int safe_path_fd(int fd, const char *file, struct passwd *pw, char *err, size_t errlen) { struct stat st; /* check the open file to avoid races */ if (fstat(fd, &st) == -1) { snprintf(err, errlen, "cannot stat file %s: %s", file, strerror(errno)); return -1; } return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); } /* * Sets the value of the given variable in the environment. If the variable * already exists, its value is overridden. */ void child_set_env(char ***envp, u_int *envsizep, const char *name, const char *value) { char **env; u_int envsize; u_int i, namelen; if (strchr(name, '=') != NULL) { error("Invalid environment variable \"%.100s\"", name); return; } /* * If we're passed an uninitialized list, allocate a single null * entry before continuing. */ if ((*envp == NULL) != (*envsizep == 0)) fatal_f("environment size mismatch"); if (*envp == NULL && *envsizep == 0) { *envp = xmalloc(sizeof(char *)); *envp[0] = NULL; *envsizep = 1; } /* * Find the slot where the value should be stored. If the variable * already exists, we reuse the slot; otherwise we append a new slot * at the end of the array, expanding if necessary. */ env = *envp; namelen = strlen(name); for (i = 0; env[i]; i++) if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') break; if (env[i]) { /* Reuse the slot. */ free(env[i]); } else { /* New variable. Expand if necessary. */ envsize = *envsizep; if (i >= envsize - 1) { if (envsize >= 1000) fatal("child_set_env: too many env vars"); envsize += 50; env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); *envsizep = envsize; } /* Need to set the NULL pointer at end of array beyond the new slot. */ env[i + 1] = NULL; } /* Allocate space and format the variable in the appropriate slot. */ /* XXX xasprintf */ env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); } /* * Check and optionally lowercase a domain name, also removes trailing '.' * Returns 1 on success and 0 on failure, storing an error message in errstr. */ int valid_domain(char *name, int makelower, const char **errstr) { size_t i, l = strlen(name); u_char c, last = '\0'; static char errbuf[256]; if (l == 0) { strlcpy(errbuf, "empty domain name", sizeof(errbuf)); goto bad; } if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]) && name[0] != '_' /* technically invalid, but common */) { 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; if (nptr == NULL || *nptr == '\0') return "missing"; *val = strtonum(nptr, 0, INT_MAX, &errstr); return errstr; } int parse_absolute_time(const char *s, uint64_t *tp) { struct tm tm; time_t tt; char buf[32], *fmt; const char *cp; size_t l; int is_utc = 0; *tp = 0; l = strlen(s); if (l > 1 && strcasecmp(s + l - 1, "Z") == 0) { is_utc = 1; l--; } else if (l > 3 && strcasecmp(s + l - 3, "UTC") == 0) { is_utc = 1; l -= 3; } /* * POSIX strptime says "The application shall ensure that there * is white-space or other non-alphanumeric characters between * any two conversion specifications" so arrange things this way. */ switch (l) { case 8: /* YYYYMMDD */ fmt = "%Y-%m-%d"; snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6); break; case 12: /* YYYYMMDDHHMM */ fmt = "%Y-%m-%dT%H:%M"; snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s", s, s + 4, s + 6, s + 8, s + 10); break; case 14: /* YYYYMMDDHHMMSS */ fmt = "%Y-%m-%dT%H:%M:%S"; snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", s, s + 4, s + 6, s + 8, s + 10, s + 12); break; default: return SSH_ERR_INVALID_FORMAT; } memset(&tm, 0, sizeof(tm)); if ((cp = strptime(buf, fmt, &tm)) == NULL || *cp != '\0') return SSH_ERR_INVALID_FORMAT; if (is_utc) { if ((tt = timegm(&tm)) < 0) return SSH_ERR_INVALID_FORMAT; } else { if ((tt = mktime(&tm)) < 0) return SSH_ERR_INVALID_FORMAT; } /* success */ *tp = (uint64_t)tt; return 0; } void format_absolute_time(uint64_t t, char *buf, size_t len) { time_t tt = t > SSH_TIME_T_MAX ? SSH_TIME_T_MAX : t; struct tm tm; localtime_r(&tt, &tm); strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); } /* * Parse a "pattern=interval" clause (e.g. a ChannelTimeout). * Returns 0 on success or non-zero on failure. * Caller must free *typep. */ int parse_pattern_interval(const char *s, char **typep, int *secsp) { char *cp, *sdup; int secs; if (typep != NULL) *typep = NULL; if (secsp != NULL) *secsp = 0; if (s == NULL) return -1; sdup = xstrdup(s); if ((cp = strchr(sdup, '=')) == NULL || cp == sdup) { free(sdup); return -1; } *cp++ = '\0'; if ((secs = convtime(cp)) < 0) { free(sdup); return -1; } /* success */ if (typep != NULL) *typep = xstrdup(sdup); if (secsp != NULL) *secsp = secs; free(sdup); return 0; } /* check if path is absolute */ int path_absolute(const char *path) { return (*path == '/') ? 1 : 0; } void skip_space(char **cpp) { char *cp; for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) ; *cpp = cp; } /* authorized_key-style options parsing helpers */ /* * Match flag 'opt' in *optsp, and if allow_negate is set then also match * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0 * if negated option matches. * If the option or negated option matches, then *optsp is updated to * point to the first character after the option. */ int opt_flag(const char *opt, int allow_negate, const char **optsp) { size_t opt_len = strlen(opt); const char *opts = *optsp; int negate = 0; if (allow_negate && strncasecmp(opts, "no-", 3) == 0) { opts += 3; negate = 1; } if (strncasecmp(opts, opt, opt_len) == 0) { *optsp = opts + opt_len; return negate ? 0 : 1; } return -1; } char * opt_dequote(const char **sp, const char **errstrp) { const char *s = *sp; char *ret; size_t i; *errstrp = NULL; if (*s != '"') { *errstrp = "missing start quote"; return NULL; } s++; if ((ret = malloc(strlen((s)) + 1)) == NULL) { *errstrp = "memory allocation failed"; return NULL; } for (i = 0; *s != '\0' && *s != '"';) { if (s[0] == '\\' && s[1] == '"') s++; ret[i++] = *s++; } if (*s == '\0') { *errstrp = "missing end quote"; free(ret); return NULL; } ret[i] = '\0'; s++; *sp = s; return ret; } int opt_match(const char **opts, const char *term) { if (strncasecmp((*opts), term, strlen(term)) == 0 && (*opts)[strlen(term)] == '=') { *opts += strlen(term) + 1; return 1; } return 0; } void opt_array_append2(const char *file, const int line, const char *directive, char ***array, int **iarray, u_int *lp, const char *s, int i) { if (*lp >= INT_MAX) fatal("%s line %d: Too many %s entries", file, line, directive); if (iarray != NULL) { *iarray = xrecallocarray(*iarray, *lp, *lp + 1, sizeof(**iarray)); (*iarray)[*lp] = i; } *array = xrecallocarray(*array, *lp, *lp + 1, sizeof(**array)); (*array)[*lp] = xstrdup(s); (*lp)++; } void opt_array_append(const char *file, const int line, const char *directive, char ***array, u_int *lp, const char *s) { opt_array_append2(file, line, directive, array, NULL, lp, s, 0); } void opt_array_free2(char **array, int **iarray, u_int l) { u_int i; if (array == NULL || l == 0) return; for (i = 0; i < l; i++) free(array[i]); free(array); free(iarray); } sshsig_t ssh_signal(int signum, sshsig_t handler) { struct sigaction sa, osa; /* mask all other signals while in handler */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; sigfillset(&sa.sa_mask); #if defined(SA_RESTART) && !defined(NO_SA_RESTART) if (signum != SIGALRM) sa.sa_flags = SA_RESTART; #endif if (sigaction(signum, &sa, &osa) == -1) { debug3("sigaction(%s): %s", strsignal(signum), strerror(errno)); return SIG_ERR; } return osa.sa_handler; } int stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) { int devnull, ret = 0; if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { error_f("open %s: %s", _PATH_DEVNULL, strerror(errno)); return -1; } if ((do_stdin && dup2(devnull, STDIN_FILENO) == -1) || (do_stdout && dup2(devnull, STDOUT_FILENO) == -1) || (do_stderr && dup2(devnull, STDERR_FILENO) == -1)) { error_f("dup2: %s", strerror(errno)); ret = -1; } if (devnull > STDERR_FILENO) close(devnull); return ret; } /* * Runs command in a subprocess with a minimal environment. * Returns pid on success, 0 on failure. * The child stdout and stderr maybe captured, left attached or sent to * /dev/null depending on the contents of flags. * "tag" is prepended to log messages. * NB. "command" is only used for logging; the actual command executed is * av[0]. */ pid_t subprocess(const char *tag, const char *command, int ac, char **av, FILE **child, u_int flags, struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs) { FILE *f = NULL; struct stat st; int fd, devnull, p[2], i; pid_t pid; char *cp, errmsg[512]; u_int nenv = 0; char **env = NULL; /* If dropping privs, then must specify user and restore function */ if (drop_privs != NULL && (pw == NULL || restore_privs == NULL)) { error("%s: inconsistent arguments", tag); /* XXX fatal? */ return 0; } if (pw == NULL && (pw = getpwuid(getuid())) == NULL) { error("%s: no user for current uid", tag); return 0; } if (child != NULL) *child = NULL; debug3_f("%s command \"%s\" running as %s (flags 0x%x)", tag, command, pw->pw_name, flags); /* Check consistency */ if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) { error_f("inconsistent flags"); return 0; } if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) { error_f("inconsistent flags/output"); return 0; } /* * If executing an explicit binary, then verify the it exists * and appears safe-ish to execute */ if (!path_absolute(av[0])) { error("%s path is not absolute", tag); return 0; } if (drop_privs != NULL) drop_privs(pw); if (stat(av[0], &st) == -1) { error("Could not stat %s \"%s\": %s", tag, av[0], strerror(errno)); goto restore_return; } if ((flags & SSH_SUBPROCESS_UNSAFE_PATH) == 0 && safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); goto restore_return; } /* Prepare to keep the child's stdout if requested */ if (pipe(p) == -1) { error("%s: pipe: %s", tag, strerror(errno)); restore_return: if (restore_privs != NULL) restore_privs(); return 0; } if (restore_privs != NULL) restore_privs(); switch ((pid = fork())) { case -1: /* error */ error("%s: fork: %s", tag, strerror(errno)); close(p[0]); close(p[1]); return 0; case 0: /* child */ /* Prepare a minimal environment for the child. */ if ((flags & SSH_SUBPROCESS_PRESERVE_ENV) == 0) { nenv = 5; env = xcalloc(sizeof(*env), nenv); child_set_env(&env, &nenv, "PATH", _PATH_STDPATH); child_set_env(&env, &nenv, "USER", pw->pw_name); child_set_env(&env, &nenv, "LOGNAME", pw->pw_name); child_set_env(&env, &nenv, "HOME", pw->pw_dir); if ((cp = getenv("LANG")) != NULL) child_set_env(&env, &nenv, "LANG", cp); } for (i = 1; i < NSIG; i++) ssh_signal(i, SIG_DFL); if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { error("%s: open %s: %s", tag, _PATH_DEVNULL, strerror(errno)); _exit(1); } if (dup2(devnull, STDIN_FILENO) == -1) { error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } /* Set up stdout as requested; leave stderr in place for now. */ fd = -1; if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) fd = p[1]; else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0) fd = devnull; if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) { error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } closefrom(STDERR_FILENO + 1); if (geteuid() == 0 && initgroups(pw->pw_name, pw->pw_gid) == -1) { error("%s: initgroups(%s, %u): %s", tag, pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); _exit(1); } if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) { error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, strerror(errno)); _exit(1); } if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) { error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid, strerror(errno)); _exit(1); } /* stdin is pointed to /dev/null at this point */ if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && dup2(STDIN_FILENO, STDERR_FILENO) == -1) { error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } if (env != NULL) execve(av[0], av, env); else execv(av[0], av); error("%s %s \"%s\": %s", tag, env == NULL ? "execv" : "execve", command, strerror(errno)); _exit(127); default: /* parent */ break; } close(p[1]); if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) close(p[0]); else if ((f = fdopen(p[0], "r")) == NULL) { error("%s: fdopen: %s", tag, strerror(errno)); close(p[0]); /* Don't leave zombie child */ kill(pid, SIGTERM); while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) ; return 0; } /* Success */ debug3_f("%s pid %ld", tag, (long)pid); if (child != NULL) *child = f; return pid; } const char * lookup_env_in_list(const char *env, char * const *envs, size_t nenvs) { size_t i, envlen; envlen = strlen(env); for (i = 0; i < nenvs; i++) { if (strncmp(envs[i], env, envlen) == 0 && envs[i][envlen] == '=') { return envs[i] + envlen + 1; } } return NULL; } const char * lookup_setenv_in_list(const char *env, char * const *envs, size_t nenvs) { char *name, *cp; const char *ret; name = xstrdup(env); if ((cp = strchr(name, '=')) == NULL) { free(name); return NULL; /* not env=val */ } *cp = '\0'; ret = lookup_env_in_list(name, envs, nenvs); free(name); return ret; } /* * Helpers for managing poll(2)/ppoll(2) timeouts * Will remember the earliest deadline and return it for use in poll/ppoll. */ /* Initialise a poll/ppoll timeout with an indefinite deadline */ void ptimeout_init(struct timespec *pt) { /* * Deliberately invalid for ppoll(2). * Will be converted to NULL in ptimeout_get_tspec() later. */ pt->tv_sec = -1; pt->tv_nsec = 0; } /* Specify a poll/ppoll deadline of at most 'sec' seconds */ void ptimeout_deadline_sec(struct timespec *pt, long sec) { if (pt->tv_sec == -1 || pt->tv_sec >= sec) { pt->tv_sec = sec; pt->tv_nsec = 0; } } /* Specify a poll/ppoll deadline of at most 'p' (timespec) */ static void ptimeout_deadline_tsp(struct timespec *pt, struct timespec *p) { if (pt->tv_sec == -1 || timespeccmp(pt, p, >=)) *pt = *p; } /* Specify a poll/ppoll deadline of at most 'ms' milliseconds */ void ptimeout_deadline_ms(struct timespec *pt, long ms) { struct timespec p; p.tv_sec = ms / 1000; p.tv_nsec = (ms % 1000) * 1000000; ptimeout_deadline_tsp(pt, &p); } /* Specify a poll/ppoll deadline at wall clock monotime 'when' (timespec) */ void ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when) { struct timespec now, t; monotime_ts(&now); if (timespeccmp(&now, when, >=)) { /* 'when' is now or in the past. Timeout ASAP */ pt->tv_sec = 0; pt->tv_nsec = 0; } else { timespecsub(when, &now, &t); ptimeout_deadline_tsp(pt, &t); } } /* Specify a poll/ppoll deadline at wall clock monotime 'when' */ void ptimeout_deadline_monotime(struct timespec *pt, time_t when) { struct timespec t; t.tv_sec = when; t.tv_nsec = 0; ptimeout_deadline_monotime_tsp(pt, &t); } /* Get a poll(2) timeout value in milliseconds */ int ptimeout_get_ms(struct timespec *pt) { if (pt->tv_sec == -1) return -1; if (pt->tv_sec >= (INT_MAX - (pt->tv_nsec / 1000000)) / 1000) return INT_MAX; return (pt->tv_sec * 1000) + (pt->tv_nsec / 1000000); } /* Get a ppoll(2) timeout value as a timespec pointer */ struct timespec * ptimeout_get_tsp(struct timespec *pt) { return pt->tv_sec == -1 ? NULL : pt; } /* Returns non-zero if a timeout has been set (i.e. is not indefinite) */ int ptimeout_isset(struct timespec *pt) { return pt->tv_sec != -1; } /* * Returns zero if the library at 'path' contains symbol 's', nonzero * otherwise. */ int lib_contains_symbol(const char *path, const char *s) { #ifdef HAVE_NLIST_H struct nlist nl[2]; int ret = -1, r; memset(nl, 0, sizeof(nl)); nl[0].n_name = xstrdup(s); nl[1].n_name = NULL; if ((r = nlist(path, nl)) == -1) { error_f("nlist failed for %s", path); goto out; } if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) { error_f("library %s does not contain symbol %s", path, s); goto out; } /* success */ ret = 0; out: free(nl[0].n_name); return ret; #else /* HAVE_NLIST_H */ int fd, ret = -1; struct stat st; void *m = NULL; size_t sz = 0; memset(&st, 0, sizeof(st)); if ((fd = open(path, O_RDONLY)) < 0) { error_f("open %s: %s", path, strerror(errno)); return -1; } if (fstat(fd, &st) != 0) { error_f("fstat %s: %s", path, strerror(errno)); goto out; } if (!S_ISREG(st.st_mode)) { error_f("%s is not a regular file", path); goto out; } if (st.st_size < 0 || (size_t)st.st_size < strlen(s) || st.st_size >= INT_MAX/2) { error_f("%s bad size %lld", path, (long long)st.st_size); goto out; } sz = (size_t)st.st_size; if ((m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED || m == NULL) { error_f("mmap %s: %s", path, strerror(errno)); goto out; } if (memmem(m, sz, s, strlen(s)) == NULL) { error_f("%s does not contain expected string %s", path, s); goto out; } /* success */ ret = 0; out: if (m != NULL && m != MAP_FAILED) munmap(m, sz); close(fd); return ret; #endif /* HAVE_NLIST_H */ } int signal_is_crash(int sig) { switch (sig) { case SIGSEGV: case SIGBUS: case SIGTRAP: case SIGSYS: case SIGFPE: case SIGILL: case SIGABRT: return 1; } return 0; } openssh-10.0p1/PaxHeaders.10889/misc.h100644 001750 001750 0000000003614775415623 0014260xustar0030 atime=1744182234.604320775 openssh-10.0p1/misc.h010064400017500001750000000223031477541562300126430ustar00djmdjm/* $OpenBSD: misc.h,v 1.110 2024/09/25 01:24:04 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef _MISC_H #define _MISC_H #include #include #include #include #include /* special-case port number meaning allow any port */ #define FWD_PERMIT_ANY_PORT 0 /* special-case wildcard meaning allow any host */ #define FWD_PERMIT_ANY_HOST "*" /* Data structure for representing a forwarding request. */ struct Forward { char *listen_host; /* Host (address) to listen on. */ int listen_port; /* Port to forward. */ char *listen_path; /* Path to bind domain socket. */ char *connect_host; /* Host to connect. */ int connect_port; /* Port to connect on connect_host. */ char *connect_path; /* Path to connect domain socket. */ int allocated_port; /* Dynamically allocated listen port */ int handle; /* Handle for dynamic listen ports */ }; int forward_equals(const struct Forward *, const struct Forward *); int permitopen_port(const char *p); int daemonized(void); /* Common server and client forwarding options. */ struct ForwardOptions { int gateway_ports; /* Allow remote connects to forwarded ports. */ mode_t streamlocal_bind_mask; /* umask for streamlocal binds */ int streamlocal_bind_unlink; /* unlink socket before bind */ }; /* misc.c */ char *chop(char *); void rtrim(char *); void skip_space(char **); const char *strprefix(const char *, const char *, int); char *strdelim(char **); char *strdelimw(char **); int set_nonblock(int); int unset_nonblock(int); void set_nodelay(int); int set_reuseaddr(int); char *get_rdomain(int); int set_rdomain(int, const char *); int get_sock_af(int); void set_sock_tos(int, int); int waitrfd(int, int *, volatile sig_atomic_t *); int timeout_connect(int, const struct sockaddr *, socklen_t, int *); int a2port(const char *); int a2tun(const char *, int *); char *put_host_port(const char *, u_short); char *hpdelim2(char **, char *); char *hpdelim(char **); char *cleanhostname(char *); char *colon(char *); int parse_user_host_path(const char *, char **, char **, char **); int parse_user_host_port(const char *, char **, char **, int *); int parse_uri(const char *, const char *, char **, char **, int *, char **); int convtime(const char *); const char *fmt_timeframe(time_t t); int tilde_expand(const char *, uid_t, char **); char *tilde_expand_filename(const char *, uid_t); char *dollar_expand(int *, const char *string, ...); char *percent_expand(const char *, ...) __attribute__((__sentinel__)); char *percent_dollar_expand(const char *, ...) __attribute__((__sentinel__)); char *tohex(const void *, size_t); void xextendf(char **s, const char *sep, const char *fmt, ...) __attribute__((__format__ (printf, 3, 4))) __attribute__((__nonnull__ (3))); void sanitise_stdfd(void); void ms_subtract_diff(struct timeval *, int *); void ms_to_timespec(struct timespec *, int); void monotime_ts(struct timespec *); void monotime_tv(struct timeval *); time_t monotime(void); double monotime_double(void); void lowercase(char *s); int unix_listener(const char *, int, int); int valid_domain(char *, int, const char **); int valid_env_name(const char *); const char *atoi_err(const char *, int *); int parse_absolute_time(const char *, uint64_t *); void format_absolute_time(uint64_t, char *, size_t); int parse_pattern_interval(const char *, char **, int *); int path_absolute(const char *); int stdfd_devnull(int, int, int); int lib_contains_symbol(const char *, const char *); void sock_set_v6only(int); struct passwd *pwcopy(struct passwd *); const char *ssh_gai_strerror(int); typedef void privdrop_fn(struct passwd *); typedef void privrestore_fn(void); #define SSH_SUBPROCESS_STDOUT_DISCARD (1) /* Discard stdout */ #define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */ #define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */ #define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ #define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, struct passwd *, privdrop_fn *, privrestore_fn *); typedef struct arglist arglist; struct arglist { char **list; u_int num; u_int nalloc; }; void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3))); void replacearg(arglist *, u_int, char *, ...) __attribute__((format(printf, 3, 4))); void freeargs(arglist *); int tun_open(int, int, char **); /* Common definitions for ssh tunnel device forwarding */ #define SSH_TUNMODE_NO 0x00 #define SSH_TUNMODE_POINTOPOINT 0x01 #define SSH_TUNMODE_ETHERNET 0x02 #define SSH_TUNMODE_DEFAULT SSH_TUNMODE_POINTOPOINT #define SSH_TUNMODE_YES (SSH_TUNMODE_POINTOPOINT|SSH_TUNMODE_ETHERNET) #define SSH_TUNID_ANY 0x7fffffff #define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) #define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) /* Fake port to indicate that host field is really a path. */ #define PORT_STREAMLOCAL -2 /* Functions to extract or store big-endian words of various sizes */ u_int64_t get_u64(const void *) __attribute__((__bounded__( __minbytes__, 1, 8))); u_int32_t get_u32(const void *) __attribute__((__bounded__( __minbytes__, 1, 4))); u_int16_t get_u16(const void *) __attribute__((__bounded__( __minbytes__, 1, 2))); void put_u64(void *, u_int64_t) __attribute__((__bounded__( __minbytes__, 1, 8))); void put_u32(void *, u_int32_t) __attribute__((__bounded__( __minbytes__, 1, 4))); void put_u16(void *, u_int16_t) __attribute__((__bounded__( __minbytes__, 1, 2))); /* Little-endian store/load, used by umac.c */ u_int32_t get_u32_le(const void *) __attribute__((__bounded__(__minbytes__, 1, 4))); void put_u32_le(void *, u_int32_t) __attribute__((__bounded__(__minbytes__, 1, 4))); struct bwlimit { size_t buflen; u_int64_t rate; /* desired rate in kbit/s */ u_int64_t thresh; /* threshold after which we'll check timers */ u_int64_t lamt; /* amount written in last timer interval */ struct timeval bwstart, bwend; }; void bandwidth_limit_init(struct bwlimit *, u_int64_t, size_t); void bandwidth_limit(struct bwlimit *, size_t); int parse_ipqos(const char *); const char *iptos2str(int); void mktemp_proto(char *, size_t); void child_set_env(char ***envp, u_int *envsizep, const char *name, const char *value); const char *lookup_env_in_list(const char *env, char * const *envs, size_t nenvs); const char *lookup_setenv_in_list(const char *env, char * const *envs, size_t nenvs); int argv_split(const char *, int *, char ***, int); char *argv_assemble(int, char **argv); char *argv_next(int *, char ***); void argv_consume(int *); void argv_free(char **, int); int exited_cleanly(pid_t, const char *, const char *, int); struct stat; int safe_path(const char *, struct stat *, const char *, uid_t, char *, size_t); int safe_path_fd(int, const char *, struct passwd *, char *err, size_t errlen); /* authorized_key-style options parsing helpers */ int opt_flag(const char *opt, int allow_negate, const char **optsp); char *opt_dequote(const char **sp, const char **errstrp); int opt_match(const char **opts, const char *term); /* readconf/servconf option lists */ void opt_array_append(const char *file, const int line, const char *directive, char ***array, u_int *lp, const char *s); void opt_array_append2(const char *file, const int line, const char *directive, char ***array, int **iarray, u_int *lp, const char *s, int i); void opt_array_free2(char **array, int **iarray, u_int l); struct timespec; void ptimeout_init(struct timespec *pt); void ptimeout_deadline_sec(struct timespec *pt, long sec); void ptimeout_deadline_ms(struct timespec *pt, long ms); void ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when); void ptimeout_deadline_monotime(struct timespec *pt, time_t when); int ptimeout_get_ms(struct timespec *pt); struct timespec *ptimeout_get_tsp(struct timespec *pt); int ptimeout_isset(struct timespec *pt); /* readpass.c */ #define RP_ECHO 0x0001 #define RP_ALLOW_STDIN 0x0002 #define RP_ALLOW_EOF 0x0004 #define RP_USE_ASKPASS 0x0008 struct notifier_ctx; char *read_passphrase(const char *, int); int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); struct notifier_ctx *notify_start(int, const char *, ...) __attribute__((format(printf, 2, 3))); void notify_complete(struct notifier_ctx *, const char *, ...) __attribute__((format(printf, 2, 3))); #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) typedef void (*sshsig_t)(int); sshsig_t ssh_signal(int, sshsig_t); int signal_is_crash(int); /* On OpenBSD time_t is int64_t which is long long. */ /* #define SSH_TIME_T_MAX LLONG_MAX */ #endif /* _MISC_H */ openssh-10.0p1/PaxHeaders.10889/mkinstalldirs100755 001750 001750 0000000003614775415623 0015762xustar0030 atime=1744182234.604320775 openssh-10.0p1/mkinstalldirs010075500017500001750000000011711477541562300143450ustar00djmdjm#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here openssh-10.0p1/PaxHeaders.10889/mlkem768.sh100644 001750 001750 0000000003614775415623 0015062xustar0030 atime=1744182234.604320775 openssh-10.0p1/mlkem768.sh010064400017500001750000000136331477541562300134530ustar00djmdjm#!/bin/sh # $OpenBSD: mlkem768.sh,v 1.3 2024/10/27 02:06:01 djm Exp $ # Placed in the Public Domain. # #WANT_LIBCRUX_REVISION="origin/main" WANT_LIBCRUX_REVISION="84c5d87b3092c59294345aa269ceefe0eb97cc35" FILES=" libcrux/libcrux-ml-kem/cg/eurydice_glue.h libcrux/libcrux-ml-kem/cg/libcrux_core.h libcrux/libcrux-ml-kem/cg/libcrux_ct_ops.h libcrux/libcrux-ml-kem/cg/libcrux_sha3_portable.h libcrux/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h " START="$PWD" die() { echo "$@" 1>&2 exit 1 } set -xeuo pipefail test -d libcrux || git clone https://github.com/cryspen/libcrux cd libcrux test `git diff | wc -l` -ne 0 && die "tree has unstaged changes" git fetch git checkout -B extract 1>&2 git reset --hard $WANT_LIBCRUX_REVISION 1>&2 LIBCRUX_REVISION=`git rev-parse HEAD` set +x cd $START ( printf '/* $Open'; printf 'BSD$ */\n' # Sigh echo echo "/* Extracted from libcrux revision $LIBCRUX_REVISION */" echo echo '/*' cat libcrux/LICENSE-MIT | sed 's/^/ * /;s/ *$//' echo ' */' echo echo '#if !defined(__GNUC__) || (__GNUC__ < 2)' echo '# define __attribute__(x)' echo '#endif' echo '#define KRML_MUSTINLINE inline' echo '#define KRML_NOINLINE __attribute__((noinline, unused))' echo '#define KRML_HOST_EPRINTF(...)' echo '#define KRML_HOST_EXIT(x) fatal_f("internal error")' echo __builtin_popcount_replacement=' const uint8_t v[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; return v[x0 & 0xf] + v[(x0 >> 4) & 0xf]; ' for i in $FILES; do echo "/* from $i */" # Changes to all files: # - remove all includes, we inline everything required. # - cleanup whitespace sed -e "/#include/d" \ -e 's/[ ]*$//' \ $i | \ case "$i" in */libcrux-ml-kem/cg/eurydice_glue.h) # Replace endian functions with versions that work. perl -0777 -pe 's/(static inline void core_num__u64_9__to_le_bytes.*\n)([^}]*\n)/\1 v = htole64(v);\n\2/' | perl -0777 -pe 's/(static inline uint64_t core_num__u64_9__from_le_bytes.*?)return v;/\1return le64toh(v);/s' | perl -0777 -pe 's/(static inline uint32_t core_num__u32_8__from_le_bytes.*?)return v;/\1return le32toh(v);/s' | # Compat for popcount. perl -0777 -pe 's/\#ifdef (_MSC_VER)(.*?return __popcnt\(x0\);)/\#if defined(\1)\2/s' | perl -0777 -pe "s/\\#else(\\n\\s+return __builtin_popcount\\(x0\\);)/\\#elif !defined(MISSING_BUILTIN_POPCOUNT)\\1\\n#else$__builtin_popcount_replacement/s" ;; # Default: pass through. *) cat ;; esac echo done echo echo '/* rename some types to be a bit more ergonomic */' echo '#define libcrux_mlkem768_keypair libcrux_ml_kem_mlkem768_MlKem768KeyPair_s' echo '#define libcrux_mlkem768_pk_valid_result Option_92_s' echo '#define libcrux_mlkem768_pk libcrux_ml_kem_types_MlKemPublicKey_15_s' echo '#define libcrux_mlkem768_sk libcrux_ml_kem_types_MlKemPrivateKey_55_s' echo '#define libcrux_mlkem768_ciphertext libcrux_ml_kem_mlkem768_MlKem768Ciphertext_s' echo '#define libcrux_mlkem768_enc_result tuple_3c_s' ) > libcrux_mlkem768_sha3.h_new # Do some checks on the resultant file cat > libcrux_mlkem768_sha3_check.c << _EOF #include #include #include #include #include #include #include #include #include "crypto_api.h" #define fatal_f(x) exit(1) #include "libcrux_mlkem768_sha3.h_new" int main(void) { struct libcrux_mlkem768_keypair keypair = {0}; struct libcrux_mlkem768_pk pk = {0}; struct libcrux_mlkem768_sk sk = {0}; struct libcrux_mlkem768_ciphertext ct = {0}; struct libcrux_mlkem768_enc_result enc_result = {0}; uint8_t kp_seed[64] = {0}, enc_seed[32] = {0}; uint8_t shared_key[crypto_kem_mlkem768_BYTES]; if (sizeof(keypair.pk.value) != crypto_kem_mlkem768_PUBLICKEYBYTES) errx(1, "keypair.pk bad"); if (sizeof(keypair.sk.value) != crypto_kem_mlkem768_SECRETKEYBYTES) errx(1, "keypair.sk bad"); if (sizeof(pk.value) != crypto_kem_mlkem768_PUBLICKEYBYTES) errx(1, "pk bad"); if (sizeof(sk.value) != crypto_kem_mlkem768_SECRETKEYBYTES) errx(1, "sk bad"); if (sizeof(ct.value) != crypto_kem_mlkem768_CIPHERTEXTBYTES) errx(1, "ct bad"); if (sizeof(enc_result.fst.value) != crypto_kem_mlkem768_CIPHERTEXTBYTES) errx(1, "enc_result ct bad"); if (sizeof(enc_result.snd) != crypto_kem_mlkem768_BYTES) errx(1, "enc_result shared key bad"); keypair = libcrux_ml_kem_mlkem768_portable_generate_key_pair(kp_seed); if (!libcrux_ml_kem_mlkem768_portable_validate_public_key(&keypair.pk)) errx(1, "valid smoke failed"); enc_result = libcrux_ml_kem_mlkem768_portable_encapsulate(&keypair.pk, enc_seed); libcrux_ml_kem_mlkem768_portable_decapsulate(&keypair.sk, &enc_result.fst, shared_key); if (memcmp(shared_key, enc_result.snd, sizeof(shared_key)) != 0) errx(1, "smoke failed"); return 0; } _EOF cc -Wall -Wextra -Wno-unused-parameter -o libcrux_mlkem768_sha3_check \ libcrux_mlkem768_sha3_check.c ./libcrux_mlkem768_sha3_check # Extract PRNG inputs; there's no nice #defines for these key_pair_rng_len=`sed -e '/^libcrux_ml_kem_mlkem768_portable_kyber_generate_key_pair[(]$/,/[)] {$/!d' < libcrux_mlkem768_sha3.h_new | grep 'uint8_t randomness\[[0-9]*U\][)]' | sed 's/.*randomness\[\([0-9]*\)U\].*/\1/'` enc_rng_len=`sed -e '/^static inline tuple_3c libcrux_ml_kem_mlkem768_portable_kyber_encapsulate[(]$/,/[)] {$/!d' < libcrux_mlkem768_sha3.h_new | grep 'uint8_t randomness\[[0-9]*U\][)]' | sed 's/.*randomness\[\([0-9]*\)U\].*/\1/'` test -z "$key_pair_rng_len" && die "couldn't find size of libcrux_ml_kem_mlkem768_portable_kyber_generate_key_pair randomness argument" test -z "$enc_rng_len" && die "couldn't find size of libcrux_ml_kem_mlkem768_portable_kyber_encapsulate randomness argument" ( echo "/* defines for PRNG inputs */" echo "#define LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN $key_pair_rng_len" echo "#define LIBCRUX_ML_KEM_ENC_PRNG_LEN $enc_rng_len" ) >> libcrux_mlkem768_sha3.h_new mv libcrux_mlkem768_sha3.h_new libcrux_mlkem768_sha3.h rm libcrux_mlkem768_sha3_check libcrux_mlkem768_sha3_check.c echo 1>&2 echo "libcrux_mlkem768_sha3.h OK" 1>&2 openssh-10.0p1/PaxHeaders.10889/moduli100644 001750 001750 0000000003614775415623 0014370xustar0030 atime=1744182234.612134284 openssh-10.0p1/moduli010064400017500001750000022050761477541562300127670ustar00djmdjm# $OpenBSD: moduli,v 1.39 2024/11/29 00:13:36 dtucker Exp $ # Time Type Tests Tries Size Generator Modulus 20240828044144 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63216235F7 20240828044149 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63217EB4CB 20240828044153 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632197445F 20240828044203 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6321E28D7F 20240828044206 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6321F5D65F 20240828044207 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6321F5F783 20240828044210 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63220959FB 20240828044217 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63223CB053 20240828044224 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63226F7A83 20240828044233 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6322B452E7 20240828044240 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6322E58253 20240828044251 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632334AB77 20240828044259 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632379357B 20240828044311 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6323D336A7 20240828044323 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63242A969B 20240828044326 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63243E12C3 20240828044349 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6324EA98FF 20240828044351 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6324F33C17 20240828044406 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632569D1BF 20240828044412 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632591055B 20240828044416 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6325A64983 20240828044426 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6325F39C73 20240828044435 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63263987CF 20240828044440 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63265B2A5F 20240828044445 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63267C888B 20240828044453 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6326B9D6C3 20240828044505 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63270DF46F 20240828044509 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632725FB3B 20240828044510 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632728D6F3 20240828044525 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6327A20713 20240828044536 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6327FA0007 20240828044603 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6328C7601B 20240828044621 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602100B138DB 20240828044622 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602100BA7D33 20240828044630 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602100F35A77 20240828044634 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021010E6E03 20240828044637 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021011F7EAB 20240828044646 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021016091AB 20240828044657 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602101B2C867 20240828044658 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602101B60E87 20240828044721 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602102652CD7 20240828044731 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602102B160B7 20240828044737 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602102DA0A57 20240828044755 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD260210367434B 20240828044803 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602103A3B7DF 20240828044807 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602103C2D9CB 20240828044812 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602103DE1313 20240828044821 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602104264E53 20240828044835 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602104909817 20240828044855 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602105309B8B 20240828044903 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021056A2A5F 20240828044903 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021056A52EB 20240828044921 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602105F6DDD3 20240828044930 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021063AE353 20240828044934 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD260210651B5C7 20240828044937 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602106651B4B 20240828044944 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021069D4573 20240828045003 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021072D06EB 20240828045023 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602107C5C8DB 20240828045043 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021085D358B 20240828045540 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB83F1177 20240828045614 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB8AA8ABF 20240828045644 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB90E7B73 20240828045720 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB984B19F 20240828045813 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBA2CAEB7 20240828045858 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBABFBAAB 20240828045903 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBACAA69F 20240828045912 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBAE15E2B 20240828045932 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBB1CB097 20240828050005 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBB86CA4F 20240828050036 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBBEDB4C7 20240828050043 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBBFC577F 20240828050107 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBC490C0B 20240828050136 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBCA8444F 20240828050201 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBCFC24F3 20240828050209 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBD0E9213 20240828050303 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBDBBE653 20240828050329 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBE0AE17B 20240828050406 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBE8344F3 20240828050430 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBEC9D58B 20240828050438 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBEDF58FB 20240828050528 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBF858DCB 20240828050633 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC0619997 20240828050638 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC06A2A8B 20240828050712 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC0D40C6F 20240828050715 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC0D78F7F 20240828050743 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC12FBEF7 20240828050851 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC216E8EB 20240828050903 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC235154F 20240828050905 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC235B9E3 20240828050941 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC2AA4F87 20240828051038 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC36951FB 20240828051046 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC37DE073 20240828051104 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC3B311A3 20240828051215 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC4A3904B 20240828051246 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC502215B 20240828051312 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC5506613 20240828051329 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC57E32D3 20240828051336 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC58E630B 20240828051520 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC6DF9DDB 20240828051549 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC736A7B3 20240828051622 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC7A11C13 20240828051823 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC933AB0B 20240828051906 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC9BF25EF 20240828052009 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BBF34E3B 20240828052030 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BC38F533 20240828052045 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BC632227 20240828052153 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BD42ABFF 20240828052207 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BD6986DF 20240828052211 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BD7241F7 20240828052259 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BE0ECA0B 20240828052336 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BE863B2B 20240828052339 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BE899267 20240828052415 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BF03197B 20240828052431 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BF33F3BB 20240828052513 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BFBAA987 20240828052522 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BFD18B5B 20240828052527 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BFDA82D3 20240828052609 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C0656637 20240828052616 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C07626F3 20240828052621 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C07E39AB 20240828052816 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C2033C13 20240828052903 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C29B2063 20240828052932 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C2FB438B 20240828052959 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C35070C3 20240828053054 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C4050DE3 20240828053223 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C52F78A7 20240828053319 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C5E6180B 20240828053339 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C61E1503 20240828053345 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C62B8123 20240828053430 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C6B80C6B 20240828053549 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C7B7959F 20240828053758 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C95C0E23 20240828053817 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C9938013 20240828053837 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C9D0494F 20240828053914 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79CA42683F 20240828054013 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79CB06EC0B 20240828054258 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79CD234BAB 20240828060009 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A70951B13 20240828060511 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A726F0C37 20240828060714 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7335AED3 20240828061156 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7501901B 20240828061217 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A751A9A43 20240828061522 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A763D53FF 20240828061600 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7675A20F 20240828061619 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A768B4D03 20240828061636 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A769E17B3 20240828062452 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A79B996BB 20240828062521 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A79E2492B 20240828062623 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7A419E13 20240828062831 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7B0C50CB 20240828062854 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7B27FC2B 20240828063249 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7CA08843 20240828063334 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7CE52E4F 20240828063443 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7D4D4863 20240828063548 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7DAC7243 20240828063629 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7DE88D73 20240828064128 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7FCA819B 20240828064626 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A819B3083 20240828064816 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8247AB73 20240828065323 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A84385B67 20240828065513 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A84DF9C03 20240828070128 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A872AEE03 20240828070200 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A87566497 20240828070537 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A88AEB07F 20240828070904 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8A00154F 20240828071020 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8A740023 20240828071247 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8B633D9B 20240828071353 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8BC1DD33 20240828071426 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8BF0634B 20240828071455 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8C19F3D3 20240828071541 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8C5E63D3 20240828071923 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B3CF4313 20240828072226 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B4F5B7EF 20240828072458 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B5EF31DB 20240828073047 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B82262CF 20240828073253 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B8EDB05B 20240828074035 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9BBE344BF 20240828074440 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9BD60A58B 20240828074721 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9BE6938F7 20240828075138 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C00C2AD3 20240828075304 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C0911F9B 20240828075632 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C1E1F5EB 20240828080239 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C432FEB3 20240828080841 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C68352A3 20240828081126 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C78B996B 20240828081614 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C9536B03 20240828082258 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CBE55E03 20240828082637 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CD49EF1B 20240828082710 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CD7A6C07 20240828082726 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CD8C1A83 20240828082826 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CDEC8AA3 20240828082907 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CE27CDDF 20240828083210 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CF4E290B 20240828083415 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D01153B3 20240828083603 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D0BAF663 20240828083703 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D11A10CB 20240828083816 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D18C60B7 20240828084040 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D26C42A3 20240828090009 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F2258E4DB 20240828090718 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F233F2A7B 20240828091256 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F23ED9417 20240828091549 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F243D1C03 20240828092905 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F25E8D11F 20240828093653 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F26E25303 20240828100014 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F29D9C7A3 20240828100324 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F2A3C434F 20240828105814 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3151094F 20240828111427 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F33641C63 20240828113247 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F35BB7B0B 20240828113333 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F35CD9A97 20240828113540 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F360A482B 20240828115349 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3862A7B3 20240828115426 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F386EC997 20240828120438 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F39B5CC43 20240828121629 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3B334FB3 20240828121657 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3B3B734B 20240828122545 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3C524DB3 20240828123158 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3D1B196F 20240828130157 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F40EB0D47 20240828130238 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F40F7E253 20240828134737 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F46C46D3B 20240828135646 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F47E7985B 20240828144149 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F4DB24103 20240828145157 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F4EF2EE0B 20240828145816 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F4FB0AC7F 20240828151150 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F515FD9BF 20240828151822 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5229B63F 20240828153933 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F54CF3923 20240828154759 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F55E07A93 20240828161625 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F598D643B 20240828162500 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5A998FB7 20240828162916 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5B1CC43B 20240828163955 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5C71914B 20240828164552 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5D2E5D1F 20240828170129 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5F34D397 20240828172001 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F6192353F 20240828172046 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F61A3C147 20240828172320 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F61EF7817 20240828173414 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F6352E0CB 20240828173441 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F6359E007 20240828180730 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F679AD6CB 20240828180915 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F67CD41EB 20240828180941 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F67D23A63 20240828181257 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F683B05BF 20240828182555 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3180CE228BB 20240828184406 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3180F2F287B 20240828185315 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181059FDFB 20240828191106 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31812A21FB3 20240828191122 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31812A28277 20240828195243 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318180489DB 20240828195610 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31818728F67 20240828201325 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181AAF829B 20240828202233 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181BD9FE33 20240828202820 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181C96132B 20240828204913 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181F3FE8A3 20240828205946 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318209CB6D7 20240828211537 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31822AC1387 20240828220459 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318290F4E1F 20240828224012 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3182D9E3A03 20240828232844 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31833F1DD7B 20240828233400 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183494A423 20240828235802 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31837ADEA57 20240829001115 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318395E7B83 20240829004718 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183E0E5603 20240829004844 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183E34D98F 20240829005431 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183EECD0DF 20240829010933 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31840CEA00B 20240829014049 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31844D61FFB 20240829014355 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184533474F 20240829014829 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31845BEB5C7 20240829015142 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31846235FD3 20240829015517 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184695C7FB 20240829020608 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31847F7E373 20240829023600 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184BC56B47 20240829025737 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184E74875B 20240829031846 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318511B9B7F 20240829033452 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318531C0F27 20240829034004 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31853C097B7 20240829043625 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187E5F08523 20240829053823 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187EA33BB33 20240829061611 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187ECC3E213 20240829064111 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187EE73FD37 20240829065111 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187EF1CB167 20240829082003 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187F52294C3 20240829091934 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187F92CC467 20240829093659 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187FA58CCB3 20240829103319 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187FE2DC683 20240829123824 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18806C1B393 20240829130958 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18808EFDAAB 20240829135456 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1880C119733 20240829150211 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18810B3AE03 20240829152452 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18812362547 20240829171859 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881A26609B 20240829181704 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881E2C3E3B 20240829182818 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881EED38A3 20240829184006 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881FB9391B 20240829190814 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18821A70EA7 20240829195154 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18824BB04C7 20240829200011 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882546EC8F 20240829203003 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188274D620B 20240829220907 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882E2608EB 20240829221444 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882E810C9B 20240829222440 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882F2EBA7B 20240829230449 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18831F68C1B 20240829231044 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18832552757 20240829233827 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188343C3EAB 20240829235120 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188351A81B3 20240830003221 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18837F06443 20240830011832 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1883B1C9E73 20240830013013 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1883BE3681B 20240830014610 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1883CF597DB 20240830032931 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188443580AB 20240830042102 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18847CB52C7 20240830042255 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18847E4A687 20240830052035 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884BDB09B7 20240830053449 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884CD217AB 20240830054036 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884D30808F 20240830060721 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884F02040B 20240830071657 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18853C7A8E7 20240830084720 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FEF75703DB 20240830094656 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FEFB626A2F 20240830095006 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FEFB909467 20240830110930 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0108EC1F 20240830112637 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF02315BCB 20240830113545 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF02D19C77 20240830134211 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0BA3E697 20240830134427 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0BC3CC37 20240830134817 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0C009ED3 20240830145923 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF10E44067 20240830161320 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF15FCEA4B 20240830170319 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF197243AF 20240830171339 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1A211BAF 20240830173745 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1BC7E24F 20240830181908 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1E96C5DF 20240830181940 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1E9711DB 20240830183135 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1F5C367B 20240830190740 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF21D6FFCB 20240830192133 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF22C8073B 20240830213430 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF2BE900AB 20240830213722 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF2C10C36F 20240830221923 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF2EF2814B 20240830225347 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF314EE303 20240830231356 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF32AF8B0B 20240830234723 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF34FE61CB 20240831004647 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF3918C417 20240831020149 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF3E4B559F 20240831022637 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF4002F243 20240831030552 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF42BB548F 20240831033741 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF44F1D9D7 20240831034841 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF45ACBE37 20240831035452 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF460E12C3 20240831053706 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF4D2CFB27 20240831055400 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF4E512613 20240831073419 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF5532694B 20240831074414 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF55DB1637 20240831081807 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF583421DF 20240831090302 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF5B405DA3 20240831093205 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF5D338B6B 20240831103110 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF61456293 20240831121754 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB1349E143 20240831124443 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB14CB7AFF 20240831135558 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB18CC80A3 20240831145738 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB1C36864B 20240831165313 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB22B0FAD7 20240831185249 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB29880B2B 20240831185952 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB29E5889B 20240831194619 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB2C7FC84F 20240831230544 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB37F47B7F 20240901001522 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB3BE4A76B 20240901013228 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB404463B7 20240901015829 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB41B1142F 20240901025646 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB44FDAE87 20240901031615 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB461000EB 20240901042008 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB49A1BE47 20240901044227 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB4AE1A82B 20240901064528 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB51D37F37 20240901073955 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB54DB30B7 20240901080825 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB56740653 20240901083546 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB57EF4EAF 20240901093005 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB5AF60F7B 20240901122015 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB64814643 20240901124800 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB661018A7 20240901134700 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB695D723F 20240901135853 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6A06CAEB 20240901140005 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6A0E0D2F 20240901141551 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6AEB6337 20240901141841 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6B0A7C53 20240901144342 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6C6CC963 20240901151624 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6E3F7CCF 20240901173158 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB75F13437 20240901180438 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB77CD90AB 20240901182042 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB78AD2B63 20240901193908 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB7D18983B 20240901195652 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB7E1244DF 20240901202100 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB7F6CD3C7 20240901210156 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB81BA121B 20240901220732 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB8571A7D3 20240901233244 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB8A40CE93 20240902012852 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46ED77CB9B 20240902013705 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46EDE42B6B 20240902022309 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46F07C42B3 20240902023700 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46F13D6B9B 20240902033157 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46F444A467 20240902074115 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D470264825B 20240902081217 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D47041D069B 20240902085634 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4706993BE7 20240902095212 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4709C080DB 20240902103310 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D470C00A7DB 20240902113925 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D470FB7C81B 20240902145636 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D471ADD1BC7 20240902162039 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D471F910B07 20240902162513 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D471FCD9837 20240902170958 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D47224EBF47 20240902195925 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D472BED92A7 20240902201041 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D472C8835C3 20240902212334 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4730A0A15F 20240903001824 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473A91EE3B 20240903003705 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473B9B08CB 20240903010010 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473CDEB7B3 20240903010348 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473D0B3A67 20240903034119 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D474614297B 20240903040728 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4747910563 20240903051146 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D474B45E3DB 20240903064823 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4750BE2633 20240903064907 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4750C0835B 20240903101831 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D475C6B64DB 20240903113322 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4760A047BF 20240903122505 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D47638D75FB 20240903124220 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D476482E71B 20240903133142 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D476752BA3F 20240903143834 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D476B1AC6BB openssh-10.0p1/PaxHeaders.10889/moduli.0100644 001750 001750 0000000003614775415623 0014526xustar0030 atime=1744182234.621898794 openssh-10.0p1/moduli.0010064400017500001750000000066021477541562300131150ustar00djmdjmMODULI(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 -M generate, calculates numbers that are likely to be useful. A second primality testing pass, using ssh-keygen -M screen, 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. OpenBSD 7.6 April 16, 2022 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/moduli.5100644 001750 001750 0000000003614775415623 0014533xustar0030 atime=1744182234.621898794 openssh-10.0p1/moduli.5010064400017500001750000000071541477541562300131250ustar00djmdjm.\" $OpenBSD: moduli.5,v 1.19 2022/04/16 04:30:10 dtucker Exp $ .\" .\" Copyright (c) 2008 Damien Miller .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .Dd $Mdocdate: April 16 2022 $ .Dt MODULI 5 .Os .Sh NAME .Nm moduli .Nd Diffie-Hellman moduli .Sh DESCRIPTION The .Pa /etc/moduli file contains prime numbers and generators for use by .Xr sshd 8 in the Diffie-Hellman Group Exchange key exchange method. .Pp New moduli may be generated with .Xr ssh-keygen 1 using a two-step process. An initial .Em candidate generation pass, using .Ic ssh-keygen -M generate , calculates numbers that are likely to be useful. A second .Em primality testing pass, using .Ic ssh-keygen -M screen , provides a high degree of assurance that the numbers are prime and are safe for use in Diffie-Hellman operations by .Xr sshd 8 . This .Nm format is used as the output from each pass. .Pp The file consists of newline-separated records, one per modulus, containing seven space-separated fields. These fields are as follows: .Bl -tag -width Description -offset indent .It timestamp The time that the modulus was last processed as YYYYMMDDHHMMSS. .It type Decimal number specifying the internal structure of the prime modulus. Supported types are: .Pp .Bl -tag -width 0x00 -compact .It 0 Unknown, not tested. .It 2 "Safe" prime; (p-1)/2 is also prime. .It 4 Sophie Germain; 2p+1 is also prime. .El .Pp Moduli candidates initially produced by .Xr ssh-keygen 1 are Sophie Germain primes (type 4). Further primality testing with .Xr ssh-keygen 1 produces safe prime moduli (type 2) that are ready for use in .Xr sshd 8 . Other types are not used by OpenSSH. .It tests Decimal number indicating the type of primality tests that the number has been subjected to represented as a bitmask of the following values: .Pp .Bl -tag -width 0x00 -compact .It 0x00 Not tested. .It 0x01 Composite number \(en not prime. .It 0x02 Sieve of Eratosthenes. .It 0x04 Probabilistic Miller-Rabin primality tests. .El .Pp The .Xr ssh-keygen 1 moduli candidate generation uses the Sieve of Eratosthenes (flag 0x02). Subsequent .Xr ssh-keygen 1 primality tests are Miller-Rabin tests (flag 0x04). .It trials Decimal number indicating the number of primality trials that have been performed on the modulus. .It size Decimal number indicating the size of the prime in bits. .It generator The recommended generator for use with this modulus (hexadecimal). .It modulus The modulus itself in hexadecimal. .El .Pp When performing Diffie-Hellman Group Exchange, .Xr sshd 8 first estimates the size of the modulus required to produce enough Diffie-Hellman output to sufficiently key the selected symmetric cipher. .Xr sshd 8 then randomly selects a modulus from .Fa /etc/moduli that best meets the size requirement. .Sh SEE ALSO .Xr ssh-keygen 1 , .Xr sshd 8 .Sh STANDARDS .Rs .%A M. Friedl .%A N. Provos .%A W. Simpson .%D March 2006 .%R RFC 4419 .%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol .Re openssh-10.0p1/PaxHeaders.10889/moduli.c100644 001750 001750 0000000003614775415623 0014611xustar0030 atime=1744182234.622875411 openssh-10.0p1/moduli.c010064400017500001750000000513021477541562300131750ustar00djmdjm/* $OpenBSD: moduli.c,v 1.39 2023/03/02 06:41:56 dtucker Exp $ */ /* * Copyright 1994 Phil Karn * Copyright 1996-1998, 2003 William Allen Simpson * Copyright 2000 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. */ /* * Two-step process to generate safe primes for DHGEX * * Sieve candidates for "safe" primes, * suitable for use as Diffie-Hellman moduli; * that is, where q = (p-1)/2 is also prime. * * First step: generate candidate primes (memory intensive) * Second step: test primes' safety (processor intensive) */ #include "includes.h" #ifdef WITH_OPENSSL #include #include #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "dh.h" #include "log.h" #include "misc.h" #include "openbsd-compat/openssl-compat.h" /* * File output defines */ /* need line long enough for largest moduli plus headers */ #define QLINESIZE (100+8192) /* * Size: decimal. * Specifies the number of the most significant bit (0 to M). * WARNING: internally, usually 1 to N. */ #define QSIZE_MINIMUM (511) /* * Prime sieving defines */ /* Constant: assuming 8 bit bytes and 32 bit words */ #define SHIFT_BIT (3) #define SHIFT_BYTE (2) #define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE) #define SHIFT_MEGABYTE (20) #define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE) /* * Using virtual memory can cause thrashing. This should be the largest * number that is supported without a large amount of disk activity -- * that would increase the run time from hours to days or weeks! */ #define LARGE_MINIMUM (8UL) /* megabytes */ /* * Do not increase this number beyond the unsigned integer bit size. * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits). */ #define LARGE_MAXIMUM (127UL) /* megabytes */ /* * Constant: when used with 32-bit integers, the largest sieve prime * has to be less than 2**32. */ #define SMALL_MAXIMUM (0xffffffffUL) /* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */ #define TINY_NUMBER (1UL<<16) /* Ensure enough bit space for testing 2*q. */ #define TEST_MAXIMUM (1UL<<16) #define TEST_MINIMUM (QSIZE_MINIMUM + 1) /* real TEST_MINIMUM (1UL << (SHIFT_WORD - TEST_POWER)) */ #define TEST_POWER (3) /* 2**n, n < SHIFT_WORD */ /* bit operations on 32-bit words */ #define BIT_CLEAR(a,n) ((a)[(n)>>SHIFT_WORD] &= ~(1L << ((n) & 31))) #define BIT_SET(a,n) ((a)[(n)>>SHIFT_WORD] |= (1L << ((n) & 31))) #define BIT_TEST(a,n) ((a)[(n)>>SHIFT_WORD] & (1L << ((n) & 31))) /* * Prime testing defines */ /* Minimum number of primality tests to perform */ #define TRIAL_MINIMUM (4) /* * Sieving data (XXX - move to struct) */ /* sieve 2**16 */ static u_int32_t *TinySieve, tinybits; /* sieve 2**30 in 2**16 parts */ static u_int32_t *SmallSieve, smallbits, smallbase; /* sieve relative to the initial value */ static u_int32_t *LargeSieve, largewords, largetries, largenumbers; static u_int32_t largebits, largememory; /* megabytes */ static BIGNUM *largebase; int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long, unsigned long); /* * print moduli out in consistent form, */ static int qfileout(FILE * ofile, u_int32_t otype, u_int32_t otests, u_int32_t otries, u_int32_t osize, u_int32_t ogenerator, BIGNUM * omodulus) { struct tm *gtm; time_t time_now; int res; 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, gtm->tm_hour, gtm->tm_min, gtm->tm_sec, otype, otests, otries, osize, ogenerator); if (res < 0) return (-1); if (BN_print_fp(ofile, omodulus) < 1) return (-1); res = fprintf(ofile, "\n"); fflush(ofile); return (res > 0 ? 0 : -1); } /* ** Sieve p's and q's with small factors */ static void sieve_large(u_int32_t s32) { u_int64_t r, u, s = s32; debug3("sieve_large %u", s32); largetries++; /* r = largebase mod s */ r = BN_mod_word(largebase, s32); if (r == 0) u = 0; /* s divides into largebase exactly */ else u = s - r; /* largebase+u is first entry divisible by s */ if (u < largebits * 2ULL) { /* * The sieve omits p's and q's divisible by 2, so ensure that * largebase+u is odd. Then, step through the sieve in * increments of 2*s */ if (u & 0x1) u += s; /* Make largebase+u odd, and u even */ /* Mark all multiples of 2*s */ for (u /= 2; u < largebits; u += s) BIT_SET(LargeSieve, u); } /* r = p mod s */ r = (2 * r + 1) % s; if (r == 0) u = 0; /* s divides p exactly */ else u = s - r; /* p+u is first entry divisible by s */ if (u < largebits * 4ULL) { /* * The sieve omits p's divisible by 4, so ensure that * largebase+u is not. Then, step through the sieve in * increments of 4*s */ while (u & 0x3) { if (SMALL_MAXIMUM - u < s) return; u += s; } /* Mark all multiples of 4*s */ for (u /= 4; u < largebits; u += s) BIT_SET(LargeSieve, u); } } /* * list candidates for Sophie-Germain primes (where q = (p-1)/2) * to standard output. * The list is checked against small known primes (less than 2**30). */ int gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) { BIGNUM *q; u_int32_t j, r, s, t; u_int32_t smallwords = TINY_NUMBER >> 6; u_int32_t tinywords = TINY_NUMBER >> 6; time_t time_start, time_stop; u_int32_t i; int ret = 0; largememory = memory; if (memory != 0 && (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { error("Invalid memory amount (min %ld, max %ld)", LARGE_MINIMUM, LARGE_MAXIMUM); return (-1); } /* * Set power to the length in bits of the prime to be generated. * This is changed to 1 less than the desired safe prime moduli p. */ if (power > TEST_MAXIMUM) { error("Too many bits: %u > %lu", power, TEST_MAXIMUM); return (-1); } else if (power < TEST_MINIMUM) { error("Too few bits: %u < %u", power, TEST_MINIMUM); return (-1); } power--; /* decrement before squaring */ /* * The density of ordinary primes is on the order of 1/bits, so the * density of safe primes should be about (1/bits)**2. Set test range * to something well above bits**2 to be reasonably sure (but not * guaranteed) of catching at least one safe prime. */ largewords = ((power * power) >> (SHIFT_WORD - TEST_POWER)); /* * Need idea of how much memory is available. We don't have to use all * of it. */ if (largememory > LARGE_MAXIMUM) { logit("Limited memory: %u MB; limit %lu MB", largememory, LARGE_MAXIMUM); largememory = LARGE_MAXIMUM; } if (largewords <= (largememory << SHIFT_MEGAWORD)) { logit("Increased memory: %u MB; need %u bytes", largememory, (largewords << SHIFT_BYTE)); largewords = (largememory << SHIFT_MEGAWORD); } else if (largememory > 0) { logit("Decreased memory: %u MB; want %u bytes", largememory, (largewords << SHIFT_BYTE)); largewords = (largememory << SHIFT_MEGAWORD); } TinySieve = xcalloc(tinywords, sizeof(u_int32_t)); tinybits = tinywords << SHIFT_WORD; SmallSieve = xcalloc(smallwords, sizeof(u_int32_t)); smallbits = smallwords << SHIFT_WORD; /* * dynamically determine available memory */ while ((LargeSieve = calloc(largewords, sizeof(u_int32_t))) == NULL) largewords -= (1L << (SHIFT_MEGAWORD - 2)); /* 1/4 MB chunks */ largebits = largewords << SHIFT_WORD; largenumbers = largebits * 2; /* even numbers excluded */ /* validation check: count the number of primes tried */ largetries = 0; if ((q = BN_new()) == NULL) fatal("BN_new failed"); /* * Generate random starting point for subprime search, or use * specified parameter. */ if ((largebase = BN_new()) == NULL) fatal("BN_new failed"); if (start == NULL) { if (BN_rand(largebase, power, 1, 1) == 0) fatal("BN_rand failed"); } else { if (BN_copy(largebase, start) == NULL) fatal("BN_copy: failed"); } /* ensure odd */ if (BN_set_bit(largebase, 0) == 0) fatal("BN_set_bit: failed"); time(&time_start); logit("%.24s Sieve next %u plus %u-bit", ctime(&time_start), largenumbers, power); debug2("start point: 0x%s", BN_bn2hex(largebase)); /* * TinySieve */ for (i = 0; i < tinybits; i++) { if (BIT_TEST(TinySieve, i)) continue; /* 2*i+3 is composite */ /* The next tiny prime */ t = 2 * i + 3; /* Mark all multiples of t */ for (j = i + t; j < tinybits; j += t) BIT_SET(TinySieve, j); sieve_large(t); } /* * Start the small block search at the next possible prime. To avoid * fencepost errors, the last pass is skipped. */ for (smallbase = TINY_NUMBER + 3; smallbase < (SMALL_MAXIMUM - TINY_NUMBER); smallbase += TINY_NUMBER) { for (i = 0; i < tinybits; i++) { if (BIT_TEST(TinySieve, i)) continue; /* 2*i+3 is composite */ /* The next tiny prime */ t = 2 * i + 3; r = smallbase % t; if (r == 0) { s = 0; /* t divides into smallbase exactly */ } else { /* smallbase+s is first entry divisible by t */ s = t - r; } /* * The sieve omits even numbers, so ensure that * smallbase+s is odd. Then, step through the sieve * in increments of 2*t */ if (s & 1) s += t; /* Make smallbase+s odd, and s even */ /* Mark all multiples of 2*t */ for (s /= 2; s < smallbits; s += t) BIT_SET(SmallSieve, s); } /* * SmallSieve */ for (i = 0; i < smallbits; i++) { if (BIT_TEST(SmallSieve, i)) continue; /* 2*i+smallbase is composite */ /* The next small prime */ sieve_large((2 * i) + smallbase); } memset(SmallSieve, 0, smallwords << SHIFT_BYTE); } time(&time_stop); 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)) continue; /* Definitely composite, skip */ debug2("test q = largebase+%u", 2 * j); if (BN_set_word(q, 2 * j) == 0) fatal("BN_set_word failed"); if (BN_add(q, q, largebase) == 0) fatal("BN_add failed"); if (qfileout(out, MODULI_TYPE_SOPHIE_GERMAIN, MODULI_TESTS_SIEVE, largetries, (power - 1) /* MSB */, (0), q) == -1) { ret = -1; break; } r++; /* count q */ } time(&time_stop); free(LargeSieve); free(SmallSieve); free(TinySieve); logit("%.24s Found %u candidates", ctime(&time_stop), r); return (ret); } static void write_checkpoint(char *cpfile, u_int32_t lineno) { FILE *fp; char tmp[PATH_MAX]; int r, writeok, closeok; r = snprintf(tmp, sizeof(tmp), "%s.XXXXXXXXXX", cpfile); if (r < 0 || r >= PATH_MAX) { logit("write_checkpoint: temp pathname too long"); return; } if ((r = mkstemp(tmp)) == -1) { logit("mkstemp(%s): %s", tmp, strerror(errno)); return; } if ((fp = fdopen(r, "w")) == NULL) { logit("write_checkpoint: fdopen: %s", strerror(errno)); unlink(tmp); close(r); return; } writeok = (fprintf(fp, "%lu\n", (unsigned long)lineno) > 0); closeok = (fclose(fp) == 0); if (writeok && closeok && rename(tmp, cpfile) == 0) { debug3("wrote checkpoint line %lu to '%s'", (unsigned long)lineno, cpfile); } else { logit("failed to write to checkpoint file '%s': %s", cpfile, strerror(errno)); (void)unlink(tmp); } } static unsigned long read_checkpoint(char *cpfile) { FILE *fp; unsigned long lineno = 0; if ((fp = fopen(cpfile, "r")) == NULL) return 0; if (fscanf(fp, "%lu\n", &lineno) < 1) logit("Failed to load checkpoint from '%s'", cpfile); else logit("Loaded checkpoint from '%s' line %lu", cpfile, lineno); fclose(fp); return lineno; } static unsigned long count_lines(FILE *f) { unsigned long count = 0; char lp[QLINESIZE + 1]; if (fseek(f, 0, SEEK_SET) != 0) { debug("input file is not seekable"); return ULONG_MAX; } while (fgets(lp, QLINESIZE + 1, f) != NULL) count++; rewind(f); debug("input file has %lu lines", count); return count; } static char * fmt_time(time_t seconds) { int day, hr, min; static char buf[128]; min = (seconds / 60) % 60; hr = (seconds / 60 / 60) % 24; day = seconds / 60 / 60 / 24; if (day > 0) snprintf(buf, sizeof buf, "%dd %d:%02d", day, hr, min); else snprintf(buf, sizeof buf, "%d:%02d", hr, min); return buf; } static void print_progress(unsigned long start_lineno, unsigned long current_lineno, unsigned long end_lineno) { static time_t time_start, time_prev; time_t time_now, elapsed; unsigned long num_to_process, processed, remaining, percent, eta; double time_per_line; char *eta_str; time_now = monotime(); if (time_start == 0) { time_start = time_prev = time_now; return; } /* print progress after 1m then once per 5m */ if (time_now - time_prev < 5 * 60) return; time_prev = time_now; elapsed = time_now - time_start; processed = current_lineno - start_lineno; remaining = end_lineno - current_lineno; num_to_process = end_lineno - start_lineno; time_per_line = (double)elapsed / processed; /* if we don't know how many we're processing just report count+time */ time(&time_now); if (end_lineno == ULONG_MAX) { logit("%.24s processed %lu in %s", ctime(&time_now), processed, fmt_time(elapsed)); return; } percent = 100 * processed / num_to_process; eta = time_per_line * remaining; eta_str = xstrdup(fmt_time(eta)); logit("%.24s processed %lu of %lu (%lu%%) in %s, ETA %s", ctime(&time_now), processed, num_to_process, percent, fmt_time(elapsed), eta_str); free(eta_str); } /* * perform a Miller-Rabin primality test * on the list of candidates * (checking both q and p) * The result is a list of so-call "safe" primes */ int 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; 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, is_prime; if (trials < TRIAL_MINIMUM) { error("Minimum primality trials is %d", TRIAL_MINIMUM); return (-1); } if (num_lines == 0) end_lineno = count_lines(in); else end_lineno = start_lineno + num_lines; time(&time_start); if ((p = BN_new()) == NULL) fatal("BN_new failed"); if ((q = BN_new()) == NULL) fatal("BN_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 = MAXIMUM(last_processed, start_lineno); if (end_lineno == ULONG_MAX) debug("process from line %lu from pipe", last_processed); else debug("process from line %lu to line %lu", last_processed, end_lineno); res = 0; lp = xmalloc(QLINESIZE + 1); while (fgets(lp, QLINESIZE + 1, in) != NULL && count_in < end_lineno) { count_in++; if (count_in <= last_processed) { debug3("skipping line %u, before checkpoint or " "specified start line", count_in); continue; } if (checkpoint_file != NULL) write_checkpoint(checkpoint_file, count_in); print_progress(start_lineno, count_in, end_lineno); if (strlen(lp) < 14 || *lp == '!' || *lp == '#') { debug2("%10u: comment or short line", count_in); continue; } /* XXX - fragile parser */ /* time */ cp = &lp[14]; /* (skip) */ /* type */ in_type = strtoul(cp, &cp, 10); /* tests */ in_tests = strtoul(cp, &cp, 10); if (in_tests & MODULI_TESTS_COMPOSITE) { debug2("%10u: known composite", count_in); continue; } /* tries */ in_tries = strtoul(cp, &cp, 10); /* size (most significant bit) */ in_size = strtoul(cp, &cp, 10); /* generator (hex) */ generator_known = strtoul(cp, &cp, 16); /* Skip white space */ cp += strspn(cp, " "); /* modulus (hex) */ switch (in_type) { case MODULI_TYPE_SOPHIE_GERMAIN: debug2("%10u: (%u) Sophie-Germain", count_in, in_type); a = q; if (BN_hex2bn(&a, cp) == 0) fatal("BN_hex2bn failed"); /* p = 2*q + 1 */ if (BN_lshift(p, q, 1) == 0) fatal("BN_lshift failed"); if (BN_add_word(p, 1) == 0) fatal("BN_add_word failed"); in_size += 1; generator_known = 0; break; case MODULI_TYPE_UNSTRUCTURED: case MODULI_TYPE_SAFE: case MODULI_TYPE_SCHNORR: case MODULI_TYPE_STRONG: case MODULI_TYPE_UNKNOWN: debug2("%10u: (%u)", count_in, in_type); a = p; if (BN_hex2bn(&a, cp) == 0) fatal("BN_hex2bn failed"); /* q = (p-1) / 2 */ if (BN_rshift(q, p, 1) == 0) fatal("BN_rshift failed"); break; default: debug2("Unknown prime type"); break; } /* * due to earlier inconsistencies in interpretation, check * the proposed bit size. */ if ((u_int32_t)BN_num_bits(p) != (in_size + 1)) { debug2("%10u: bit size %u mismatch", count_in, in_size); continue; } if (in_size < QSIZE_MINIMUM) { debug2("%10u: bit size %u too short", count_in, in_size); continue; } if (in_tests & MODULI_TESTS_MILLER_RABIN) in_tries += trials; else in_tries = trials; /* * guess unknown generator */ if (generator_known == 0) { if (BN_mod_word(p, 24) == 11) generator_known = 2; else { u_int32_t r = BN_mod_word(p, 10); if (r == 3 || r == 7) generator_known = 5; } } /* * skip tests when desired generator doesn't match */ if (generator_wanted > 0 && generator_wanted != generator_known) { debug2("%10u: generator %d != %d", count_in, generator_known, generator_wanted); continue; } /* * Primes with no known generator are useless for DH, so * skip those. */ if (generator_known == 0) { debug2("%10u: no known generator", count_in); continue; } count_possible++; /* * The (1/4)^N performance bound on Miller-Rabin is * extremely pessimistic, so don't spend a lot of time * really verifying that q is prime until after we know * that p is also prime. A single pass will weed out the * vast majority of composite q's. */ is_prime = BN_is_prime_ex(q, 1, 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; } /* * q is possibly prime, so go ahead and really make sure * that p is prime. If it is, then we can go back and do * the same for q. If p is composite, chances are that * will show up on the first Rabin-Miller iteration so it * doesn't hurt to specify a high iteration count. */ is_prime = BN_is_prime_ex(p, trials, 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 */ 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; } debug("%10u: q is almost certainly prime", count_in); if (qfileout(out, MODULI_TYPE_SAFE, in_tests | MODULI_TESTS_MILLER_RABIN, in_tries, in_size, generator_known, p)) { res = -1; break; } count_out++; } time(&time_stop); free(lp); BN_free(p); BN_free(q); if (checkpoint_file != NULL) unlink(checkpoint_file); logit("%.24s Found %u safe primes of %u candidates in %ld seconds", ctime(&time_stop), count_out, count_possible, (long) (time_stop - time_start)); return (res); } #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/monitor.c100644 001750 001750 0000000003514775415623 0015006xustar0029 atime=1744182234.62678173 openssh-10.0p1/monitor.c010064400017500001750000001557161477541562300134110ustar00djmdjm/* $OpenBSD: monitor.c,v 1.247 2024/12/03 22:30:03 jsg Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #ifdef WITH_OPENSSL #include #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 "sshkey.h" #include "sshbuf.h" #include "hostfile.h" #include "auth.h" #include "cipher.h" #include "kex.h" #include "dh.h" #include "auth-pam.h" #include "packet.h" #include "auth-options.h" #include "sshpty.h" #include "channels.h" #include "session.h" #include "sshlogin.h" #include "canohost.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "monitor_fdpass.h" #include "compat.h" #include "ssh2.h" #include "authfd.h" #include "match.h" #include "ssherr.h" #include "sk-api.h" #include "srclimit.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; #endif /* Imports */ extern ServerOptions options; extern u_int utmp_len; extern struct sshbuf *cfg; extern struct sshbuf *loginmsg; extern struct include_list includes; 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(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_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_state(struct ssh *, int, struct sshbuf *); #ifdef USE_PAM 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(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(struct ssh *, int, struct sshbuf *); int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); #endif static Authctxt *authctxt; /* local state for key verify */ static u_char *key_blob = NULL; static size_t key_bloblen = 0; static u_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"; static char *auth_submethod = NULL; static u_int session_id2_len = 0; static u_char *session_id2 = NULL; static pid_t monitor_child_pid; int auth_attempted = 0; struct mon_table { enum monitor_reqtype type; int flags; int (*f)(struct ssh *, int, struct sshbuf *); }; #define MON_ISAUTH 0x0004 /* Required for Authentication */ #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ #define MON_ONCE 0x0010 /* Disable after calling */ #define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) #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[] = { {MONITOR_REQ_STATE, MON_ONCE, mm_answer_state}, #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, #endif {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #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_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 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, #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, 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} }; struct mon_table mon_dispatch_postauth20[] = { {MONITOR_REQ_STATE, MON_ONCE, mm_answer_state}, #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, #endif {MONITOR_REQ_SIGN, 0, mm_answer_sign}, {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, 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, mm_answer_audit_command}, #endif {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) { while (ent->f != NULL) { if (ent->type == type) { ent->flags &= ~MON_PERMIT; ent->flags |= permit ? MON_PERMIT : 0; return; } ent++; } } static void monitor_permit_authentications(int permit) { struct mon_table *ent = mon_dispatch; while (ent->f != NULL) { if (ent->flags & MON_AUTH) { ent->flags &= ~MON_PERMIT; ent->flags |= permit ? MON_PERMIT : 0; } ent++; } } void monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) { struct mon_table *ent; int authenticated = 0, partial = 0; debug3("preauth child monitor started"); 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 *)ssh->authctxt; memset(authctxt, 0, sizeof(*authctxt)); ssh->authctxt = authctxt; authctxt->loginmsg = loginmsg; mon_dispatch = mon_dispatch_proto20; /* Permit requests for state, moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_STATE, 1); 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; auth2_authctxt_reset_info(authctxt); authenticated = (monitor_read(ssh, pmonitor, mon_dispatch, &ent) == 1); /* Record that auth was attempted to set exit status later */ if ((ent->flags & MON_AUTH) != 0) auth_attempted = 1; /* Special handling for multiple required authentications */ if (options.num_auth_methods != 0) { if (authenticated && !auth2_update_methods_lists(authctxt, auth_method, auth_submethod)) { debug3_f("method %s: partial", auth_method); authenticated = 0; partial = 1; } } if (authenticated) { if (!(ent->flags & MON_AUTHDECIDE)) fatal_f("unexpected authentication from %d", ent->type); if (authctxt->pw->pw_uid == 0 && !auth_root_allowed(ssh, auth_method)) authenticated = 0; #ifdef USE_PAM /* PAM needs to perform account checks after auth */ if (options.use_pam && authenticated) { struct sshbuf *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( ssh, pmonitor->m_sendfd, m); sshbuf_free(m); } #endif } if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(ssh, authenticated, partial, auth_method, auth_submethod); if (!partial && !authenticated) authctxt->failures++; if (authenticated || partial) { auth2_update_session_info(authctxt, auth_method, auth_submethod); } } if (authctxt->failures > options.max_authtries) { /* Shouldn't happen */ fatal_f("privsep child made too many authentication " "attempts"); } } if (!authctxt->valid) fatal_f("authenticated invalid user"); if (strcmp(auth_method, "unknown") == 0) fatal_f("authentication method name unknown"); debug_f("user %s authenticated by privileged process", authctxt->user); auth_attempted = 0; ssh->authctxt = NULL; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); mm_get_keystate(ssh, pmonitor); /* Drain any buffered messages from the child */ while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) ; 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; } static void monitor_set_child_handler(pid_t pid) { monitor_child_pid = pid; } static void monitor_child_handler(int sig) { kill(monitor_child_pid, sig); } void monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) { close(pmonitor->m_recvfd); pmonitor->m_recvfd = -1; monitor_set_child_handler(pmonitor->m_pid); ssh_signal(SIGHUP, &monitor_child_handler); ssh_signal(SIGTERM, &monitor_child_handler); ssh_signal(SIGINT, &monitor_child_handler); #ifdef SIGXFSZ ssh_signal(SIGXFSZ, SIG_IGN); #endif mon_dispatch = mon_dispatch_postauth20; /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_STATE, 1); 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(ssh, pmonitor, mon_dispatch, NULL); } static int monitor_read_log(struct monitor *pmonitor) { struct sshbuf *logmsg; u_int len, level, forced; char *msg; u_char *p; int r; if ((logmsg = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); /* Read length */ if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0) fatal_fr(r, "reserve len"); if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) { if (errno == EPIPE) { sshbuf_free(logmsg); debug_f("child log fd closed"); close(pmonitor->m_log_recvfd); pmonitor->m_log_recvfd = -1; return -1; } fatal_f("log fd read: %s", strerror(errno)); } if ((r = sshbuf_get_u32(logmsg, &len)) != 0) fatal_fr(r, "parse len"); if (len <= 4 || len > 8192) fatal_f("invalid log message length %u", len); /* Read severity, message */ sshbuf_reset(logmsg); if ((r = sshbuf_reserve(logmsg, len, &p)) != 0) fatal_fr(r, "reserve msg"); if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len) fatal_f("log fd read: %s", strerror(errno)); if ((r = sshbuf_get_u32(logmsg, &level)) != 0 || (r = sshbuf_get_u32(logmsg, &forced)) != 0 || (r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0) fatal_fr(r, "parse"); /* Log it */ if (log_level_name(level) == NULL) fatal_f("invalid log level %u (corrupted message?)", level); sshlogdirect(level, forced, "%s [%s]", msg, mon_dispatch == mon_dispatch_postauth20 ? "postauth" : "preauth"); sshbuf_free(logmsg); free(msg); return 0; } static int monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent, struct mon_table **pent) { struct sshbuf *m; int r, ret; u_char type; struct pollfd pfd[2]; for (;;) { memset(&pfd, 0, sizeof(pfd)); pfd[0].fd = pmonitor->m_sendfd; pfd[0].events = POLLIN; pfd[1].fd = pmonitor->m_log_recvfd; pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN; if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { if (errno == EINTR || errno == EAGAIN) continue; fatal_f("poll: %s", strerror(errno)); } if (pfd[1].revents) { /* * Drain all log messages before processing next * monitor request. */ monitor_read_log(pmonitor); continue; } if (pfd[0].revents) break; /* Continues below */ } if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); mm_request_receive(pmonitor->m_sendfd, m); if ((r = sshbuf_get_u8(m, &type)) != 0) fatal_fr(r, "parse type"); debug3_f("checking request %d", type); while (ent->f != NULL) { if (ent->type == type) break; ent++; } if (ent->f != NULL) { if (!(ent->flags & MON_PERMIT)) fatal_f("unpermitted request %d", type); ret = (*ent->f)(ssh, pmonitor->m_sendfd, m); sshbuf_free(m); /* The child may use this request only once, disable it */ if (ent->flags & MON_ONCE) { debug2_f("%d used once, disabling now", type); ent->flags &= ~MON_PERMIT; } if (pent != NULL) *pent = ent; return ret; } fatal_f("unsupported request: %d", type); /* NOTREACHED */ return (-1); } /* allowed key state */ static int monitor_allowed_key(const u_char *blob, u_int bloblen) { /* make sure key is allowed */ if (key_blob == NULL || key_bloblen != bloblen || timingsafe_bcmp(key_blob, blob, key_bloblen)) return (0); return (1); } static void monitor_reset_key_state(void) { /* reset state */ 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; } int mm_answer_state(struct ssh *ssh, int sock, struct sshbuf *m) { struct sshbuf *inc = NULL, *hostkeys = NULL; struct sshbuf *opts = NULL, *confdata = NULL; struct include_item *item = NULL; int postauth; int r; sshbuf_reset(m); debug_f("config len %zu", sshbuf_len(cfg)); if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL || (opts = sshbuf_new()) == NULL || (confdata = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* XXX unnecessary? */ /* pack includes into a string */ TAILQ_FOREACH(item, &includes, entry) { if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 || (r = sshbuf_put_cstring(inc, item->filename)) != 0 || (r = sshbuf_put_stringb(inc, item->contents)) != 0) fatal_fr(r, "compose includes"); } hostkeys = pack_hostkeys(); /* * Protocol from monitor to unpriv privsep process: * string configuration * uint64 timing_secret XXX move delays to monitor and remove * string host_keys[] { * string public_key * string certificate * } * string server_banner * string client_banner * string included_files[] { * string selector * string filename * string contents * } * string configuration_data (postauth) * string keystate (postauth) * string authenticated_user (postauth) * string session_info (postauth) * string authopts (postauth) */ if ((r = sshbuf_put_stringb(m, cfg)) != 0 || (r = sshbuf_put_u64(m, options.timing_secret)) != 0 || (r = sshbuf_put_stringb(m, hostkeys)) != 0 || (r = sshbuf_put_stringb(m, ssh->kex->server_version)) != 0 || (r = sshbuf_put_stringb(m, ssh->kex->client_version)) != 0 || (r = sshbuf_put_stringb(m, inc)) != 0) fatal_fr(r, "compose config"); postauth = (authctxt && authctxt->pw && authctxt->authenticated); if (postauth) { /* XXX shouldn't be reachable */ fatal_f("internal error: called in postauth"); } sshbuf_free(inc); sshbuf_free(opts); sshbuf_free(confdata); mm_request_send(sock, MONITOR_ANS_STATE, m); debug3_f("done"); return (0); } #ifdef WITH_OPENSSL int mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m) { DH *dh; const BIGNUM *dh_p, *dh_g; int r; u_int min, want, max; if ((r = sshbuf_get_u32(m, &min)) != 0 || (r = sshbuf_get_u32(m, &want)) != 0 || (r = sshbuf_get_u32(m, &max)) != 0) fatal_fr(r, "parse"); debug3_f("got parameters: %d %d %d", min, want, max); /* We need to check here, too, in case the child got corrupted */ if (max < min || want < min || max < want) fatal_f("bad parameters: %d %d %d", min, want, max); sshbuf_reset(m); dh = choose_dh(min, want, max); if (dh == NULL) { if ((r = sshbuf_put_u8(m, 0)) != 0) fatal_fr(r, "assemble empty"); return (0); } else { /* Send first bignum */ 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_fr(r, "assemble"); DH_free(dh); } mm_request_send(sock, MONITOR_ANS_MODULI, m); return (0); } #endif int mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) { extern int auth_sock; /* XXX move to state struct? */ struct sshkey *pubkey, *key; struct sshbuf *sigbuf = NULL; u_char *p = NULL, *signature = NULL; char *alg = NULL; size_t datlen, siglen; int r, is_proof = 0, keyid; u_int compat; const char proof_req[] = "hostkeys-prove-00@openssh.com"; debug3_f("entering"); if ((r = sshkey_froms(m, &pubkey)) != 0 || (r = sshbuf_get_string(m, &p, &datlen)) != 0 || (r = sshbuf_get_cstring(m, &alg, NULL)) != 0 || (r = sshbuf_get_u32(m, &compat)) != 0) fatal_fr(r, "parse"); if ((keyid = get_hostkey_index(pubkey, 1, ssh)) == -1) fatal_f("unknown hostkey"); debug_f("hostkey %s index %d", sshkey_ssh_name(pubkey), keyid); sshkey_free(pubkey); /* * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), * SHA384 (48 bytes) and SHA512 (64 bytes). * * Otherwise, verify the signature request is for a hostkey * proof. * * XXX perform similar check for KEX signature requests too? * it's not trivial, since what is signed is the hash, rather * than the full kex structure... */ if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { /* * Construct expected hostkey proof and compare it to what * the client sent us. */ if (session_id2_len == 0) /* hostkeys is never first */ fatal_f("bad data length: %zu", datlen); if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) fatal_f("no hostkey for index %d", keyid); if ((sigbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || (r = sshbuf_put_string(sigbuf, session_id2, session_id2_len)) != 0 || (r = sshkey_puts(key, sigbuf)) != 0) fatal_fr(r, "assemble private key proof"); if (datlen != sshbuf_len(sigbuf) || memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) fatal_f("bad data length: %zu, hostkey proof len %zu", datlen, sshbuf_len(sigbuf)); sshbuf_free(sigbuf); is_proof = 1; } /* save session id, it will be passed on the first call */ if (session_id2_len == 0) { session_id2_len = datlen; session_id2 = xmalloc(session_id2_len); memcpy(session_id2, p, session_id2_len); } if ((key = get_hostkey_by_index(keyid)) != NULL) { if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, options.sk_provider, NULL, compat)) != 0) fatal_fr(r, "sign"); } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && auth_sock > 0) { if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, p, datlen, alg, compat)) != 0) fatal_fr(r, "agent sign"); } else fatal_f("no hostkey from index %d", keyid); debug3_f("%s %s signature len=%zu", alg, is_proof ? "hostkey proof" : "KEX", siglen); sshbuf_reset(m); if ((r = sshbuf_put_string(m, signature, siglen)) != 0) fatal_fr(r, "assemble"); free(alg); free(p); free(signature); mm_request_send(sock, MONITOR_ANS_SIGN, m); /* Turn on permissions for getpwnam */ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); return (0); } #define PUTPW(b, id) \ do { \ if ((r = sshbuf_put_string(b, \ &pwent->id, sizeof(pwent->id))) != 0) \ fatal_fr(r, "assemble %s", #id); \ } while (0) void mm_encode_server_options(struct sshbuf *m) { int r; u_int i; /* XXX this leaks raw pointers to the unpriv child processes */ if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0) fatal_fr(r, "assemble options"); #define M_CP_STROPT(x) do { \ if (options.x != NULL && \ (r = sshbuf_put_cstring(m, options.x)) != 0) \ fatal_fr(r, "assemble %s", #x); \ } while (0) #define M_CP_STRARRAYOPT(x, nx) do { \ for (i = 0; i < options.nx; i++) { \ if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \ fatal_fr(r, "assemble %s", #x); \ } \ } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT } /* Retrieves the password entry and also checks if the user is permitted */ int mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) { struct passwd *pwent; int r, allowed = 0; debug3_f("entering"); if (authctxt->attempt++ != 0) fatal_f("multiple attempts for getpwnam"); if ((r = sshbuf_get_cstring(m, &authctxt->user, NULL)) != 0) fatal_fr(r, "parse"); pwent = getpwnamallow(ssh, authctxt->user); setproctitle("%s [priv]", pwent ? authctxt->user : "unknown"); sshbuf_reset(m); if (pwent == NULL) { if ((r = sshbuf_put_u8(m, 0)) != 0) fatal_fr(r, "assemble fakepw"); authctxt->pw = fakepw(); goto out; } allowed = 1; authctxt->pw = pwent; authctxt->valid = 1; /* XXX send fake class/dir/shell, etc. */ if ((r = sshbuf_put_u8(m, 1)) != 0) fatal_fr(r, "assemble ok"); PUTPW(m, pw_uid); PUTPW(m, pw_gid); #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE PUTPW(m, pw_change); #endif #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE PUTPW(m, pw_expire); #endif if ((r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 || (r = sshbuf_put_cstring(m, "*")) != 0 || #ifdef HAVE_STRUCT_PASSWD_PW_GECOS (r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 || #endif #ifdef HAVE_STRUCT_PASSWD_PW_CLASS (r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 || #endif (r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 || (r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0) fatal_fr(r, "assemble pw"); out: ssh_packet_set_log_preamble(ssh, "%suser %s", authctxt->valid ? "authenticating" : "invalid ", authctxt->user); if (options.refuse_connection) { logit("administratively prohibited connection for " "%s%s from %.128s port %d", authctxt->valid ? "" : "invalid user ", authctxt->user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); cleanup_exit(EXIT_CONFIG_REFUSED); } /* Send active options to unpriv */ mm_encode_server_options(m); /* Create valid auth method lists */ if (auth2_setup_methods_lists(authctxt) != 0) { /* * The monitor will continue long enough to let the child * run to its packet_disconnect(), but it must not allow any * authentication to succeed. */ debug_f("no valid authentication method lists"); } debug3_f("sending MONITOR_ANS_PWNAM: %d", allowed); mm_request_send(sock, MONITOR_ANS_PWNAM, m); /* 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); #endif return (0); } int mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m) { char *banner; int r; sshbuf_reset(m); banner = auth2_read_banner(); if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0) fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); free(banner); return (0); } int mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m) { int r; monitor_permit_authentications(1); if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 || (r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0) fatal_fr(r, "parse"); debug3_f("service=%s, style=%s", authctxt->service, authctxt->style); if (strlen(authctxt->style) == 0) { free(authctxt->style); authctxt->style = NULL; } 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(struct ssh *ssh, int sock, struct sshbuf *m) { static int call_count; char *passwd; int r, authenticated; size_t plen; if (!options.password_authentication) fatal_f("password authentication not enabled"); if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0) fatal_fr(r, "parse"); /* Only authenticate if the context is valid */ authenticated = options.password_authentication && auth_password(ssh, passwd); freezero(passwd, plen); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) fatal_fr(r, "assemble"); #ifdef USE_PAM if ((r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0) fatal_fr(r, "assemble PAM"); #endif debug3("%s: sending result %d", __func__, authenticated); debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); call_count++; if (plen == 0 && call_count == 1) auth_method = "none"; else auth_method = "password"; /* Causes monitor loop to terminate if authenticated */ return (authenticated); } #ifdef BSD_AUTH int mm_answer_bsdauthquery(struct ssh *ssh, int sock, struct sshbuf *m) { char *name, *infotxt; u_int numprompts, *echo_on, success; char **prompts; int r; if (!options.kbd_interactive_authentication) fatal_f("kbd-int authentication not enabled"); success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, &prompts, &echo_on) < 0 ? 0 : 1; sshbuf_reset(m); if ((r = sshbuf_put_u32(m, success)) != 0) fatal_fr(r, "assemble"); if (success) { if ((r = sshbuf_put_cstring(m, prompts[0])) != 0) fatal_fr(r, "assemble prompt"); } debug3_f("sending challenge success: %u", success); mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); if (success) { free(name); free(infotxt); free(prompts); free(echo_on); } return (0); } int mm_answer_bsdauthrespond(struct ssh *ssh, int sock, struct sshbuf *m) { char *response; int r, authok; if (!options.kbd_interactive_authentication) fatal_f("kbd-int authentication not enabled"); if (authctxt->as == NULL) fatal_f("no bsd auth session"); if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0) fatal_fr(r, "parse"); authok = options.kbd_interactive_authentication && auth_userresponse(authctxt->as, response, 0); authctxt->as = NULL; debug3_f("<%s> = <%d>", response, authok); free(response); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authok)) != 0) fatal_fr(r, "assemble"); debug3_f("sending authenticated: %d", authok); mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); auth_method = "keyboard-interactive"; auth_submethod = "bsdauth"; return (authok != 0); } #endif #ifdef USE_PAM int mm_answer_pam_start(struct ssh *ssh, int sock, struct sshbuf *m) { if (!options.use_pam) fatal("UsePAM not set, but ended up in %s anyway", __func__); 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(struct ssh *ssh, int sock, struct sshbuf *m) { u_int ret; int r; if (!options.use_pam) fatal("%s: PAM not enabled", __func__); ret = do_pam_account(); if ((r = sshbuf_put_u32(m, ret)) != 0 || (r = sshbuf_put_stringb(m, loginmsg)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); return (ret); } static void *sshpam_ctxt, *sshpam_authok; extern KbdintDevice sshpam_device; int mm_answer_pam_init_ctx(struct ssh *ssh, int sock, struct sshbuf *m) { u_int ok = 0; int r; debug3("%s", __func__); 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; sshbuf_reset(m); if (sshpam_ctxt != NULL) { monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1); 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(struct ssh *ssh, int sock, struct sshbuf *m) { char *name = NULL, *info = NULL, **prompts = NULL; u_int i, num = 0, *echo_on = 0; int r, ret; debug3("%s", __func__); sshpam_authok = NULL; 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) 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); free(info); for (i = 0; i < num; ++i) { if ((r = sshbuf_put_cstring(m, prompts[i])) != 0 || (r = sshbuf_put_u32(m, echo_on[i])) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(prompts[i]); } free(prompts); free(echo_on); auth_method = "keyboard-interactive"; auth_submethod = "pam"; mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); return (0); } int mm_answer_pam_respond(struct ssh *ssh, int sock, struct sshbuf *m) { char **resp; u_int i, num; int r, ret; debug3("%s", __func__); if (sshpam_ctxt == NULL) fatal("%s: no context", __func__); sshpam_authok = NULL; if ((r = sshbuf_get_u32(m, &num)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (num > PAM_MAX_NUM_MSG) { fatal_f("Too many PAM messages, got %u, expected <= %u", num, (unsigned)PAM_MAX_NUM_MSG); } if (num > 0) { resp = xcalloc(num, sizeof(char *)); 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]); free(resp); } else { ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL); } 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"; if (ret == 0) sshpam_authok = sshpam_ctxt; return (0); } int 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); 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 r; } #endif int mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) { struct sshkey *key = NULL; char *cuser, *chost; u_int pubkey_auth_attempt; u_int type = 0; int r, allowed = 0; struct sshauthopt *opts = NULL; debug3_f("entering"); if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 || (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || (r = sshkey_froms(m, &key)) != 0 || (r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0) fatal_fr(r, "parse"); if (key != NULL && authctxt->valid) { switch (type) { case MM_USERKEY: auth_method = "publickey"; if (!options.pubkey_authentication) break; if (auth2_key_already_used(authctxt, key)) break; if (!key_base_type_match(auth_method, key, options.pubkey_accepted_algos)) break; allowed = user_key_allowed(ssh, authctxt->pw, key, pubkey_auth_attempt, &opts); break; case MM_HOSTKEY: 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_accepted_algos)) break; allowed = hostbased_key_allowed(ssh, authctxt->pw, cuser, chost, key); auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", cuser, chost); break; default: fatal_f("unknown key type %u", type); break; } } debug3_f("%s authentication%s: %s key is %s", auth_method, pubkey_auth_attempt ? "" : " test", (key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key), allowed ? "allowed" : "not allowed"); auth2_record_key(authctxt, 0, key); /* clear temporarily storage (used by verify) */ monitor_reset_key_state(); if (allowed) { /* Save temporarily for comparison in verify */ if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0) fatal_fr(r, "sshkey_to_blob"); key_blobtype = type; key_opts = opts; hostbased_cuser = cuser; hostbased_chost = chost; } else { /* Log failed attempt */ auth_log(ssh, 0, 0, auth_method, NULL); free(cuser); free(chost); } sshkey_free(key); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, allowed)) != 0) fatal_fr(r, "assemble"); if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) fatal_fr(r, "sshauthopt_serialise"); mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); if (!allowed) sshauthopt_free(opts); return (0); } static int monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) { struct sshbuf *b; struct sshkey *hostkey = NULL; const u_char *p; char *userstyle, *cp; size_t len; u_char type; int hostbound = 0, r, fail = 0; if ((b = sshbuf_from(data, datalen)) == NULL) fatal_f("sshbuf_from"); if (ssh->compat & SSH_OLD_SESSIONID) { 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++; if ((r = sshbuf_consume(b, session_id2_len)) != 0) fatal_fr(r, "consume"); } else { if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) fatal_fr(r, "parse sessionid"); if ((session_id2 == NULL) || (len != session_id2_len) || (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) fail++; } if ((r = sshbuf_get_u8(b, &type)) != 0) fatal_fr(r, "parse type"); if (type != SSH2_MSG_USERAUTH_REQUEST) fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse userstyle"); xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); if (strcmp(userstyle, cp) != 0) { logit("wrong user name passed to monitor: " "expected %s != %.100s", userstyle, cp); fail++; } free(userstyle); free(cp); if ((r = sshbuf_skip_string(b)) != 0 || /* service */ (r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse method"); if (strcmp("publickey", cp) != 0) { if (strcmp("publickey-hostbound-v00@openssh.com", cp) == 0) hostbound = 1; else fail++; } free(cp); if ((r = sshbuf_get_u8(b, &type)) != 0) fatal_fr(r, "parse pktype"); if (type == 0) fail++; if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ (r = sshbuf_skip_string(b)) != 0 || /* pkblob */ (hostbound && (r = sshkey_froms(b, &hostkey)) != 0)) fatal_fr(r, "parse pk"); if (sshbuf_len(b) != 0) fail++; sshbuf_free(b); if (hostkey != NULL) { /* * Ensure this is actually one of our hostkeys; unfortunately * can't check ssh->kex->initial_hostkey directly at this point * as packet state has not yet been exported to monitor. */ if (get_hostkey_index(hostkey, 1, ssh) == -1) fatal_f("hostbound hostkey does not match"); sshkey_free(hostkey); } return (fail == 0); } static int monitor_valid_hostbasedblob(const u_char *data, u_int datalen, const char *cuser, const char *chost) { struct sshbuf *b; const u_char *p; char *cp, *userstyle; size_t len; int r, fail = 0; u_char type; if ((b = sshbuf_from(data, datalen)) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) fatal_fr(r, "parse sessionid"); if ((session_id2 == NULL) || (len != session_id2_len) || (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) fail++; if ((r = sshbuf_get_u8(b, &type)) != 0) fatal_fr(r, "parse type"); if (type != SSH2_MSG_USERAUTH_REQUEST) fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse userstyle"); xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); if (strcmp(userstyle, cp) != 0) { logit("wrong user name passed to monitor: " "expected %s != %.100s", userstyle, cp); fail++; } free(userstyle); free(cp); if ((r = sshbuf_skip_string(b)) != 0 || /* service */ (r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse method"); if (strcmp(cp, "hostbased") != 0) fail++; free(cp); if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ (r = sshbuf_skip_string(b)) != 0) /* pkblob */ fatal_fr(r, "parse pk"); /* verify client host, strip trailing dot if necessary */ if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse host"); if (((len = strlen(cp)) > 0) && cp[len - 1] == '.') cp[len - 1] = '\0'; if (strcmp(cp, chost) != 0) fail++; free(cp); /* verify client user */ if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse ruser"); if (strcmp(cp, cuser) != 0) fail++; free(cp); if (sshbuf_len(b) != 0) fail++; sshbuf_free(b); return (fail == 0); } int mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) { 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, req_verify = 0, valid_data = 0; int encoded_ret; struct sshkey_sig_details *sig_details = NULL; if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) fatal_fr(r, "parse"); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal_f("bad key, not previously allowed"); /* 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_fr(r, "parse key"); switch (key_blobtype) { case MM_USERKEY: valid_data = monitor_valid_userblob(ssh, 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; break; } if (!valid_data) fatal_f("bad %s signature data blob", key_blobtype == MM_USERKEY ? "userkey" : (key_blobtype == MM_HOSTKEY ? "hostkey" : "unknown")); if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); ret = sshkey_verify(key, signature, signaturelen, data, datalen, sigalg, ssh->compat, &sig_details); debug3_f("%s %s signature using %s %s%s%s", auth_method, sshkey_type(key), sigalg == NULL ? "default" : sigalg, (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; } req_verify = (options.pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) || key_opts->require_verify; if (req_verify && (sig_details->sk_flags & SSH_SK_USER_VERIFICATION_REQD) == 0) { error("public key %s %s signature for %s%s from %.128s " "port %d rejected: user verification requirement " "not met ", sshkey_type(key), fp, authctxt->valid ? "" : "invalid user ", authctxt->user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); ret = SSH_ERR_SIGNATURE_INVALID; } } auth2_record_key(authctxt, ret == 0, key); if (key_blobtype == MM_USERKEY && ret == 0) auth_activate_options(ssh, key_opts); monitor_reset_key_state(); 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_fr(r, "assemble"); if (sig_details != NULL) { if ((r = sshbuf_put_u32(m, sig_details->sk_counter)) != 0 || (r = sshbuf_put_u8(m, sig_details->sk_flags)) != 0) fatal_fr(r, "assemble sk"); } sshkey_sig_details_free(sig_details); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); free(sigalg); free(fp); sshkey_free(key); return ret == 0; } static void mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw) { socklen_t fromlen; struct sockaddr_storage from; /* * 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 (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, session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns), (struct sockaddr *)&from, fromlen); } static void mm_session_close(Session *s) { debug3_f("session %d pid %ld", s->self, (long)s->pid); if (s->ttyfd != -1) { debug3_f("tty %s ptyfd %d", s->tty, s->ptyfd); session_pty_cleanup2(s); } session_unused(s->self); } int mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) { extern struct monitor *pmonitor; Session *s; int r, res, fd0; debug3_f("entering"); sshbuf_reset(m); s = session_new(); if (s == NULL) goto error; s->authctxt = authctxt; s->pw = authctxt->pw; s->pid = pmonitor->m_pid; res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); if (res == 0) goto error; pty_setowner(authctxt->pw, s->tty); if ((r = sshbuf_put_u32(m, 1)) != 0 || (r = sshbuf_put_cstring(m, s->tty)) != 0) fatal_fr(r, "assemble"); /* We need to trick ttyslot */ if (dup2(s->ttyfd, 0) == -1) fatal_f("dup2"); mm_record_login(ssh, s, authctxt->pw); /* Now we can close the file descriptor again */ close(0); /* send messages generated by record_login */ if ((r = sshbuf_put_stringb(m, loginmsg)) != 0) fatal_fr(r, "assemble loginmsg"); sshbuf_reset(loginmsg); mm_request_send(sock, MONITOR_ANS_PTY, m); if (mm_send_fd(sock, s->ptyfd) == -1 || mm_send_fd(sock, s->ttyfd) == -1) fatal_f("send fds failed"); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) == -1) fatal_f("open(/dev/null): %s", strerror(errno)); if (fd0 != 0) error_f("fd0 %d != 0", fd0); /* slave side of pty is not needed */ close(s->ttyfd); s->ttyfd = s->ptyfd; /* no need to dup() because nobody closes ptyfd */ s->ptymaster = s->ptyfd; debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd); return (0); error: if (s != NULL) mm_session_close(s); if ((r = sshbuf_put_u32(m, 0)) != 0) fatal_fr(r, "assemble 0"); mm_request_send(sock, MONITOR_ANS_PTY, m); return (0); } int mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m) { Session *s; char *tty; int r; debug3_f("entering"); if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) fatal_fr(r, "parse tty"); if ((s = session_by_tty(tty)) != NULL) mm_session_close(s); sshbuf_reset(m); free(tty); return (0); } int mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) { extern struct monitor *pmonitor; int res, status; debug3_f("tearing down sessions"); /* The child is terminating */ session_destroy_all(ssh, &mm_session_close); #ifdef USE_PAM if (options.use_pam) sshpam_cleanup(); #endif while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; /* Terminate process */ exit(res); } #ifdef SSH_AUDIT_EVENTS /* Report that an audit event occurred */ int 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__); 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: case SSH_LOGIN_EXCEED_MAXTRIES: case SSH_LOGIN_ROOT_DENIED: case SSH_CONNECTION_CLOSE: case SSH_INVALID_USER: audit_event(ssh, event); break; default: fatal("Audit event type %d not permitted", event); } return (0); } int mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) { char *cmd; int r; debug3("%s entering", __func__); 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); return (0); } #endif /* SSH_AUDIT_EVENTS */ void 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 kex *kex; int r; debug3_f("packet_set_state"); if ((r = ssh_packet_set_state(ssh, child_state)) != 0) fatal_fr(r, "packet_set_state"); sshbuf_free(child_state); child_state = NULL; if ((kex = ssh->kex) == NULL) fatal_f("internal error: ssh->kex == NULL"); if (session_id2_len != sshbuf_len(ssh->kex->session_id)) { fatal_f("incorrect session id length %zu (expected %u)", sshbuf_len(ssh->kex->session_id), session_id2_len); } if (memcmp(sshbuf_ptr(ssh->kex->session_id), session_id2, session_id2_len) != 0) fatal_f("session ID mismatch"); /* XXX set callbacks */ #ifdef WITH_OPENSSL kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; kex->sign = sshd_hostkey_sign; } /* This function requires careful sanity checking */ void mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { debug3_f("Waiting for new keys"); if ((child_state = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); debug3_f("GOT new keys"); } /* XXX */ #define FD_CLOSEONEXEC(x) do { \ if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \ fatal("fcntl(%d, F_SETFD)", x); \ } while (0) 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_f("socketpair: %s", strerror(errno)); #ifdef SO_ZEROIZE if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) == -1) error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); 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]; mon->m_sendfd = pair[1]; if (do_logfds) { if (pipe(pair) == -1) fatal_f("pipe: %s", strerror(errno)); FD_CLOSEONEXEC(pair[0]); FD_CLOSEONEXEC(pair[1]); mon->m_log_recvfd = pair[0]; mon->m_log_sendfd = pair[1]; } else mon->m_log_recvfd = mon->m_log_sendfd = -1; } struct monitor * monitor_init(void) { struct monitor *mon; mon = xcalloc(1, sizeof(*mon)); monitor_openfds(mon, 1); return mon; } void monitor_reinit(struct monitor *mon) { monitor_openfds(mon, 0); } #ifdef GSSAPI int mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) { gss_OID_desc goid; OM_uint32 major; size_t len; u_char *p; int r; if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); if ((r = sshbuf_get_string(m, &p, &len)) != 0) fatal_fr(r, "parse"); goid.elements = p; goid.length = len; major = ssh_gssapi_server_ctx(&gsscontext, &goid); free(goid.elements); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, major)) != 0) fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); /* Now we have a context, enable the step */ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); return (0); } int 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 */ int r; if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) fatal_fr(r, "ssh_gssapi_get_buffer_desc"); major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); free(in.value); 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_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); gss_release_buffer(&minor, &out); if (major == GSS_S_COMPLETE) { monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); } return (0); } int mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) { gss_buffer_desc gssbuf, mic; OM_uint32 ret; int r; if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) fatal_fr(r, "ssh_gssapi_get_buffer_desc"); ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); free(gssbuf.value); free(mic.value); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, ret)) != 0) fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); if (!GSS_ERROR(ret)) monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); return (0); } int mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) { int r, authenticated; const char *displayname; if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) fatal_fr(r, "assemble"); debug3_f("sending result %d", 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); } #endif /* GSSAPI */ openssh-10.0p1/PaxHeaders.10889/monitor.h100644 001750 001750 0000000003514775415623 0015013xustar0029 atime=1744182234.62678173 openssh-10.0p1/monitor.h010064400017500001750000000101311477541562300133730ustar00djmdjm/* $OpenBSD: monitor.h,v 1.24 2024/05/17 00:30:24 djm Exp $ */ /* * Copyright 2002 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MONITOR_H_ #define _MONITOR_H_ /* Please keep *_REQ_* values on even numbers and *_ANS_* on odd numbers */ enum monitor_reqtype { MONITOR_REQ_MODULI = 0, MONITOR_ANS_MODULI = 1, MONITOR_REQ_FREE = 2, MONITOR_REQ_AUTHSERV = 4, MONITOR_REQ_SIGN = 6, MONITOR_ANS_SIGN = 7, MONITOR_REQ_PWNAM = 8, MONITOR_ANS_PWNAM = 9, MONITOR_REQ_AUTH2_READ_BANNER = 10, MONITOR_ANS_AUTH2_READ_BANNER = 11, 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_KEYALLOWED = 22, MONITOR_ANS_KEYALLOWED = 23, MONITOR_REQ_KEYVERIFY = 24, MONITOR_ANS_KEYVERIFY = 25, MONITOR_REQ_KEYEXPORT = 26, MONITOR_REQ_PTY = 28, MONITOR_ANS_PTY = 29, MONITOR_REQ_PTYCLEANUP = 30, MONITOR_REQ_SESSKEY = 32, MONITOR_ANS_SESSKEY = 33, MONITOR_REQ_SESSID = 34, MONITOR_REQ_RSAKEYALLOWED = 36, MONITOR_ANS_RSAKEYALLOWED = 37, MONITOR_REQ_RSACHALLENGE = 38, MONITOR_ANS_RSACHALLENGE = 39, MONITOR_REQ_RSARESPONSE = 40, MONITOR_ANS_RSARESPONSE = 41, MONITOR_REQ_GSSSETUP = 42, MONITOR_ANS_GSSSETUP = 43, MONITOR_REQ_GSSSTEP = 44, MONITOR_ANS_GSSSTEP = 45, MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47, MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, MONITOR_REQ_TERM = 50, MONITOR_REQ_STATE = 51, MONITOR_ANS_STATE = 52, MONITOR_REQ_PAM_START = 100, MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105, MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, }; struct ssh; struct sshbuf; struct monitor { int m_recvfd; int m_sendfd; int m_log_recvfd; int m_log_sendfd; struct kex **m_pkex; pid_t m_pid; }; struct monitor *monitor_init(void); void monitor_reinit(struct monitor *); struct Authctxt; void monitor_child_preauth(struct ssh *, struct monitor *); void monitor_child_postauth(struct ssh *, struct monitor *); 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, 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 *); /* XXX: should be returned via a monitor call rather than config_fd */ void mm_encode_server_options(struct sshbuf *); struct sshbuf *pack_hostkeys(void); #endif /* _MONITOR_H_ */ openssh-10.0p1/PaxHeaders.10889/monitor_fdpass.c100644 001750 001750 0000000003614775415623 0016347xustar0030 atime=1744182234.630687598 openssh-10.0p1/monitor_fdpass.c010064400017500001750000000111221477541562300147270ustar00djmdjm/* $OpenBSD: monitor_fdpass.c,v 1.22 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright 2001 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #ifdef HAVE_SYS_UN_H #include #endif #include #include #include #ifdef HAVE_POLL_H # include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #include "log.h" #include "monitor_fdpass.h" int mm_send_fd(int sock, int fd) { #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'; ssize_t n; struct pollfd pfd; memset(&msg, 0, sizeof(msg)); #ifdef HAVE_ACCRIGHTS_IN_MSGHDR msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof(fd); #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) = fd; #endif vec.iov_base = &ch; vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; pfd.fd = sock; pfd.events = POLLOUT; while ((n = sendmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN || errno == EINTR)) { debug3_f("sendmsg(%d): %s", fd, strerror(errno)); (void)poll(&pfd, 1, -1); } if (n == -1) { error_f("sendmsg(%d): %s", fd, strerror(errno)); return -1; } if (n != 1) { error_f("sendmsg: expected sent 1 got %zd", n); return -1; } return 0; #else error("%s: file descriptor passing not supported", __func__); return -1; #endif } int mm_receive_fd(int sock) { #if defined(HAVE_RECVMSG) && (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; ssize_t n; char ch; int fd; struct pollfd pfd; memset(&msg, 0, sizeof(msg)); vec.iov_base = &ch; vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; #ifdef HAVE_ACCRIGHTS_IN_MSGHDR msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof(fd); #else memset(&cmsgbuf, 0, sizeof(cmsgbuf)); msg.msg_control = &cmsgbuf.buf; msg.msg_controllen = sizeof(cmsgbuf.buf); #endif pfd.fd = sock; pfd.events = POLLIN; while ((n = recvmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN || errno == EINTR)) { debug3_f("recvmsg: %s", strerror(errno)); (void)poll(&pfd, 1, -1); } if (n == -1) { error_f("recvmsg: %s", strerror(errno)); return -1; } if (n != 1) { error_f("recvmsg: expected received 1 got %zd", n); return -1; } #ifdef HAVE_ACCRIGHTS_IN_MSGHDR if (msg.msg_accrightslen != sizeof(fd)) { error_f("no fd"); return -1; } #else cmsg = CMSG_FIRSTHDR(&msg); if (cmsg == NULL) { error_f("no message header"); return -1; } #ifndef BROKEN_CMSG_TYPE if (cmsg->cmsg_type != SCM_RIGHTS) { error_f("expected %d got %d", SCM_RIGHTS, cmsg->cmsg_type); return -1; } #endif fd = (*(int *)CMSG_DATA(cmsg)); #endif return fd; #else error_f("file descriptor passing not supported"); return -1; #endif } openssh-10.0p1/PaxHeaders.10889/monitor_fdpass.h100644 001750 001750 0000000003614775415623 0016354xustar0030 atime=1744182234.630687598 openssh-10.0p1/monitor_fdpass.h010064400017500001750000000027721477541562300147470ustar00djmdjm/* $OpenBSD: monitor_fdpass.h,v 1.4 2007/09/04 03:21:03 djm Exp $ */ /* * Copyright 2002 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MM_FDPASS_H_ #define _MM_FDPASS_H_ int mm_send_fd(int, int); int mm_receive_fd(int); #endif /* _MM_FDPASS_H_ */ openssh-10.0p1/PaxHeaders.10889/monitor_wrap.c100644 001750 001750 0000000003614775415623 0016040xustar0030 atime=1744182234.632642295 openssh-10.0p1/monitor_wrap.c010064400017500001750000000762561477541562300144430ustar00djmdjm/* $OpenBSD: monitor_wrap.c,v 1.138 2024/10/22 06:13:00 dtucker Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #include #endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #ifdef WITH_OPENSSL #include "dh.h" #endif #include "sshbuf.h" #include "sshkey.h" #include "cipher.h" #include "kex.h" #include "hostfile.h" #include "auth.h" #include "auth-options.h" #include "packet.h" #include "mac.h" #include "log.h" #include "auth-pam.h" #include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "atomicio.h" #include "monitor_fdpass.h" #include "misc.h" #include "channels.h" #include "session.h" #include "servconf.h" #include "monitor_wrap.h" #include "srclimit.h" #include "ssherr.h" /* Imports */ extern struct monitor *pmonitor; extern struct sshbuf *loginmsg; extern ServerOptions options; void mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx) { struct sshbuf *log_msg; struct monitor *mon = (struct monitor *)ctx; int r; size_t len; if (mon->m_log_sendfd == -1) fatal_f("no log channel"); if ((log_msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */ (r = sshbuf_put_u32(log_msg, level)) != 0 || (r = sshbuf_put_u32(log_msg, forced)) != 0 || (r = sshbuf_put_cstring(log_msg, msg)) != 0) fatal_fr(r, "assemble"); if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff) fatal_f("bad length %zu", len); POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4); if (atomicio(vwrite, mon->m_log_sendfd, sshbuf_mutable_ptr(log_msg), len) != len) fatal_f("write: %s", strerror(errno)); sshbuf_free(log_msg); } static void mm_reap(void) { int status = -1; if (!mm_is_monitor()) return; while (waitpid(pmonitor->m_pid, &status, 0) == -1) { if (errno == EINTR) continue; pmonitor->m_pid = -1; fatal_f("waitpid: %s", strerror(errno)); } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) { debug_f("preauth child exited with status %d", WEXITSTATUS(status)); cleanup_exit(255); } } else if (WIFSIGNALED(status)) { error_f("preauth child terminated by signal %d", WTERMSIG(status)); cleanup_exit(signal_is_crash(WTERMSIG(status)) ? EXIT_CHILD_CRASH : 255); } else { error_f("preauth child terminated abnormally (status=0x%x)", status); cleanup_exit(EXIT_CHILD_CRASH); } } void mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m) { size_t mlen = sshbuf_len(m); u_char buf[5]; debug3_f("entering, type %d", type); if (mlen >= 0xffffffff) fatal_f("bad length %zu", mlen); POKE_U32(buf, mlen + 1); buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf) || atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen) { if (errno == EPIPE) { debug3_f("monitor fd closed"); mm_reap(); cleanup_exit(255); } fatal_f("write: %s", strerror(errno)); } } void mm_request_receive(int sock, struct sshbuf *m) { u_char buf[4], *p = NULL; u_int msg_len; int oerrno, r; debug3_f("entering"); if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) { if (errno == EPIPE) { debug3_f("monitor fd closed"); mm_reap(); cleanup_exit(255); } fatal_f("read: %s", strerror(errno)); } msg_len = PEEK_U32(buf); if (msg_len > 256 * 1024) fatal_f("read: bad msg_len %d", msg_len); sshbuf_reset(m); if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) fatal_fr(r, "reserve"); if (atomicio(read, sock, p, msg_len) != msg_len) { oerrno = errno; error_f("read: %s", strerror(errno)); if (oerrno == EPIPE) mm_reap(); cleanup_exit(255); } } void mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m) { u_char rtype; int r; debug3_f("entering, type %d", type); mm_request_receive(sock, m); if ((r = sshbuf_get_u8(m, &rtype)) != 0) fatal_fr(r, "parse"); if (rtype != type) fatal_f("read: rtype %d != type %d", rtype, type); } #ifdef WITH_OPENSSL DH * mm_choose_dh(int min, int nbits, int max) { BIGNUM *p, *g; int r; u_char success = 0; struct sshbuf *m; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(m, min)) != 0 || (r = sshbuf_put_u32(m, nbits)) != 0 || (r = sshbuf_put_u32(m, max)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m); debug3_f("waiting for MONITOR_ANS_MODULI"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m); if ((r = sshbuf_get_u8(m, &success)) != 0) fatal_fr(r, "parse success"); if (success == 0) fatal_f("MONITOR_ANS_MODULI failed"); if ((r = sshbuf_get_bignum2(m, &p)) != 0 || (r = sshbuf_get_bignum2(m, &g)) != 0) fatal_fr(r, "parse group"); debug3_f("remaining %zu", sshbuf_len(m)); sshbuf_free(m); return (dh_new_group(g, p)); } #endif int mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *hostkey_alg, const char *sk_provider, const char *sk_pin, u_int compat) { struct sshbuf *m; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshkey_puts(key, m)) != 0 || (r = sshbuf_put_string(m, data, datalen)) != 0 || (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 || (r = sshbuf_put_u32(m, compat)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m); debug3_f("waiting for MONITOR_ANS_SIGN"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m); if ((r = sshbuf_get_string(m, sigp, lenp)) != 0) fatal_fr(r, "parse"); sshbuf_free(m); debug3_f("%s signature len=%zu", hostkey_alg ? hostkey_alg : "(null)", *lenp); return (0); } void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m) { const u_char *p; size_t len; u_int i; ServerOptions *newopts; int r; if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0) fatal_fr(r, "parse opts"); if (len != sizeof(*newopts)) fatal_f("option block size mismatch"); newopts = xcalloc(sizeof(*newopts), 1); memcpy(newopts, p, sizeof(*newopts)); #define M_CP_STROPT(x) do { \ if (newopts->x != NULL && \ (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \ fatal_fr(r, "parse %s", #x); \ } while (0) #define M_CP_STRARRAYOPT(x, nx) do { \ newopts->x = newopts->nx == 0 ? \ NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \ for (i = 0; i < newopts->nx; i++) { \ if ((r = sshbuf_get_cstring(m, \ &newopts->x[i], NULL)) != 0) \ fatal_fr(r, "parse %s", #x); \ } \ } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT copy_set_server_options(&options, newopts, 1); log_change_level(options.log_level); log_verbose_reset(); for (i = 0; i < options.num_log_verbose; i++) log_verbose_add(options.log_verbose[i]); free(newopts); } #define GETPW(b, id) \ do { \ if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \ fatal_fr(r, "parse pw %s", #id); \ if (len != sizeof(pw->id)) \ fatal_fr(r, "bad length for %s", #id); \ memcpy(&pw->id, p, len); \ } while (0) struct passwd * mm_getpwnamallow(struct ssh *ssh, const char *username) { struct sshbuf *m; struct passwd *pw; size_t len; int r; u_char ok; const u_char *p; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, username)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m); debug3_f("waiting for MONITOR_ANS_PWNAM"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m); if ((r = sshbuf_get_u8(m, &ok)) != 0) fatal_fr(r, "parse success"); if (ok == 0) { pw = NULL; goto out; } /* XXX don't like passing struct passwd like this */ pw = xcalloc(sizeof(*pw), 1); GETPW(m, pw_uid); GETPW(m, pw_gid); #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE GETPW(m, pw_change); #endif #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE GETPW(m, pw_expire); #endif if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 || (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 || #ifdef HAVE_STRUCT_PASSWD_PW_GECOS (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 || #endif #ifdef HAVE_STRUCT_PASSWD_PW_CLASS (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 || #endif (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 || (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0) fatal_fr(r, "parse pw"); out: /* copy options block as a Match directive may have changed some */ mm_decode_activate_server_options(ssh, m); server_process_permitopen(ssh); server_process_channel_timeouts(ssh); kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos); sshbuf_free(m); return (pw); } char * mm_auth2_read_banner(void) { struct sshbuf *m; char *banner; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m); sshbuf_reset(m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, m); if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0) fatal_fr(r, "parse"); sshbuf_free(m); /* treat empty banner as missing banner */ if (strlen(banner) == 0) { free(banner); banner = NULL; } return (banner); } /* Inform the privileged process about service and style */ void mm_inform_authserv(char *service, char *style) { struct sshbuf *m; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, service)) != 0 || (r = sshbuf_put_cstring(m, style ? style : "")) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m); sshbuf_free(m); } /* Do the password authentication */ int mm_auth_password(struct ssh *ssh, char *password) { struct sshbuf *m; int r, authenticated = 0; #ifdef USE_PAM u_int maxtries = 0; #endif debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, password)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m); debug3_f("waiting for MONITOR_ANS_AUTHPASSWORD"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, m); if ((r = sshbuf_get_u32(m, &authenticated)) != 0) fatal_fr(r, "parse"); #ifdef USE_PAM if ((r = sshbuf_get_u32(m, &maxtries)) != 0) fatal_fr(r, "parse PAM"); if (maxtries > INT_MAX) fatal_fr(r, "bad maxtries"); sshpam_set_maxtries_reached(maxtries); #endif sshbuf_free(m); debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } int mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp) { return (mm_key_allowed(MM_USERKEY, NULL, NULL, key, pubkey_auth_attempt, authoptp)); } int mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, const char *user, const char *host, struct sshkey *key) { return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL)); } int mm_key_allowed(enum mm_keytype type, const char *user, const char *host, struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp) { struct sshbuf *m; int r, allowed = 0; struct sshauthopt *opts = NULL; debug3_f("entering"); if (authoptp != NULL) *authoptp = NULL; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(m, type)) != 0 || (r = sshbuf_put_cstring(m, user ? user : "")) != 0 || (r = sshbuf_put_cstring(m, host ? host : "")) != 0 || (r = sshkey_puts(key, m)) != 0 || (r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m); debug3_f("waiting for MONITOR_ANS_KEYALLOWED"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, m); if ((r = sshbuf_get_u32(m, &allowed)) != 0) fatal_fr(r, "parse"); if (allowed && type == MM_USERKEY && (r = sshauthopt_deserialise(m, &opts)) != 0) fatal_fr(r, "sshauthopt_deserialise"); sshbuf_free(m); if (authoptp != NULL) { *authoptp = opts; opts = NULL; } sshauthopt_free(opts); return allowed; } /* * This key verify needs to send the key type along, because the * privileged parent makes the decision if the key is allowed * for authentication. */ int mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t datalen, const char *sigalg, u_int compat, struct sshkey_sig_details **sig_detailsp) { struct sshbuf *m; u_int encoded_ret = 0; int r; u_char sig_details_present, flags; u_int counter; debug3_f("entering"); if (sig_detailsp != NULL) *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshkey_puts(key, m)) != 0 || (r = sshbuf_put_string(m, sig, siglen)) != 0 || (r = sshbuf_put_string(m, data, datalen)) != 0 || (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m); debug3_f("waiting for MONITOR_ANS_KEYVERIFY"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, m); if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 || (r = sshbuf_get_u8(m, &sig_details_present)) != 0) fatal_fr(r, "parse"); if (sig_details_present && encoded_ret == 0) { if ((r = sshbuf_get_u32(m, &counter)) != 0 || (r = sshbuf_get_u8(m, &flags)) != 0) fatal_fr(r, "parse sig_details"); if (sig_detailsp != NULL) { *sig_detailsp = xcalloc(1, sizeof(**sig_detailsp)); (*sig_detailsp)->sk_counter = counter; (*sig_detailsp)->sk_flags = flags; } } sshbuf_free(m); if (encoded_ret != 0) return SSH_ERR_SIGNATURE_INVALID; return 0; } void mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { struct sshbuf *m; int r; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = ssh_packet_get_state(ssh, m)) != 0) fatal_fr(r, "ssh_packet_get_state"); mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m); debug3_f("Finished sending state"); sshbuf_free(m); } int mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) { struct sshbuf *m; char *p, *msg; int success = 0, tmp1 = -1, tmp2 = -1, r; /* Kludge: ensure there are fds free to receive the pty/tty */ if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || (tmp2 = dup(pmonitor->m_recvfd)) == -1) { error_f("cannot allocate fds for pty"); if (tmp1 >= 0) close(tmp1); return 0; } close(tmp1); close(tmp2); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m); debug3_f("waiting for MONITOR_ANS_PTY"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m); if ((r = sshbuf_get_u32(m, &success)) != 0) fatal_fr(r, "parse success"); if (success == 0) { debug3_f("pty alloc failed"); sshbuf_free(m); return (0); } if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 || (r = sshbuf_get_cstring(m, &msg, NULL)) != 0) fatal_fr(r, "parse"); sshbuf_free(m); strlcpy(namebuf, p, namebuflen); /* Possible truncation */ free(p); if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0) fatal_fr(r, "put loginmsg"); free(msg); if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 || (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1) fatal_f("receive fds failed"); /* Success */ return (1); } void mm_session_pty_cleanup2(Session *s) { struct sshbuf *m; int r; if (s->ttyfd == -1) return; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, s->tty)) != 0) fatal_fr(r, "assmble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m); sshbuf_free(m); /* closed dup'ed master */ if (s->ptymaster != -1 && close(s->ptymaster) == -1) error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; } #ifdef USE_PAM void mm_start_pam(struct ssh *ssh) { struct sshbuf *m; debug3("%s entering", __func__); if (!options.use_pam) fatal("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m); sshbuf_free(m); } u_int mm_do_pam_account(void) { struct sshbuf *m; u_int ret; char *msg; size_t msglen; int r; debug3("%s entering", __func__); if (!options.use_pam) fatal("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_ACCOUNT, m); if ((r = sshbuf_get_u32(m, &ret)) != 0 || (r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 || (r = sshbuf_put(loginmsg, msg, msglen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(msg); sshbuf_free(m); debug3("%s returning %d", __func__, ret); return (ret); } void * mm_sshpam_init_ctx(Authctxt *authctxt) { struct sshbuf *m; int r, success; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m); debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, m); if ((r = sshbuf_get_u32(m, &success)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (success == 0) { debug3("%s: pam_init_ctx failed", __func__); sshbuf_free(m); return (NULL); } sshbuf_free(m); return (authctxt); } int mm_sshpam_query(void *ctx, char **name, char **info, u_int *num, char ***prompts, u_int **echo_on) { struct sshbuf *m; u_int i, n; int r, ret; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m); debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m); if ((r = sshbuf_get_u32(m, &ret)) != 0 || (r = sshbuf_get_cstring(m, name, NULL)) != 0 || (r = sshbuf_get_cstring(m, info, NULL)) != 0 || (r = sshbuf_get_u32(m, &n)) != 0 || (r = sshbuf_get_u32(m, num)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("%s: pam_query returned %d", __func__, ret); sshpam_set_maxtries_reached(n); if (*num > PAM_MAX_NUM_MSG) fatal("%s: received %u PAM messages, expected <= %u", __func__, *num, PAM_MAX_NUM_MSG); *prompts = xcalloc((*num + 1), sizeof(char *)); *echo_on = xcalloc((*num + 1), sizeof(u_int)); for (i = 0; i < *num; ++i) { if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 || (r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } sshbuf_free(m); return (ret); } int mm_sshpam_respond(void *ctx, u_int num, char **resp) { struct sshbuf *m; u_int n, i; int r, ret; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u32(m, num)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); for (i = 0; i < num; ++i) { if ((r = sshbuf_put_cstring(m, resp[i])) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m); debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, m); if ((r = sshbuf_get_u32(m, &n)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); ret = (int)n; /* XXX */ debug3("%s: pam_respond returned %d", __func__, ret); sshbuf_free(m); return (ret); } void mm_sshpam_free_ctx(void *ctxtp) { struct sshbuf *m; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m); debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, m); sshbuf_free(m); } #endif /* USE_PAM */ /* Request process termination */ void mm_terminate(void) { struct sshbuf *m; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m); sshbuf_free(m); } /* Request state information */ void mm_get_state(struct ssh *ssh, struct include_list *includes, struct sshbuf *conf, struct sshbuf **confdatap, uint64_t *timing_secretp, struct sshbuf **hostkeysp, struct sshbuf **keystatep, u_char **pw_namep, struct sshbuf **authinfop, struct sshbuf **auth_optsp) { struct sshbuf *m, *inc; u_char *cp; size_t len; int r; struct include_item *item; debug3_f("entering"); if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_STATE, m); debug3_f("waiting for MONITOR_ANS_STATE"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_STATE, m); if ((r = sshbuf_get_string(m, &cp, &len)) != 0 || (r = sshbuf_get_u64(m, timing_secretp)) != 0 || (r = sshbuf_froms(m, hostkeysp)) != 0 || (r = sshbuf_get_stringb(m, ssh->kex->server_version)) != 0 || (r = sshbuf_get_stringb(m, ssh->kex->client_version)) != 0 || (r = sshbuf_get_stringb(m, inc)) != 0) fatal_fr(r, "parse config"); /* postauth */ if (confdatap) { if ((r = sshbuf_froms(m, confdatap)) != 0 || (r = sshbuf_froms(m, keystatep)) != 0 || (r = sshbuf_get_string(m, pw_namep, NULL)) != 0 || (r = sshbuf_froms(m, authinfop)) != 0 || (r = sshbuf_froms(m, auth_optsp)) != 0) fatal_fr(r, "parse config postauth"); } if (conf != NULL && (r = sshbuf_put(conf, cp, len))) fatal_fr(r, "sshbuf_put"); while (sshbuf_len(inc) != 0) { item = xcalloc(1, sizeof(*item)); if ((item->contents = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 || (r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 || (r = sshbuf_get_stringb(inc, item->contents)) != 0) fatal_fr(r, "parse includes"); TAILQ_INSERT_TAIL(includes, item, entry); } free(cp); sshbuf_free(m); sshbuf_free(inc); debug3_f("done"); } static void mm_chall_setup(char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { *name = xstrdup(""); *infotxt = xstrdup(""); *numprompts = 1; *prompts = xcalloc(*numprompts, sizeof(char *)); *echo_on = xcalloc(*numprompts, sizeof(u_int)); (*echo_on)[0] = 0; } int mm_bsdauth_query(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { struct sshbuf *m; u_int success; char *challenge; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY, m); if ((r = sshbuf_get_u32(m, &success)) != 0) fatal_fr(r, "parse success"); if (success == 0) { debug3_f("no challenge"); sshbuf_free(m); return (-1); } /* Get the challenge, and format the response */ if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0) fatal_fr(r, "parse challenge"); sshbuf_free(m); mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); (*prompts)[0] = challenge; debug3_f("received challenge: %s", challenge); return (0); } int mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) { struct sshbuf *m; int r, authok; debug3_f("entering"); if (numresponses != 1) return (-1); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, responses[0])) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHRESPOND, m); if ((r = sshbuf_get_u32(m, &authok)) != 0) fatal_fr(r, "parse"); sshbuf_free(m); return ((authok == 0) ? -1 : 0); } #ifdef SSH_AUDIT_EVENTS void mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) { struct sshbuf *m; int r; debug3("%s entering", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u32(m, event)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m); sshbuf_free(m); } void mm_audit_run_command(const char *command) { struct sshbuf *m; int r; debug3("%s entering command %s", __func__, command); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_cstring(m, command)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); sshbuf_free(m); } #endif /* SSH_AUDIT_EVENTS */ #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid) { struct sshbuf *m; OM_uint32 major; int r; /* Client doesn't get to see the context */ *ctx = NULL; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m); if ((r = sshbuf_get_u32(m, &major)) != 0) fatal_fr(r, "parse"); sshbuf_free(m); return (major); } OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in, gss_buffer_desc *out, OM_uint32 *flagsp) { struct sshbuf *m; OM_uint32 major; u_int flags; int r; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, in->value, in->length)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m); if ((r = sshbuf_get_u32(m, &major)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, out)) != 0) fatal_fr(r, "parse"); if (flagsp != NULL) { if ((r = sshbuf_get_u32(m, &flags)) != 0) fatal_fr(r, "parse flags"); *flagsp = flags; } sshbuf_free(m); return (major); } OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) { struct sshbuf *m; OM_uint32 major; int r; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 || (r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC, m); if ((r = sshbuf_get_u32(m, &major)) != 0) fatal_fr(r, "parse"); sshbuf_free(m); return(major); } int mm_ssh_gssapi_userok(char *user) { struct sshbuf *m; int r, authenticated = 0; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK, m); if ((r = sshbuf_get_u32(m, &authenticated)) != 0) fatal_fr(r, "parse"); sshbuf_free(m); debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } #endif /* GSSAPI */ /* * Inform channels layer of permitopen options for a single forwarding * direction (local/remote). */ static void server_process_permitopen_list(struct ssh *ssh, int listen, char **opens, u_int num_opens) { u_int i; int port; char *host, *arg, *oarg; int where = listen ? FORWARD_REMOTE : FORWARD_LOCAL; const char *what = listen ? "permitlisten" : "permitopen"; channel_clear_permission(ssh, FORWARD_ADM, where); if (num_opens == 0) return; /* permit any */ /* handle keywords: "any" / "none" */ if (num_opens == 1 && strcmp(opens[0], "any") == 0) return; if (num_opens == 1 && strcmp(opens[0], "none") == 0) { channel_disable_admin(ssh, where); return; } /* Otherwise treat it as a list of permitted host:port */ for (i = 0; i < num_opens; i++) { oarg = arg = xstrdup(opens[i]); host = hpdelim(&arg); if (host == NULL) fatal_f("missing host in %s", what); host = cleanhostname(host); if (arg == NULL || ((port = permitopen_port(arg)) < 0)) fatal_f("bad port number in %s", what); /* Send it to channels layer */ channel_add_permission(ssh, FORWARD_ADM, where, host, port); free(oarg); } } /* * Inform channels layer of permitopen options from configuration. */ void server_process_permitopen(struct ssh *ssh) { server_process_permitopen_list(ssh, 0, options.permitted_opens, options.num_permitted_opens); server_process_permitopen_list(ssh, 1, options.permitted_listens, options.num_permitted_listens); } void server_process_channel_timeouts(struct ssh *ssh) { u_int i, secs; char *type; debug3_f("setting %u timeouts", options.num_channel_timeouts); channel_clear_timeouts(ssh); for (i = 0; i < options.num_channel_timeouts; i++) { if (parse_pattern_interval(options.channel_timeouts[i], &type, &secs) != 0) { fatal_f("internal error: bad timeout %s", options.channel_timeouts[i]); } channel_add_timeout(ssh, type, secs); free(type); } } struct connection_info * server_get_connection_info(struct ssh *ssh, int populate, int use_dns) { static struct connection_info ci; if (ssh == NULL || !populate) return &ci; ci.host = use_dns ? ssh_remote_hostname(ssh) : ssh_remote_ipaddr(ssh); 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; } openssh-10.0p1/PaxHeaders.10889/monitor_wrap.h100644 001750 001750 0000000003614775415623 0016045xustar0030 atime=1744182234.632642295 openssh-10.0p1/monitor_wrap.h010064400017500001750000000101201477541562300144220ustar00djmdjm/* $OpenBSD: monitor_wrap.h,v 1.51 2024/05/17 06:42:04 jsg Exp $ */ /* * Copyright 2002 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MM_WRAP_H_ #define _MM_WRAP_H_ enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY }; struct ssh; struct monitor; struct Authctxt; struct sshkey; struct sshauthopt; struct sshkey_sig_details; void mm_log_handler(LogLevel, int, const char *, void *); int mm_is_monitor(void); #ifdef WITH_OPENSSL DH *mm_choose_dh(int, int, int); #endif int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *, const char *, const char *, u_int compat); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(struct ssh *, const char *); char *mm_auth2_read_banner(void); 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 *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 **); void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); int mm_ssh_gssapi_userok(char *user); OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); #endif #ifdef USE_PAM 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 **); int mm_sshpam_respond(void *, u_int, char **); void mm_sshpam_free_ctx(void *); #endif #ifdef SSH_AUDIT_EVENTS #include "audit.h" void mm_audit_event(struct ssh *, ssh_audit_event_t); void mm_audit_run_command(const char *); #endif struct Session; void mm_terminate(void); int mm_pty_allocate(int *, int *, char *, size_t); void mm_session_pty_cleanup2(struct Session *); void mm_send_keystate(struct ssh *, struct monitor*); /* state */ struct include_list; void mm_get_state(struct ssh *, struct include_list *, struct sshbuf *, struct sshbuf **, uint64_t *, struct sshbuf **, struct sshbuf **, u_char **, struct sshbuf **, struct sshbuf **); /* bsdauth */ int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); int mm_bsdauth_respond(void *, u_int, char **); /* config / channels glue */ void server_process_permitopen(struct ssh *); void server_process_channel_timeouts(struct ssh *ssh); struct connection_info * server_get_connection_info(struct ssh *, int, int); #endif /* _MM_WRAP_H_ */ openssh-10.0p1/PaxHeaders.10889/msg.c100644 001750 001750 0000000003614775415623 0014106xustar0030 atime=1744182234.632642295 openssh-10.0p1/msg.c010064400017500001750000000054131477541562300124740ustar00djmdjm/* $OpenBSD: msg.c,v 1.21 2024/05/17 00:30:24 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include "sshbuf.h" #include "ssherr.h" #include "log.h" #include "atomicio.h" #include "msg.h" #include "misc.h" int ssh_msg_send(int fd, u_char type, struct sshbuf *m) { u_char buf[5]; u_int mlen = sshbuf_len(m); debug3_f("type %u len %zu", (unsigned int)type & 0xff, sshbuf_len(m)); 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_f("write: %s", strerror(errno)); return (-1); } if (atomicio(vwrite, fd, sshbuf_mutable_ptr(m), mlen) != mlen) { error_f("write: %s", strerror(errno)); return (-1); } debug3_f("done"); return (0); } int ssh_msg_recv(int fd, struct sshbuf *m) { u_char buf[4], *p; u_int msg_len; int r; debug3("ssh_msg_recv entering"); if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) { if (errno != EPIPE) error_f("read header: %s", strerror(errno)); return (-1); } msg_len = get_u32(buf); if (msg_len > sshbuf_max_size(m)) { error_f("read: bad msg_len %u", msg_len); return (-1); } sshbuf_reset(m); if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) { error_fr(r, "reserve"); return -1; } if (atomicio(read, fd, p, msg_len) != msg_len) { error_f("read: %s", strerror(errno)); return (-1); } return (0); } openssh-10.0p1/PaxHeaders.10889/msg.h100644 001750 001750 0000000003614775415623 0014113xustar0030 atime=1744182234.632642295 openssh-10.0p1/msg.h010064400017500001750000000027641477541562300125070ustar00djmdjm/* $OpenBSD: msg.h,v 1.5 2015/01/15 09:40:00 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SSH_MSG_H #define SSH_MSG_H struct sshbuf; int ssh_msg_send(int, u_char, struct sshbuf *); int ssh_msg_recv(int, struct sshbuf *); #endif openssh-10.0p1/PaxHeaders.10889/mux.c100644 001750 001750 0000000003614775415623 0014131xustar0030 atime=1744182234.638501198 openssh-10.0p1/mux.c010064400017500001750000001755601477541562300125320ustar00djmdjm/* $OpenBSD: mux.c,v 1.103 2024/10/12 10:50:37 jsg Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* ssh session multiplexing support */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #ifdef HAVE_UTIL_H # include #endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "log.h" #include "ssh.h" #include "ssh2.h" #include "pathnames.h" #include "misc.h" #include "match.h" #include "sshbuf.h" #include "channels.h" #include "msg.h" #include "packet.h" #include "monitor_fdpass.h" #include "sshpty.h" #include "sshkey.h" #include "readconf.h" #include "clientloop.h" #include "ssherr.h" /* from ssh.c */ extern int tty_flag; extern Options options; extern char *host; extern struct sshbuf *command; extern volatile sig_atomic_t quit_pending; /* Context for session open confirmation callback */ struct mux_session_confirm_ctx { u_int want_tty; u_int want_subsys; u_int want_x_fwd; u_int want_agent_fwd; struct sshbuf *cmd; char *term; struct termios tio; char **env; u_int rid; }; /* Context for stdio fwd open confirmation callback */ struct mux_stdio_confirm_ctx { u_int rid; }; /* Context for global channel callback */ struct mux_channel_confirm_ctx { u_int cid; /* channel id */ u_int rid; /* request id */ int fid; /* forward id */ }; /* fd to control socket */ int muxserver_sock = -1; /* client request id */ u_int muxclient_request_id = 0; /* Multiplexing control command */ u_int muxclient_command = 0; /* Set when signalled. */ static volatile sig_atomic_t muxclient_terminate = 0; /* PID of multiplex server */ static u_int muxserver_pid = 0; static Channel *mux_listener_channel = NULL; struct mux_master_state { int hello_rcvd; }; /* mux protocol messages */ #define MUX_MSG_HELLO 0x00000001 #define MUX_C_NEW_SESSION 0x10000002 #define MUX_C_ALIVE_CHECK 0x10000004 #define MUX_C_TERMINATE 0x10000005 #define MUX_C_OPEN_FWD 0x10000006 #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 #define MUX_C_STOP_LISTENING 0x10000009 #define MUX_C_PROXY 0x1000000f #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 #define MUX_S_EXIT_MESSAGE 0x80000004 #define MUX_S_ALIVE 0x80000005 #define MUX_S_SESSION_OPENED 0x80000006 #define MUX_S_REMOTE_PORT 0x80000007 #define MUX_S_TTY_ALLOC_FAIL 0x80000008 #define MUX_S_PROXY 0x8000000f /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ #define MUX_FWD_LOCAL 1 #define MUX_FWD_REMOTE 2 #define MUX_FWD_DYNAMIC 3 static void mux_session_confirm(struct ssh *, int, int, void *); static void mux_stdio_confirm(struct ssh *, int, int, void *); static int mux_master_process_hello(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_new_session(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_alive_check(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_terminate(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_open_fwd(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_close_fwd(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_stdio_fwd(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_stop_listening(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_proxy(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static const struct { u_int type; int (*handler)(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); } mux_master_handlers[] = { { MUX_MSG_HELLO, mux_master_process_hello }, { MUX_C_NEW_SESSION, mux_master_process_new_session }, { MUX_C_ALIVE_CHECK, mux_master_process_alive_check }, { MUX_C_TERMINATE, mux_master_process_terminate }, { MUX_C_OPEN_FWD, mux_master_process_open_fwd }, { MUX_C_CLOSE_FWD, mux_master_process_close_fwd }, { MUX_C_NEW_STDIO_FWD, mux_master_process_stdio_fwd }, { MUX_C_STOP_LISTENING, mux_master_process_stop_listening }, { MUX_C_PROXY, mux_master_process_proxy }, { 0, NULL } }; /* Cleanup callback fired on closure of mux client _session_ channel */ static void mux_master_session_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused) { Channel *cc, *c = channel_by_id(ssh, cid); debug3_f("entering for channel %d", cid); if (c == NULL) fatal_f("channel_by_id(%i) == NULL", cid); if (c->ctl_chan != -1) { if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d missing control channel %d", c->self, c->ctl_chan); c->ctl_chan = -1; cc->ctl_child_id = 0; cc->have_ctl_child_id = 0; chan_rcvd_oclose(ssh, cc); } channel_cancel_cleanup(ssh, c->self); } /* Cleanup callback fired on closure of mux client _control_ channel */ static void mux_master_control_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused) { Channel *sc, *c = channel_by_id(ssh, cid); debug3_f("entering for channel %d", cid); if (c == NULL) fatal_f("channel_by_id(%i) == NULL", cid); if (c->have_ctl_child_id) { if ((sc = channel_by_id(ssh, c->ctl_child_id)) == NULL) fatal_f("channel %d missing session channel %u", c->self, c->ctl_child_id); c->ctl_child_id = 0; c->have_ctl_child_id = 0; sc->ctl_chan = -1; if (sc->type != SSH_CHANNEL_OPEN && sc->type != SSH_CHANNEL_OPENING) { debug2_f("channel %d: not open", sc->self); chan_mark_dead(ssh, sc); } else { if (sc->istate == CHAN_INPUT_OPEN) chan_read_failed(ssh, sc); if (sc->ostate == CHAN_OUTPUT_OPEN) chan_write_failed(ssh, sc); } } channel_cancel_cleanup(ssh, c->self); } /* Check mux client environment variables before passing them to mux master. */ static int env_permitted(const char *env) { u_int i; int ret; char name[1024], *cp; if ((cp = strchr(env, '=')) == NULL || cp == env) return 0; ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env); if (ret <= 0 || (size_t)ret >= sizeof(name)) { error_f("name '%.100s...' too long", env); return 0; } for (i = 0; i < options.num_send_env; i++) if (match_pattern(name, options.send_env[i])) return 1; return 0; } /* Mux master protocol message handlers */ static int mux_master_process_hello(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { u_int ver; struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; int r; if (state == NULL) fatal_f("channel %d: c->mux_ctx == NULL", c->self); if (state->hello_rcvd) { error_f("HELLO received twice"); return -1; } if ((r = sshbuf_get_u32(m, &ver)) != 0) { error_fr(r, "parse"); return -1; } if (ver != SSHMUX_VER) { error_f("unsupported multiplexing protocol version %u " "(expected %u)", ver, SSHMUX_VER); return -1; } debug2_f("channel %d client version %u", c->self, ver); /* No extensions are presently defined */ while (sshbuf_len(m) > 0) { char *name = NULL; size_t value_len = 0; if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 || (r = sshbuf_get_string_direct(m, NULL, &value_len)) != 0) { error_fr(r, "parse extension"); return -1; } debug2_f("Unrecognised extension \"%s\" length %zu", name, value_len); free(name); } state->hello_rcvd = 1; return 0; } /* Enqueue a "ok" response to the reply buffer */ static void reply_ok(struct sshbuf *reply, u_int rid) { int r; if ((r = sshbuf_put_u32(reply, MUX_S_OK)) != 0 || (r = sshbuf_put_u32(reply, rid)) != 0) fatal_fr(r, "reply"); } /* Enqueue an error response to the reply buffer */ static void reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg) { int r; if ((r = sshbuf_put_u32(reply, type)) != 0 || (r = sshbuf_put_u32(reply, rid)) != 0 || (r = sshbuf_put_cstring(reply, msg)) != 0) fatal_fr(r, "reply"); } static int mux_master_process_new_session(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { Channel *nc; struct mux_session_confirm_ctx *cctx; char *cmd, *cp; u_int i, j, env_len, escape_char, window, packetmax; int r, new_fd[3]; /* Reply for SSHMUX_COMMAND_OPEN */ cctx = xcalloc(1, sizeof(*cctx)); cctx->term = NULL; cctx->rid = rid; cmd = NULL; cctx->env = NULL; env_len = 0; if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */ (r = sshbuf_get_u32(m, &cctx->want_tty)) != 0 || (r = sshbuf_get_u32(m, &cctx->want_x_fwd)) != 0 || (r = sshbuf_get_u32(m, &cctx->want_agent_fwd)) != 0 || (r = sshbuf_get_u32(m, &cctx->want_subsys)) != 0 || (r = sshbuf_get_u32(m, &escape_char)) != 0 || (r = sshbuf_get_cstring(m, &cctx->term, NULL)) != 0 || (r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) { malf: free(cmd); for (j = 0; j < env_len; j++) free(cctx->env[j]); free(cctx->env); free(cctx->term); free(cctx); error_f("malformed message"); return -1; } #define MUX_MAX_ENV_VARS 4096 while (sshbuf_len(m) > 0) { if ((r = sshbuf_get_cstring(m, &cp, NULL)) != 0) goto malf; if (!env_permitted(cp)) { free(cp); continue; } cctx->env = xreallocarray(cctx->env, env_len + 2, sizeof(*cctx->env)); cctx->env[env_len++] = cp; cctx->env[env_len] = NULL; if (env_len > MUX_MAX_ENV_VARS) { error_f(">%d environment variables received, " "ignoring additional", MUX_MAX_ENV_VARS); break; } } debug2_f("channel %d: request tty %d, X %d, agent %d, subsys %d, " "term \"%s\", cmd \"%s\", env %u", c->self, cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd, cctx->want_subsys, cctx->term, cmd, env_len); if ((cctx->cmd = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0) fatal_fr(r, "sshbuf_put"); free(cmd); cmd = NULL; /* Gather fds from client */ for(i = 0; i < 3; i++) { if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) { error_f("failed to receive fd %d from client", i); for (j = 0; j < i; j++) close(new_fd[j]); for (j = 0; j < env_len; j++) free(cctx->env[j]); free(cctx->env); free(cctx->term); sshbuf_free(cctx->cmd); free(cctx); reply_error(reply, MUX_S_FAILURE, rid, "did not receive file descriptors"); return -1; } } debug3_f("got fds stdin %d, stdout %d, stderr %d", new_fd[0], new_fd[1], new_fd[2]); /* XXX support multiple child sessions in future */ if (c->have_ctl_child_id) { debug2_f("session already open"); reply_error(reply, MUX_S_FAILURE, rid, "Multiple sessions not supported"); cleanup: close(new_fd[0]); close(new_fd[1]); close(new_fd[2]); free(cctx->term); if (env_len != 0) { for (i = 0; i < env_len; i++) free(cctx->env[i]); free(cctx->env); } sshbuf_free(cctx->cmd); free(cctx); return 0; } if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (!ask_permission("Allow shared connection to %s? ", host)) { debug2_f("session refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto cleanup; } } /* Try to pick up ttymodes from client before it goes raw */ if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1) error_f("tcgetattr: %s", strerror(errno)); window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; if (cctx->want_tty) { window >>= 1; packetmax >>= 1; } nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING, new_fd[0], new_fd[1], new_fd[2], window, packetmax, CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO); nc->ctl_chan = c->self; /* link session -> control channel */ c->ctl_child_id = nc->self; /* link control -> session channel */ c->have_ctl_child_id = 1; if (cctx->want_tty && escape_char != 0xffffffff) { channel_register_filter(ssh, nc->self, client_simple_escape_filter, NULL, client_filter_cleanup, client_new_escape_filter_ctx((int)escape_char)); } debug2_f("channel_new: %d linked to control channel %d", nc->self, nc->ctl_chan); channel_send_open(ssh, nc->self); channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx); c->mux_pause = 1; /* stop handling messages until open_confirm done */ channel_register_cleanup(ssh, nc->self, mux_master_session_cleanup_cb, 1); /* reply is deferred, sent by mux_session_confirm */ return 0; } static int mux_master_process_alive_check(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { int r; debug2_f("channel %d: alive check", c->self); /* prepare reply */ if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 || (r = sshbuf_put_u32(reply, rid)) != 0 || (r = sshbuf_put_u32(reply, (u_int)getpid())) != 0) fatal_fr(r, "reply"); return 0; } static int mux_master_process_terminate(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { debug2_f("channel %d: terminate request", c->self); if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (!ask_permission("Terminate shared connection to %s? ", host)) { debug2_f("termination refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); return 0; } } quit_pending = 1; reply_ok(reply, rid); /* XXX exit happens too soon - message never makes it to client */ return 0; } static char * format_forward(u_int ftype, struct Forward *fwd) { char *ret; switch (ftype) { case MUX_FWD_LOCAL: xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", (fwd->listen_path != NULL) ? fwd->listen_path : (fwd->listen_host == NULL) ? (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : fwd->listen_host, fwd->listen_port, (fwd->connect_path != NULL) ? fwd->connect_path : fwd->connect_host, fwd->connect_port); break; case MUX_FWD_DYNAMIC: xasprintf(&ret, "dynamic forward %.200s:%d -> *", (fwd->listen_host == NULL) ? (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : fwd->listen_host, fwd->listen_port); break; case MUX_FWD_REMOTE: xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", (fwd->listen_path != NULL) ? fwd->listen_path : (fwd->listen_host == NULL) ? "LOCALHOST" : fwd->listen_host, fwd->listen_port, (fwd->connect_path != NULL) ? fwd->connect_path : fwd->connect_host, fwd->connect_port); break; default: fatal_f("unknown forward type %u", ftype); } return ret; } static int compare_host(const char *a, const char *b) { if (a == NULL && b == NULL) return 1; if (a == NULL || b == NULL) return 0; return strcmp(a, b) == 0; } static int compare_forward(struct Forward *a, struct Forward *b) { if (!compare_host(a->listen_host, b->listen_host)) return 0; if (!compare_host(a->listen_path, b->listen_path)) return 0; if (a->listen_port != b->listen_port) return 0; if (!compare_host(a->connect_host, b->connect_host)) return 0; if (!compare_host(a->connect_path, b->connect_path)) return 0; if (a->connect_port != b->connect_port) return 0; return 1; } static void mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) { struct mux_channel_confirm_ctx *fctx = ctxt; char *failmsg = NULL; struct Forward *rfwd; Channel *c; struct sshbuf *out; u_int port; int r; if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { /* no channel for reply */ error_f("unknown channel"); return; } if ((out = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (fctx->fid >= options.num_remote_forwards || (options.remote_forwards[fctx->fid].connect_path == NULL && options.remote_forwards[fctx->fid].connect_host == NULL)) { xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid); goto fail; } rfwd = &options.remote_forwards[fctx->fid]; debug_f("%s for: listen %d, connect %s:%d", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : rfwd->connect_host, rfwd->connect_port); if (type == SSH2_MSG_REQUEST_SUCCESS) { if (rfwd->listen_port == 0) { if ((r = sshpkt_get_u32(ssh, &port)) != 0) fatal_fr(r, "parse port"); if (port > 65535) { fatal("Invalid allocated port %u for " "mux remote forward to %s:%d", port, rfwd->connect_host, rfwd->connect_port); } rfwd->allocated_port = (int)port; debug("Allocated port %u for mux remote forward" " to %s:%d", rfwd->allocated_port, rfwd->connect_host, rfwd->connect_port); if ((r = sshbuf_put_u32(out, MUX_S_REMOTE_PORT)) != 0 || (r = sshbuf_put_u32(out, fctx->rid)) != 0 || (r = sshbuf_put_u32(out, rfwd->allocated_port)) != 0) fatal_fr(r, "reply"); channel_update_permission(ssh, rfwd->handle, rfwd->allocated_port); } else { reply_ok(out, fctx->rid); } goto out; } else { if (rfwd->listen_port == 0) channel_update_permission(ssh, rfwd->handle, -1); if (rfwd->listen_path != NULL) xasprintf(&failmsg, "remote port forwarding failed for " "listen path %s", rfwd->listen_path); else xasprintf(&failmsg, "remote port forwarding failed for " "listen port %d", rfwd->listen_port); debug2_f("clearing registered forwarding for listen %d, " "connect %s:%d", rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : rfwd->connect_host, rfwd->connect_port); free(rfwd->listen_host); free(rfwd->listen_path); free(rfwd->connect_host); free(rfwd->connect_path); memset(rfwd, 0, sizeof(*rfwd)); } fail: error_f("%s", failmsg); reply_error(out, MUX_S_FAILURE, fctx->rid, failmsg); free(failmsg); out: if ((r = sshbuf_put_stringb(c->output, out)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(out); if (c->mux_pause <= 0) fatal_f("mux_pause %d", c->mux_pause); c->mux_pause = 0; /* start processing messages again */ } static int mux_master_process_open_fwd(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { struct Forward fwd; char *fwd_desc = NULL; char *listen_addr, *connect_addr; u_int ftype; u_int lport, cport; int r, i, ret = 0, freefwd = 1; memset(&fwd, 0, sizeof(fwd)); /* XXX - lport/cport check redundant */ if ((r = sshbuf_get_u32(m, &ftype)) != 0 || (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &lport)) != 0 || (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &cport)) != 0 || (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { error_f("malformed message"); ret = -1; goto out; } if (*listen_addr == '\0') { free(listen_addr); listen_addr = NULL; } if (*connect_addr == '\0') { free(connect_addr); connect_addr = NULL; } memset(&fwd, 0, sizeof(fwd)); fwd.listen_port = lport; if (fwd.listen_port == PORT_STREAMLOCAL) fwd.listen_path = listen_addr; else fwd.listen_host = listen_addr; fwd.connect_port = cport; if (fwd.connect_port == PORT_STREAMLOCAL) fwd.connect_path = connect_addr; else fwd.connect_host = connect_addr; debug2_f("channel %d: request %s", c->self, (fwd_desc = format_forward(ftype, &fwd))); if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE && ftype != MUX_FWD_DYNAMIC) { logit_f("invalid forwarding type %u", ftype); invalid: free(listen_addr); free(connect_addr); reply_error(reply, MUX_S_FAILURE, rid, "Invalid forwarding request"); return 0; } if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { logit_f("streamlocal and dynamic forwards " "are mutually exclusive"); goto invalid; } if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { logit_f("invalid listen port %u", fwd.listen_port); goto invalid; } if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { logit_f("invalid connect port %u", fwd.connect_port); goto invalid; } if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { logit_f("missing connect host"); goto invalid; } /* Skip forwards that have already been requested */ switch (ftype) { case MUX_FWD_LOCAL: case MUX_FWD_DYNAMIC: for (i = 0; i < options.num_local_forwards; i++) { if (compare_forward(&fwd, options.local_forwards + i)) { exists: debug2_f("found existing forwarding"); reply_ok(reply, rid); goto out; } } break; case MUX_FWD_REMOTE: for (i = 0; i < options.num_remote_forwards; i++) { if (!compare_forward(&fwd, options.remote_forwards + i)) continue; if (fwd.listen_port != 0) goto exists; debug2_f("found allocated port"); if ((r = sshbuf_put_u32(reply, MUX_S_REMOTE_PORT)) != 0 || (r = sshbuf_put_u32(reply, rid)) != 0 || (r = sshbuf_put_u32(reply, options.remote_forwards[i].allocated_port)) != 0) fatal_fr(r, "reply FWD_REMOTE"); goto out; } break; } if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (!ask_permission("Open %s on %s?", fwd_desc, host)) { debug2_f("forwarding refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto out; } } if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { fail: logit_f("requested %s failed", fwd_desc); reply_error(reply, MUX_S_FAILURE, rid, "Port forwarding failed"); goto out; } add_local_forward(&options, &fwd); freefwd = 0; } else { struct mux_channel_confirm_ctx *fctx; fwd.handle = channel_request_remote_forwarding(ssh, &fwd); if (fwd.handle < 0) goto fail; add_remote_forward(&options, &fwd); fctx = xcalloc(1, sizeof(*fctx)); fctx->cid = c->self; fctx->rid = rid; fctx->fid = options.num_remote_forwards - 1; client_register_global_confirm(mux_confirm_remote_forward, fctx); freefwd = 0; c->mux_pause = 1; /* wait for mux_confirm_remote_forward */ /* delayed reply in mux_confirm_remote_forward */ goto out; } reply_ok(reply, rid); out: free(fwd_desc); if (freefwd) { free(fwd.listen_host); free(fwd.listen_path); free(fwd.connect_host); free(fwd.connect_path); } return ret; } static int mux_master_process_close_fwd(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { struct Forward fwd, *found_fwd; char *fwd_desc = NULL; const char *error_reason = NULL; char *listen_addr = NULL, *connect_addr = NULL; u_int ftype; int r, i, ret = 0; u_int lport, cport; memset(&fwd, 0, sizeof(fwd)); if ((r = sshbuf_get_u32(m, &ftype)) != 0 || (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &lport)) != 0 || (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &cport)) != 0 || (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { error_f("malformed message"); ret = -1; goto out; } if (*listen_addr == '\0') { free(listen_addr); listen_addr = NULL; } if (*connect_addr == '\0') { free(connect_addr); connect_addr = NULL; } memset(&fwd, 0, sizeof(fwd)); fwd.listen_port = lport; if (fwd.listen_port == PORT_STREAMLOCAL) fwd.listen_path = listen_addr; else fwd.listen_host = listen_addr; fwd.connect_port = cport; if (fwd.connect_port == PORT_STREAMLOCAL) fwd.connect_path = connect_addr; else fwd.connect_host = connect_addr; debug2_f("channel %d: request cancel %s", c->self, (fwd_desc = format_forward(ftype, &fwd))); /* make sure this has been requested */ found_fwd = NULL; switch (ftype) { case MUX_FWD_LOCAL: case MUX_FWD_DYNAMIC: for (i = 0; i < options.num_local_forwards; i++) { if (compare_forward(&fwd, options.local_forwards + i)) { found_fwd = options.local_forwards + i; break; } } break; case MUX_FWD_REMOTE: for (i = 0; i < options.num_remote_forwards; i++) { if (compare_forward(&fwd, options.remote_forwards + i)) { found_fwd = options.remote_forwards + i; break; } } break; } if (found_fwd == NULL) error_reason = "port not forwarded"; else if (ftype == MUX_FWD_REMOTE) { /* * This shouldn't fail unless we confused the host/port * between options.remote_forwards and permitted_opens. * However, for dynamic allocated listen ports we need * to use the actual listen port. */ if (channel_request_rforward_cancel(ssh, found_fwd) == -1) error_reason = "port not in permitted opens"; } else { /* local and dynamic forwards */ /* Ditto */ if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port, &options.fwd_opts) == -1) error_reason = "port not found"; } if (error_reason != NULL) reply_error(reply, MUX_S_FAILURE, rid, error_reason); else { reply_ok(reply, rid); free(found_fwd->listen_host); free(found_fwd->listen_path); free(found_fwd->connect_host); free(found_fwd->connect_path); found_fwd->listen_host = found_fwd->connect_host = NULL; found_fwd->listen_path = found_fwd->connect_path = NULL; found_fwd->listen_port = found_fwd->connect_port = 0; } out: free(fwd_desc); free(listen_addr); free(connect_addr); return ret; } static int mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { Channel *nc; char *chost = NULL; u_int _cport, i, j; int ok = 0, cport, r, new_fd[2]; struct mux_stdio_confirm_ctx *cctx; if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */ (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || (r = sshbuf_get_u32(m, &_cport)) != 0) { free(chost); error_f("malformed message"); return -1; } if (_cport == (u_int)PORT_STREAMLOCAL) cport = PORT_STREAMLOCAL; else if (_cport <= INT_MAX) cport = (int)_cport; else { free(chost); error_f("invalid port 0x%x", _cport); return -1; } debug2_f("channel %d: stdio fwd to %s:%d", c->self, chost, cport); /* Gather fds from client */ for(i = 0; i < 2; i++) { if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) { error_f("failed to receive fd %d from client", i); for (j = 0; j < i; j++) close(new_fd[j]); free(chost); /* prepare reply */ reply_error(reply, MUX_S_FAILURE, rid, "did not receive file descriptors"); return -1; } } debug3_f("got fds stdin %d, stdout %d", new_fd[0], new_fd[1]); /* XXX support multiple child sessions in future */ if (c->have_ctl_child_id) { debug2_f("session already open"); reply_error(reply, MUX_S_FAILURE, rid, "Multiple sessions not supported"); cleanup: close(new_fd[0]); close(new_fd[1]); free(chost); return 0; } if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (cport == PORT_STREAMLOCAL) { ok = ask_permission("Allow forward to path %s", chost); } else { ok = ask_permission("Allow forward to [%s]:%d? ", chost, cport); } if (!ok) { debug2_f("stdio fwd refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto cleanup; } } nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1], CHANNEL_NONBLOCK_STDIO); free(chost); nc->ctl_chan = c->self; /* link session -> control channel */ c->ctl_child_id = nc->self; /* link control -> session channel */ c->have_ctl_child_id = 1; debug2_f("channel_new: %d control %d", nc->self, nc->ctl_chan); channel_register_cleanup(ssh, nc->self, mux_master_session_cleanup_cb, 1); cctx = xcalloc(1, sizeof(*cctx)); cctx->rid = rid; channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx); c->mux_pause = 1; /* stop handling messages until open_confirm done */ /* reply is deferred, sent by mux_session_confirm */ return 0; } /* Callback on open confirmation in mux master for a mux stdio fwd session. */ static void mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) { struct mux_stdio_confirm_ctx *cctx = arg; Channel *c, *cc; struct sshbuf *reply; int r; if (cctx == NULL) fatal_f("cctx == NULL"); if ((c = channel_by_id(ssh, id)) == NULL) fatal_f("no channel for id %d", id); if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d lacks control channel %d", id, c->ctl_chan); if ((reply = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (!success) { debug3_f("sending failure reply"); reply_error(reply, MUX_S_FAILURE, cctx->rid, "Session open refused by peer"); /* prepare reply */ goto done; } debug3_f("sending success reply"); /* prepare reply */ if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 || (r = sshbuf_put_u32(reply, cctx->rid)) != 0 || (r = sshbuf_put_u32(reply, c->self)) != 0) fatal_fr(r, "reply"); done: /* Send reply */ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(reply); if (cc->mux_pause <= 0) fatal_f("mux_pause %d", cc->mux_pause); cc->mux_pause = 0; /* start processing messages again */ c->open_confirm_ctx = NULL; free(cctx); } static int mux_master_process_stop_listening(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { debug_f("channel %d: stop listening", c->self); if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (!ask_permission("Disable further multiplexing on shared " "connection to %s? ", host)) { debug2_f("stop listen refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); return 0; } } if (mux_listener_channel != NULL) { channel_free(ssh, mux_listener_channel); client_stop_mux(); free(options.control_path); options.control_path = NULL; mux_listener_channel = NULL; muxserver_sock = -1; } reply_ok(reply, rid); return 0; } static int mux_master_process_proxy(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { int r; debug_f("channel %d: proxy request", c->self); c->mux_rcb = channel_proxy_downstream; if ((r = sshbuf_put_u32(reply, MUX_S_PROXY)) != 0 || (r = sshbuf_put_u32(reply, rid)) != 0) fatal_fr(r, "reply"); return 0; } /* Channel callbacks fired on read/write from mux client fd */ static int mux_master_read_cb(struct ssh *ssh, Channel *c) { struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; struct sshbuf *in = NULL, *out = NULL; u_int type, rid, i; int r, ret = -1; if ((out = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); /* Setup ctx and */ if (c->mux_ctx == NULL) { state = xcalloc(1, sizeof(*state)); c->mux_ctx = state; channel_register_cleanup(ssh, c->self, mux_master_control_cleanup_cb, 0); /* Send hello */ if ((r = sshbuf_put_u32(out, MUX_MSG_HELLO)) != 0 || (r = sshbuf_put_u32(out, SSHMUX_VER)) != 0) fatal_fr(r, "reply"); /* no extensions */ if ((r = sshbuf_put_stringb(c->output, out)) != 0) fatal_fr(r, "enqueue"); debug3_f("channel %d: hello sent", c->self); ret = 0; goto out; } /* Channel code ensures that we receive whole packets */ if ((r = sshbuf_froms(c->input, &in)) != 0) { malf: error_f("malformed message"); goto out; } if ((r = sshbuf_get_u32(in, &type)) != 0) goto malf; debug3_f("channel %d packet type 0x%08x len %zu", c->self, type, sshbuf_len(in)); if (type == MUX_MSG_HELLO) rid = 0; else { if (!state->hello_rcvd) { error_f("expected MUX_MSG_HELLO(0x%08x), " "received 0x%08x", MUX_MSG_HELLO, type); goto out; } if ((r = sshbuf_get_u32(in, &rid)) != 0) goto malf; } for (i = 0; mux_master_handlers[i].handler != NULL; i++) { if (type == mux_master_handlers[i].type) { ret = mux_master_handlers[i].handler(ssh, rid, c, in, out); break; } } if (mux_master_handlers[i].handler == NULL) { error_f("unsupported mux message 0x%08x", type); reply_error(out, MUX_S_FAILURE, rid, "unsupported request"); ret = 0; } /* Enqueue reply packet */ if (sshbuf_len(out) != 0 && (r = sshbuf_put_stringb(c->output, out)) != 0) fatal_fr(r, "enqueue"); out: sshbuf_free(in); sshbuf_free(out); return ret; } void mux_exit_message(struct ssh *ssh, Channel *c, int exitval) { struct sshbuf *m; Channel *mux_chan; int r; debug3_f("channel %d: exit message, exitval %d", c->self, exitval); if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d missing mux %d", c->self, c->ctl_chan); /* Append exit message packet to control socket output queue */ if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_S_EXIT_MESSAGE)) != 0 || (r = sshbuf_put_u32(m, c->self)) != 0 || (r = sshbuf_put_u32(m, exitval)) != 0 || (r = sshbuf_put_stringb(mux_chan->output, m)) != 0) fatal_fr(r, "reply"); sshbuf_free(m); } void mux_tty_alloc_failed(struct ssh *ssh, Channel *c) { struct sshbuf *m; Channel *mux_chan; int r; debug3_f("channel %d: TTY alloc failed", c->self); if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d missing mux %d", c->self, c->ctl_chan); /* Append exit message packet to control socket output queue */ if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_S_TTY_ALLOC_FAIL)) != 0 || (r = sshbuf_put_u32(m, c->self)) != 0 || (r = sshbuf_put_stringb(mux_chan->output, m)) != 0) fatal_fr(r, "reply"); sshbuf_free(m); } /* Prepare a mux master to listen on a Unix domain socket. */ void muxserver_listen(struct ssh *ssh) { mode_t old_umask; char *orig_control_path = options.control_path; char rbuf[16+1]; u_int i, r; int oerrno; if (options.control_path == NULL || options.control_master == SSHCTL_MASTER_NO) return; debug("setting up multiplex master socket"); /* * Use a temporary path before listen so we can pseudo-atomically * establish the listening socket in its final location to avoid * other processes racing in between bind() and listen() and hitting * an unready socket. */ for (i = 0; i < sizeof(rbuf) - 1; i++) { r = arc4random_uniform(26+26+10); rbuf[i] = (r < 26) ? 'a' + r : (r < 26*2) ? 'A' + r - 26 : '0' + r - 26 - 26; } rbuf[sizeof(rbuf) - 1] = '\0'; options.control_path = NULL; xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); debug3_f("temporary control path %s", options.control_path); old_umask = umask(0177); muxserver_sock = unix_listener(options.control_path, 64, 0); oerrno = errno; umask(old_umask); if (muxserver_sock < 0) { if (oerrno == EINVAL || oerrno == EADDRINUSE) { error("ControlSocket %s already exists, " "disabling multiplexing", options.control_path); disable_mux_master: if (muxserver_sock != -1) { close(muxserver_sock); muxserver_sock = -1; } free(orig_control_path); free(options.control_path); options.control_path = NULL; options.control_master = SSHCTL_MASTER_NO; return; } else { /* unix_listener() logs the error */ cleanup_exit(255); } } /* Now atomically "move" the mux socket into position */ if (link(options.control_path, orig_control_path) != 0) { if (errno != EEXIST) { fatal_f("link mux listener %s => %s: %s", options.control_path, orig_control_path, strerror(errno)); } error("ControlSocket %s already exists, disabling multiplexing", orig_control_path); unlink(options.control_path); goto disable_mux_master; } unlink(options.control_path); free(options.control_path); options.control_path = orig_control_path; set_nonblock(muxserver_sock); mux_listener_channel = channel_new(ssh, "mux listener", SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, options.control_path, 1); mux_listener_channel->mux_rcb = mux_master_read_cb; debug3_f("mux listener channel %d fd %d", mux_listener_channel->self, mux_listener_channel->sock); } /* Callback on open confirmation in mux master for a mux client session. */ static void mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) { struct mux_session_confirm_ctx *cctx = arg; const char *display; Channel *c, *cc; int i, r; struct sshbuf *reply; if (cctx == NULL) fatal_f("cctx == NULL"); if ((c = channel_by_id(ssh, id)) == NULL) fatal_f("no channel for id %d", id); if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d lacks control channel %d", id, c->ctl_chan); if ((reply = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (!success) { debug3_f("sending failure reply"); reply_error(reply, MUX_S_FAILURE, cctx->rid, "Session open refused by peer"); goto done; } display = getenv("DISPLAY"); if (cctx->want_x_fwd && options.forward_x11 && display != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ if (client_x11_get_proto(ssh, display, options.xauth_location, options.forward_x11_trusted, options.forward_x11_timeout, &proto, &data) == 0) { /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); x11_request_forwarding_with_spoofing(ssh, id, display, proto, data, 1); /* XXX exit_on_forward_failure */ client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); } } if (cctx->want_agent_fwd && options.forward_agent) { debug("Requesting authentication agent forwarding."); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send"); } client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys, cctx->term, &cctx->tio, c->rfd, cctx->cmd, cctx->env); debug3_f("sending success reply"); /* prepare reply */ if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 || (r = sshbuf_put_u32(reply, cctx->rid)) != 0 || (r = sshbuf_put_u32(reply, c->self)) != 0) fatal_fr(r, "reply"); done: /* Send reply */ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(reply); if (cc->mux_pause <= 0) fatal_f("mux_pause %d", cc->mux_pause); cc->mux_pause = 0; /* start processing messages again */ c->open_confirm_ctx = NULL; sshbuf_free(cctx->cmd); free(cctx->term); if (cctx->env != NULL) { for (i = 0; cctx->env[i] != NULL; i++) free(cctx->env[i]); free(cctx->env); } free(cctx); } /* ** Multiplexing client support */ /* Exit signal handler */ static void control_client_sighandler(int signo) { muxclient_terminate = signo; } /* * Relay signal handler - used to pass some signals from mux client to * mux master. */ static void control_client_sigrelay(int signo) { int save_errno = errno; if (muxserver_pid > 1) kill(muxserver_pid, signo); errno = save_errno; } static int mux_client_read(int fd, struct sshbuf *b, size_t need, int timeout_ms) { size_t have; ssize_t len; u_char *p; int r; if ((r = sshbuf_reserve(b, need, &p)) != 0) fatal_fr(r, "reserve"); for (have = 0; have < need; ) { if (muxclient_terminate) { errno = EINTR; return -1; } len = read(fd, p + have, need - have); if (len == -1) { switch (errno) { #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif case EAGAIN: if (waitrfd(fd, &timeout_ms, &muxclient_terminate) == -1 && errno != EINTR) return -1; /* timeout */ /* FALLTHROUGH */ case EINTR: continue; default: return -1; } } if (len == 0) { errno = EPIPE; return -1; } have += (size_t)len; } return 0; } static int mux_client_write_packet(int fd, struct sshbuf *m) { struct sshbuf *queue; u_int have, need; int r, oerrno, len; const u_char *ptr; struct pollfd pfd; pfd.fd = fd; pfd.events = POLLOUT; if ((queue = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_stringb(queue, m)) != 0) fatal_fr(r, "enqueue"); need = sshbuf_len(queue); ptr = sshbuf_ptr(queue); for (have = 0; have < need; ) { if (muxclient_terminate) { sshbuf_free(queue); errno = EINTR; return -1; } len = write(fd, ptr + have, need - have); if (len == -1) { switch (errno) { #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif case EAGAIN: (void)poll(&pfd, 1, -1); /* FALLTHROUGH */ case EINTR: continue; default: oerrno = errno; sshbuf_free(queue); errno = oerrno; return -1; } } if (len == 0) { sshbuf_free(queue); errno = EPIPE; return -1; } have += (u_int)len; } sshbuf_free(queue); return 0; } static int mux_client_read_packet_timeout(int fd, struct sshbuf *m, int timeout_ms) { struct sshbuf *queue; size_t need, have; const u_char *ptr; int r, oerrno; if ((queue = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (mux_client_read(fd, queue, 4, timeout_ms) != 0) { if ((oerrno = errno) == EPIPE) debug3_f("read header failed: %s", strerror(errno)); sshbuf_free(queue); errno = oerrno; return -1; } need = PEEK_U32(sshbuf_ptr(queue)); if (mux_client_read(fd, queue, need, timeout_ms) != 0) { oerrno = errno; debug3_f("read body failed: %s", strerror(errno)); sshbuf_free(queue); errno = oerrno; return -1; } if ((r = sshbuf_get_string_direct(queue, &ptr, &have)) != 0 || (r = sshbuf_put(m, ptr, have)) != 0) fatal_fr(r, "dequeue"); sshbuf_free(queue); return 0; } static int mux_client_read_packet(int fd, struct sshbuf *m) { return mux_client_read_packet_timeout(fd, m, -1); } static int mux_client_hello_exchange(int fd, int timeout_ms) { struct sshbuf *m; u_int type, ver; int r, ret = -1; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_MSG_HELLO)) != 0 || (r = sshbuf_put_u32(m, SSHMUX_VER)) != 0) fatal_fr(r, "assemble hello"); /* no extensions */ if (mux_client_write_packet(fd, m) != 0) { debug_f("write packet: %s", strerror(errno)); goto out; } sshbuf_reset(m); /* Read their HELLO */ if (mux_client_read_packet_timeout(fd, m, timeout_ms) != 0) { debug_f("read packet failed"); goto out; } if ((r = sshbuf_get_u32(m, &type)) != 0) fatal_fr(r, "parse type"); if (type != MUX_MSG_HELLO) { error_f("expected HELLO (%u) got %u", MUX_MSG_HELLO, type); goto out; } if ((r = sshbuf_get_u32(m, &ver)) != 0) fatal_fr(r, "parse version"); if (ver != SSHMUX_VER) { error("Unsupported multiplexing protocol version %d " "(expected %d)", ver, SSHMUX_VER); goto out; } debug2_f("master version %u", ver); /* No extensions are presently defined */ while (sshbuf_len(m) > 0) { char *name = NULL; if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 || (r = sshbuf_skip_string(m)) != 0) { /* value */ error_fr(r, "parse extension"); goto out; } debug2("Unrecognised master extension \"%s\"", name); free(name); } /* success */ ret = 0; out: sshbuf_free(m); return ret; } static u_int mux_client_request_alive(int fd) { struct sshbuf *m; char *e; u_int pid, type, rid; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_ALIVE_CHECK)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) fatal_fr(r, "assemble"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { sshbuf_free(m); return 0; } if ((r = sshbuf_get_u32(m, &type)) != 0) fatal_fr(r, "parse type"); if (type != MUX_S_ALIVE) { if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal_f("master returned error: %s", e); } if ((r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse remote ID"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); if ((r = sshbuf_get_u32(m, &pid)) != 0) fatal_fr(r, "parse PID"); sshbuf_free(m); debug3_f("done pid = %u", pid); muxclient_request_id++; return pid; } static void mux_client_request_terminate(int fd) { struct sshbuf *m; char *e; u_int type, rid; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_TERMINATE)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { /* Remote end exited already */ if (errno == EPIPE) { sshbuf_free(m); return; } fatal_f("read from master failed: %s", strerror(errno)); } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); switch (type) { case MUX_S_OK: break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal("Master refused termination request: %s", e); case MUX_S_FAILURE: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal_f("termination request failed: %s", e); default: fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; } static int mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) { struct sshbuf *m; char *e, *fwd_desc; const char *lhost, *chost; u_int type, rid; int r; fwd_desc = format_forward(ftype, fwd); debug("Requesting %s %s", cancel_flag ? "cancellation of" : "forwarding of", fwd_desc); free(fwd_desc); type = cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD; if (fwd->listen_path != NULL) lhost = fwd->listen_path; else if (fwd->listen_host == NULL) lhost = ""; else if (*fwd->listen_host == '\0') lhost = "*"; else lhost = fwd->listen_host; if (fwd->connect_path != NULL) chost = fwd->connect_path; else if (fwd->connect_host == NULL) chost = ""; else chost = fwd->connect_host; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, type)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 || (r = sshbuf_put_u32(m, ftype)) != 0 || (r = sshbuf_put_cstring(m, lhost)) != 0 || (r = sshbuf_put_u32(m, fwd->listen_port)) != 0 || (r = sshbuf_put_cstring(m, chost)) != 0 || (r = sshbuf_put_u32(m, fwd->connect_port)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { sshbuf_free(m); return -1; } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); switch (type) { case MUX_S_OK: break; case MUX_S_REMOTE_PORT: if (cancel_flag) fatal_f("got MUX_S_REMOTE_PORT for cancel"); if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0) fatal_fr(r, "parse port"); verbose("Allocated port %u for remote forward to %s:%d", fwd->allocated_port, fwd->connect_host ? fwd->connect_host : "", fwd->connect_port); if (muxclient_command == SSHMUX_COMMAND_FORWARD) fprintf(stdout, "%i\n", fwd->allocated_port); break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); sshbuf_free(m); error("Master refused forwarding request: %s", e); return -1; case MUX_S_FAILURE: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); sshbuf_free(m); error_f("forwarding request failed: %s", e); return -1; default: fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; return 0; } static int mux_client_forwards(int fd, int cancel_flag) { int i, ret = 0; debug3_f("%s forwardings: %d local, %d remote", cancel_flag ? "cancel" : "request", options.num_local_forwards, options.num_remote_forwards); /* XXX ExitOnForwardingFailure */ for (i = 0; i < options.num_local_forwards; i++) { if (mux_client_forward(fd, cancel_flag, options.local_forwards[i].connect_port == 0 ? MUX_FWD_DYNAMIC : MUX_FWD_LOCAL, options.local_forwards + i) != 0) ret = -1; } for (i = 0; i < options.num_remote_forwards; i++) { if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE, options.remote_forwards + i) != 0) ret = -1; } return ret; } static int mux_client_request_session(int fd) { struct sshbuf *m; char *e; const char *term = NULL; u_int i, echar, rid, sid, esid, exitval, type, exitval_seen; extern char **environ; int r, rawmode = 0; debug3_f("entering"); if ((muxserver_pid = mux_client_request_alive(fd)) == 0) { error_f("master alive request failed"); return -1; } ssh_signal(SIGPIPE, SIG_IGN); if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1) fatal_f("stdfd_devnull failed"); if ((term = lookup_env_in_list("TERM", options.setenv, options.num_setenv)) == NULL || *term == '\0') term = getenv("TERM"); echar = 0xffffffff; if (options.escape_char != SSH_ESCAPECHAR_NONE) echar = (u_int)options.escape_char; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_NEW_SESSION)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 || (r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_u32(m, tty_flag)) != 0 || (r = sshbuf_put_u32(m, options.forward_x11)) != 0 || (r = sshbuf_put_u32(m, options.forward_agent)) != 0 || (r = sshbuf_put_u32(m, options.session_type == SESSION_TYPE_SUBSYSTEM)) != 0 || (r = sshbuf_put_u32(m, echar)) != 0 || (r = sshbuf_put_cstring(m, term == NULL ? "" : term)) != 0 || (r = sshbuf_put_stringb(m, command)) != 0) fatal_fr(r, "request"); /* Pass environment */ if (options.num_send_env > 0 && environ != NULL) { for (i = 0; environ[i] != NULL; i++) { if (!env_permitted(environ[i])) continue; if ((r = sshbuf_put_cstring(m, environ[i])) != 0) fatal_fr(r, "request sendenv"); } } for (i = 0; i < options.num_setenv; i++) { if ((r = sshbuf_put_cstring(m, options.setenv[i])) != 0) fatal_fr(r, "request setenv"); } if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); /* Send the stdio file descriptors */ if (mm_send_fd(fd, STDIN_FILENO) == -1 || mm_send_fd(fd, STDOUT_FILENO) == -1 || mm_send_fd(fd, STDERR_FILENO) == -1) fatal_f("send fds failed"); debug3_f("session request sent"); /* Read their reply */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { error_f("read from master failed: %s", strerror(errno)); sshbuf_free(m); return -1; } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); switch (type) { case MUX_S_SESSION_OPENED: if ((r = sshbuf_get_u32(m, &sid)) != 0) fatal_fr(r, "parse session ID"); debug_f("master session id: %u", sid); break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); error("Master refused session request: %s", e); sshbuf_free(m); return -1; case MUX_S_FAILURE: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); error_f("session request failed: %s", e); sshbuf_free(m); return -1; default: sshbuf_free(m); error_f("unexpected response from master 0x%08x", type); return -1; } muxclient_request_id++; if (pledge("stdio proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); platform_pledge_mux(); ssh_signal(SIGHUP, control_client_sighandler); ssh_signal(SIGINT, control_client_sighandler); ssh_signal(SIGTERM, control_client_sighandler); ssh_signal(SIGWINCH, control_client_sigrelay); if (options.fork_after_authentication) daemon(1, 1); else { rawmode = tty_flag; if (tty_flag) { enter_raw_mode( options.request_tty == REQUEST_TTY_FORCE); } } /* * Stick around until the controlee closes the client_fd. * Before it does, it is expected to write an exit message. * This process must read the value and wait for the closure of * the client_fd; if this one closes early, the multiplex master will * terminate early too (possibly losing data). */ for (exitval = 255, exitval_seen = 0;;) { sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) break; if ((r = sshbuf_get_u32(m, &type)) != 0) fatal_fr(r, "parse type"); switch (type) { case MUX_S_TTY_ALLOC_FAIL: if ((r = sshbuf_get_u32(m, &esid)) != 0) fatal_fr(r, "parse session ID"); if (esid != sid) fatal_f("tty alloc fail on unknown session: " "my id %u theirs %u", sid, esid); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); rawmode = 0; continue; case MUX_S_EXIT_MESSAGE: if ((r = sshbuf_get_u32(m, &esid)) != 0) fatal_fr(r, "parse session ID"); if (esid != sid) fatal_f("exit on unknown session: " "my id %u theirs %u", sid, esid); if (exitval_seen) fatal_f("exitval sent twice"); if ((r = sshbuf_get_u32(m, &exitval)) != 0) fatal_fr(r, "parse exitval"); exitval_seen = 1; continue; default: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal_f("master returned error: %s", e); } } close(fd); if (rawmode) leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); if (muxclient_terminate) { debug2("Exiting on signal: %s", strsignal(muxclient_terminate)); exitval = 255; } else if (!exitval_seen) { debug2("Control master terminated unexpectedly"); exitval = 255; } else debug2("Received exit status from master %d", exitval); if (tty_flag && options.log_level >= SYSLOG_LEVEL_INFO) fprintf(stderr, "Shared connection to %s closed.\r\n", host); exit(exitval); } static int mux_client_proxy(int fd) { struct sshbuf *m; char *e; u_int type, rid; int r; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_PROXY)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { sshbuf_free(m); return 0; } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); if (type != MUX_S_PROXY) { if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal_f("master returned error: %s", e); } sshbuf_free(m); debug3_f("done"); muxclient_request_id++; return 0; } static int mux_client_request_stdio_fwd(int fd) { struct sshbuf *m; char *e; u_int type, rid, sid; int r; debug3_f("entering"); if ((muxserver_pid = mux_client_request_alive(fd)) == 0) { error_f("master alive request failed"); return -1; } ssh_signal(SIGPIPE, SIG_IGN); if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1) fatal_f("stdfd_devnull failed"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_NEW_STDIO_FWD)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 || (r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_cstring(m, options.stdio_forward_host)) != 0 || (r = sshbuf_put_u32(m, options.stdio_forward_port)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); /* Send the stdio file descriptors */ if (mm_send_fd(fd, STDIN_FILENO) == -1 || mm_send_fd(fd, STDOUT_FILENO) == -1) fatal_f("send fds failed"); if (pledge("stdio proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); platform_pledge_mux(); debug3_f("stdio forward request sent"); /* Read their reply */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { error_f("read from master failed: %s", strerror(errno)); sshbuf_free(m); return -1; } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); switch (type) { case MUX_S_SESSION_OPENED: if ((r = sshbuf_get_u32(m, &sid)) != 0) fatal_fr(r, "parse session ID"); debug_f("master session id: %u", sid); break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); sshbuf_free(m); fatal("Master refused stdio forwarding request: %s", e); case MUX_S_FAILURE: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); sshbuf_free(m); fatal("Stdio forwarding request failed: %s", e); default: sshbuf_free(m); error_f("unexpected response from master 0x%08x", type); return -1; } muxclient_request_id++; ssh_signal(SIGHUP, control_client_sighandler); ssh_signal(SIGINT, control_client_sighandler); ssh_signal(SIGTERM, control_client_sighandler); ssh_signal(SIGWINCH, control_client_sigrelay); /* * Stick around until the controlee closes the client_fd. */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { if (errno == EPIPE || (errno == EINTR && muxclient_terminate != 0)) return 0; fatal_f("mux_client_read_packet: %s", strerror(errno)); } fatal_f("master returned unexpected message %u", type); } static void mux_client_request_stop_listening(int fd) { struct sshbuf *m; char *e; u_int type, rid; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_STOP_LISTENING)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) fatal_f("read from master failed: %s", strerror(errno)); if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); switch (type) { case MUX_S_OK: break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal("Master refused stop listening request: %s", e); case MUX_S_FAILURE: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal_f("stop listening request failed: %s", e); default: fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; } /* Multiplex client main loop. */ int muxclient(const char *path) { struct sockaddr_un addr; int sock, timeout = options.connection_timeout, timeout_ms = -1; u_int pid; if (muxclient_command == 0) { if (options.stdio_forward_host != NULL) muxclient_command = SSHMUX_COMMAND_STDIO_FWD; else muxclient_command = SSHMUX_COMMAND_OPEN; } switch (options.control_master) { case SSHCTL_MASTER_AUTO: case SSHCTL_MASTER_AUTO_ASK: debug("auto-mux: Trying existing master at '%s'", path); /* FALLTHROUGH */ case SSHCTL_MASTER_NO: break; default: return -1; } memset(&addr, '\0', sizeof(addr)); addr.sun_family = AF_UNIX; if (strlcpy(addr.sun_path, path, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) fatal("ControlPath too long ('%s' >= %u bytes)", path, (unsigned int)sizeof(addr.sun_path)); if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) fatal_f("socket(): %s", strerror(errno)); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { switch (muxclient_command) { case SSHMUX_COMMAND_OPEN: case SSHMUX_COMMAND_STDIO_FWD: break; default: fatal("Control socket connect(%.100s): %s", path, strerror(errno)); } if (errno == ECONNREFUSED && options.control_master != SSHCTL_MASTER_NO) { debug("Stale control socket %.100s, unlinking", path); unlink(path); } else if (errno == ENOENT) { debug("Control socket \"%.100s\" does not exist", path); } else { error("Control socket connect(%.100s): %s", path, strerror(errno)); } close(sock); return -1; } set_nonblock(sock); /* Timeout on initial connection only. */ if (timeout > 0 && timeout < INT_MAX / 1000) timeout_ms = timeout * 1000; if (mux_client_hello_exchange(sock, timeout_ms) != 0) { error_f("master hello exchange failed"); close(sock); return -1; } switch (muxclient_command) { case SSHMUX_COMMAND_ALIVE_CHECK: if ((pid = mux_client_request_alive(sock)) == 0) fatal_f("master alive check failed"); fprintf(stderr, "Master running (pid=%u)\r\n", pid); exit(0); case SSHMUX_COMMAND_TERMINATE: mux_client_request_terminate(sock); if (options.log_level != SYSLOG_LEVEL_QUIET) fprintf(stderr, "Exit request sent.\r\n"); exit(0); case SSHMUX_COMMAND_FORWARD: if (mux_client_forwards(sock, 0) != 0) fatal_f("master forward request failed"); exit(0); case SSHMUX_COMMAND_OPEN: if (mux_client_forwards(sock, 0) != 0) { error_f("master forward request failed"); return -1; } mux_client_request_session(sock); return -1; case SSHMUX_COMMAND_STDIO_FWD: mux_client_request_stdio_fwd(sock); exit(0); case SSHMUX_COMMAND_STOP: mux_client_request_stop_listening(sock); if (options.log_level != SYSLOG_LEVEL_QUIET) fprintf(stderr, "Stop listening request sent.\r\n"); exit(0); case SSHMUX_COMMAND_CANCEL_FWD: if (mux_client_forwards(sock, 1) != 0) error_f("master cancel forward request failed"); exit(0); case SSHMUX_COMMAND_PROXY: mux_client_proxy(sock); return (sock); default: fatal("unrecognised muxclient_command %d", muxclient_command); } } openssh-10.0p1/PaxHeaders.10889/myproposal.h100644 001750 001750 0000000003614775415623 0015532xustar0030 atime=1744182234.638501198 openssh-10.0p1/myproposal.h010064400017500001750000000073371477541562300141270ustar00djmdjm/* $OpenBSD: myproposal.h,v 1.77 2024/12/02 14:06:42 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. */ #define KEX_SERVER_KEX \ "mlkem768x25519-sha256," \ "sntrup761x25519-sha512," \ "sntrup761x25519-sha512@openssh.com," \ "curve25519-sha256," \ "curve25519-sha256@libssh.org," \ "ecdh-sha2-nistp256," \ "ecdh-sha2-nistp384," \ "ecdh-sha2-nistp521" \ #define KEX_CLIENT_KEX KEX_SERVER_KEX "," \ "diffie-hellman-group-exchange-sha256," \ "diffie-hellman-group16-sha512," \ "diffie-hellman-group18-sha512," \ "diffie-hellman-group14-sha256" #define KEX_DEFAULT_PK_ALG \ "ssh-ed25519-cert-v01@openssh.com," \ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ "sk-ssh-ed25519-cert-v01@openssh.com," \ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com," \ "rsa-sha2-512-cert-v01@openssh.com," \ "rsa-sha2-256-cert-v01@openssh.com," \ "ssh-ed25519," \ "ecdsa-sha2-nistp256," \ "ecdsa-sha2-nistp384," \ "ecdsa-sha2-nistp521," \ "sk-ssh-ed25519@openssh.com," \ "sk-ecdsa-sha2-nistp256@openssh.com," \ "rsa-sha2-512," \ "rsa-sha2-256" #define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ "aes128-gcm@openssh.com,aes256-gcm@openssh.com," \ "aes128-ctr,aes192-ctr,aes256-ctr" #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 /* Not a KEX value, but here so all the algorithm defaults are together */ #define SSH_ALLOWED_CA_SIGALGS \ "ssh-ed25519," \ "ecdsa-sha2-nistp256," \ "ecdsa-sha2-nistp384," \ "ecdsa-sha2-nistp521," \ "sk-ssh-ed25519@openssh.com," \ "sk-ecdsa-sha2-nistp256@openssh.com," \ "rsa-sha2-512," \ "rsa-sha2-256" #define KEX_DEFAULT_COMP "none,zlib@openssh.com" #define KEX_DEFAULT_LANG "" #define KEX_CLIENT \ KEX_CLIENT_KEX, \ KEX_DEFAULT_PK_ALG, \ KEX_CLIENT_ENCRYPT, \ KEX_CLIENT_ENCRYPT, \ KEX_CLIENT_MAC, \ KEX_CLIENT_MAC, \ KEX_DEFAULT_COMP, \ KEX_DEFAULT_COMP, \ KEX_DEFAULT_LANG, \ KEX_DEFAULT_LANG #define KEX_SERVER \ KEX_SERVER_KEX, \ KEX_DEFAULT_PK_ALG, \ KEX_SERVER_ENCRYPT, \ KEX_SERVER_ENCRYPT, \ KEX_SERVER_MAC, \ KEX_SERVER_MAC, \ KEX_DEFAULT_COMP, \ KEX_DEFAULT_COMP, \ KEX_DEFAULT_LANG, \ KEX_DEFAULT_LANG openssh-10.0p1/PaxHeaders.10889/nchan.c100644 001750 001750 0000000003614775415623 0014407xustar0030 atime=1744182234.638501198 openssh-10.0p1/nchan.c010064400017500001750000000276651477541562300130120ustar00djmdjm/* $OpenBSD: nchan.c,v 1.76 2024/07/25 22:40:08 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "ssh2.h" #include "sshbuf.h" #include "ssherr.h" #include "packet.h" #include "channels.h" #include "compat.h" #include "log.h" /* * SSH Protocol 1.5 aka New Channel Protocol * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored. * Written by Markus Friedl in October 1999 * * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the * tear down of channels: * * 1.3: strict request-ack-protocol: * CLOSE -> * <- CLOSE_CONFIRM * * 1.5: uses variations of: * IEOF -> * <- OCLOSE * <- IEOF * OCLOSE -> * i.e. both sides have to close the channel * * 2.0: the EOF messages are optional * * See the debugging output from 'ssh -v' and 'sshd -d' of * ssh-1.2.27 as an example. * */ /* functions manipulating channel states */ /* * EVENTS update channel input/output states execute ACTIONS */ /* * ACTIONS: should never update the channel states */ static void chan_send_eof2(struct ssh *, Channel *); static void chan_send_eow2(struct ssh *, Channel *); /* helper */ 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 const char * const ostates[] = { "open", "drain", "wait_ieof", "closed", }; static const char * const istates[] = { "open", "drain", "wait_oclose", "closed", }; static void chan_set_istate(Channel *c, u_int next) { if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED) fatal("chan_set_istate: bad state %d -> %d", c->istate, next); debug2("channel %d: input %s -> %s", c->self, istates[c->istate], istates[next]); c->istate = next; } static void chan_set_ostate(Channel *c, u_int next) { if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED) fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next); debug2("channel %d: output %s -> %s", c->self, ostates[c->ostate], ostates[next]); c->ostate = next; } void 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(ssh, c); chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); break; default: error("channel %d: chan_read_failed for istate %d", c->self, c->istate); break; } } void chan_ibuf_empty(struct ssh *ssh, Channel *c) { debug2("channel %d: ibuf empty", c->self); 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 (!(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", c->self, c->istate); break; } } void chan_obuf_empty(struct ssh *ssh, Channel *c) { debug2("channel %d: obuf empty", c->self); 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(ssh, c); chan_set_ostate(c, CHAN_OUTPUT_CLOSED); break; default: error("channel %d: internal error: obuf_empty for ostate %d", c->self, c->ostate); break; } } void chan_rcvd_eow(struct ssh *ssh, Channel *c) { 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: if (!c->have_remote_id) fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send CHANNEL_EOF"); 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(struct ssh *ssh, Channel *c) { int r; debug2("channel %d: send_close2", 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_f("channel %d: no remote_id", c->self); debug2("channel %d: send close for remote id %u", c->self, c->remote_id); 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_fr(r, "send CHANNEL_EOF"); c->flags |= CHAN_CLOSE_SENT; } } static void 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 (!(ssh->compat & SSH_NEW_OPENSSH)) return; if (!c->have_remote_id) fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send CHANNEL_EOF"); } /* 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)) { if (c->flags & CHAN_CLOSE_RCVD) error("channel %d: protocol error: close rcvd twice", c->self); c->flags |= CHAN_CLOSE_RCVD; } if (c->type == SSH_CHANNEL_LARVAL) { /* tear down larval channels immediately */ chan_set_ostate(c, CHAN_OUTPUT_CLOSED); chan_set_istate(c, CHAN_INPUT_CLOSED); return; } switch (c->ostate) { case CHAN_OUTPUT_OPEN: /* * wait until a data from the channel is consumed if a CLOSE * is received */ chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); break; } switch (c->istate) { case CHAN_INPUT_OPEN: 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(ssh, c); chan_shutdown_extended_read(ssh, c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; } } void 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(ssh, c); if (strcmp(c->ctype, "session") == 0) chan_send_eow2(ssh, 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_mark_dead(struct ssh *ssh, Channel *c) { c->type = SSH_CHANNEL_ZOMBIE; } int chan_is_dead(struct ssh *ssh, Channel *c, int do_send) { if (c->type == SSH_CHANNEL_ZOMBIE) { debug2("channel %d: zombie", c->self); return 1; } if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) return 0; if ((ssh->compat & SSH_BUG_EXTEOF) && c->extended_usage == CHAN_EXTENDED_WRITE && c->efd != -1 && 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) { debug2("channel %d: is dead (local)", c->self); return 1; } if (!(c->flags & CHAN_CLOSE_SENT)) { if (do_send) { chan_send_close2(ssh, c); } else { /* channel would be dead if we sent a close */ if (c->flags & CHAN_CLOSE_RCVD) { debug2("channel %d: almost dead", c->self); return 1; } } } if ((c->flags & CHAN_CLOSE_SENT) && (c->flags & CHAN_CLOSE_RCVD)) { debug2("channel %d: is dead", c->self); return 1; } return 0; } /* helper */ static void chan_shutdown_write(struct ssh *ssh, Channel *c) { sshbuf_reset(c->output); if (c->type == SSH_CHANNEL_LARVAL) return; /* shutdown failure is allowed if write failed already */ debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", c->self, c->istate, c->ostate, c->sock, c->wfd, c->efd, channel_format_extended_usage(c)); if (c->sock != -1) { if (shutdown(c->sock, SHUT_WR) == -1) { debug2_f("channel %d: shutdown() failed for " "fd %d [i%d o%d]: %.100s", c->self, c->sock, c->istate, c->ostate, strerror(errno)); } } else { if (channel_close_fd(ssh, c, &c->wfd) < 0) { logit_f("channel %d: close() failed for " "fd %d [i%d o%d]: %.100s", c->self, c->wfd, c->istate, c->ostate, strerror(errno)); } } } static void chan_shutdown_read(struct ssh *ssh, Channel *c) { if (c->type == SSH_CHANNEL_LARVAL) return; debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd, channel_format_extended_usage(c)); if (c->sock != -1) { /* * 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) == -1 && errno != ENOTCONN) { error_f("channel %d: shutdown() failed for " "fd %d [i%d o%d]: %.100s", c->self, c->sock, c->istate, c->ostate, strerror(errno)); } } else { if (channel_close_fd(ssh, c, &c->rfd) < 0) { logit_f("channel %d: close() failed for " "fd %d [i%d o%d]: %.100s", c->self, c->rfd, c->istate, c->ostate, strerror(errno)); } } } 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; debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd, channel_format_extended_usage(c)); if (channel_close_fd(ssh, c, &c->efd) < 0) { logit_f("channel %d: close() failed for " "extended fd %d [i%d o%d]: %.100s", c->self, c->efd, c->istate, c->ostate, strerror(errno)); } } openssh-10.0p1/PaxHeaders.10889/nchan.ms100644 001750 001750 0000000003614775415623 0014604xustar0030 atime=1744182234.638501198 openssh-10.0p1/nchan.ms010064400017500001750000000075561477541562300132040ustar00djmdjm.\" $OpenBSD: nchan.ms,v 1.8 2003/11/21 11:57:03 djm Exp $ .\" .\" .\" Copyright (c) 1999 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. .\" .TL OpenSSH Channel Close Protocol 1.5 Implementation .SH Channel Input State Diagram .PS reset l=1 s=1.2 ellipsewid=s*ellipsewid boxwid=s*boxwid ellipseht=s*ellipseht S1: ellipse "INPUT" "OPEN" move right 2*l from last ellipse.e S4: ellipse "INPUT" "CLOSED" move down l from last ellipse.s S3: ellipse "INPUT" "WAIT" "OCLOSED" move down l from 1st ellipse.s S2: ellipse "INPUT" "WAIT" "DRAIN" arrow "" "rcvd OCLOSE/" "shutdown_read" "send IEOF" from S1.e to S4.w arrow "ibuf_empty/" "send IEOF" from S2.e to S3.w arrow from S1.s to S2.n box invis "read_failed/" "shutdown_read" with .e at last arrow.c arrow from S3.n to S4.s box invis "rcvd OCLOSE/" "-" with .w at last arrow.c ellipse wid .9*ellipsewid ht .9*ellipseht at S4 arrow "start" "" from S1.w+(-0.5,0) to S1.w arrow from S2.ne to S4.sw box invis "rcvd OCLOSE/ " with .e at last arrow.c box invis " send IEOF" with .w at last arrow.c .PE .SH Channel Output State Diagram .PS S1: ellipse "OUTPUT" "OPEN" move right 2*l from last ellipse.e S3: ellipse "OUTPUT" "WAIT" "IEOF" move down l from last ellipse.s S4: ellipse "OUTPUT" "CLOSED" move down l from 1st ellipse.s S2: ellipse "OUTPUT" "WAIT" "DRAIN" arrow "" "write_failed/" "shutdown_write" "send OCLOSE" from S1.e to S3.w arrow "obuf_empty ||" "write_failed/" "shutdown_write" "send OCLOSE" from S2.e to S4.w arrow from S1.s to S2.n box invis "rcvd IEOF/" "-" with .e at last arrow.c arrow from S3.s to S4.n box invis "rcvd IEOF/" "-" with .w at last arrow.c ellipse wid .9*ellipsewid ht .9*ellipseht at S4 arrow "start" "" from S1.w+(-0.5,0) to S1.w .PE .SH Notes .PP The input buffer is filled with data from the socket (the socket represents the local consumer/producer of the forwarded channel). The data is then sent over the INPUT-end (transmit-end) of the channel to the remote peer. Data sent by the peer is received on the OUTPUT-end (receive-end), saved in the output buffer and written to the socket. .PP If the local protocol instance has forwarded all data on the INPUT-end of the channel, it sends an IEOF message to the peer. If the peer receives the IEOF and has consumed all data he replies with an OCLOSE. When the local instance receives the OCLOSE he considers the INPUT-half of the channel closed. The peer has his OUTOUT-half closed. .PP A channel can be deallocated by a protocol instance if both the INPUT- and the OUTOUT-half on his side of the channel are closed. Note that when an instance is unable to consume the received data, he is permitted to send an OCLOSE before the matching IEOF is received. openssh-10.0p1/PaxHeaders.10889/nchan2.ms100644 001750 001750 0000000003614775415623 0014666xustar0030 atime=1744182234.638501198 openssh-10.0p1/nchan2.ms010064400017500001750000000066021477541562300132550ustar00djmdjm.\" $OpenBSD: nchan2.ms,v 1.4 2008/05/15 23:52:24 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. .\" .TL OpenSSH Channel Close Protocol 2.0 Implementation .SH Channel Input State Diagram .PS reset l=1 s=1.2 ellipsewid=s*ellipsewid boxwid=s*boxwid ellipseht=s*ellipseht S1: ellipse "INPUT" "OPEN" move right 2*l from last ellipse.e S3: ellipse invis move down l from last ellipse.s S4: ellipse "INPUT" "CLOSED" move down l from 1st ellipse.s S2: ellipse "INPUT" "WAIT" "DRAIN" arrow from S1.e to S4.n box invis "rcvd CLOSE/" "shutdown_read" with .sw at last arrow.c arrow "ibuf_empty ||" "rcvd CLOSE/" "send EOF" "" from S2.e to S4.w arrow from S1.s to S2.n box invis "read_failed ||" "rcvd EOW/" "shutdown_read" with .e at last arrow.c ellipse wid .9*ellipsewid ht .9*ellipseht at S4 arrow "start" "" from S1.w+(-0.5,0) to S1.w .PE .SH Channel Output State Diagram .PS S1: ellipse "OUTPUT" "OPEN" move right 2*l from last ellipse.e S3: ellipse invis move down l from last ellipse.s S4: ellipse "OUTPUT" "CLOSED" move down l from 1st ellipse.s S2: ellipse "OUTPUT" "WAIT" "DRAIN" arrow from S1.e to S4.n box invis "write_failed/" "shutdown_write" "send EOW" with .sw at last arrow.c arrow "obuf_empty ||" "write_failed/" "shutdown_write" "" from S2.e to S4.w arrow from S1.s to S2.n box invis "rcvd EOF ||" "rcvd CLOSE/" "-" with .e at last arrow.c ellipse wid .9*ellipsewid ht .9*ellipseht at S4 arrow "start" "" from S1.w+(-0.5,0) to S1.w .PE .SH Notes .PP The input buffer is filled with data from the socket (the socket represents the local consumer/producer of the forwarded channel). The data is then sent over the INPUT-end (transmit-end) of the channel to the remote peer. Data sent by the peer is received on the OUTPUT-end (receive-end), saved in the output buffer and written to the socket. .PP If the local protocol instance has forwarded all data on the INPUT-end of the channel, it sends an EOF message to the peer. .PP A CLOSE message is sent to the peer if both the INPUT- and the OUTOUT-half of the local end of the channel are closed. .PP The channel can be deallocated by a protocol instance if a CLOSE message he been both sent and received. openssh-10.0p1/PaxHeaders.10889/openbsd-compat040755 001750 001750 0000000003614775415623 0016020xustar0030 atime=1744182234.638501198 openssh-10.0p1/openbsd-compat004075500017500001750000000000001477541562300143765ustar00djmdjmopenssh-10.0p1/openbsd-compat/PaxHeaders.10889/Makefile.in100644 001750 001750 0000000003614775415623 0020134xustar0030 atime=1744182234.639478496 openssh-10.0p1/openbsd-compat/Makefile.in010064400017500001750000000037151477541562300165250ustar00djmdjmsysconfdir=@sysconfdir@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ 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=arc4random.o \ arc4random_uniform.o \ base64.o \ basename.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= bsd-asprintf.o \ bsd-closefrom.o \ bsd-cygwin_util.o \ bsd-err.o \ bsd-flock.o \ bsd-getentropy.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-pselect.o \ bsd-setres_id.o \ bsd-signal.o \ bsd-snprintf.o \ bsd-statvfs.o \ bsd-timegm.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-prngd.o \ port-solaris.o \ port-net.o \ port-uw.o .c.o: $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< all: libopenbsd-compat.a $(COMPAT): ../config.h $(OPENBSD): ../config.h $(PORTS): ../config.h libopenbsd-compat.a: $(COMPAT) $(OPENBSD) $(PORTS) $(AR) rv $@ $(COMPAT) $(OPENBSD) $(PORTS) $(RANLIB) $@ clean: rm -f *.o *.a core distclean: clean rm -f Makefile *~ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/arc4random.c100644 001750 001750 0000000003614775415623 0020265xustar0030 atime=1744182234.647289611 openssh-10.0p1/openbsd-compat/arc4random.c010064400017500001750000000140061477541562300166510ustar00djmdjm/* $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $ */ /* * Copyright (c) 1996, David Mazieres * Copyright (c) 2008, Damien Miller * Copyright (c) 2013, Markus Friedl * Copyright (c) 2014, Theo de Raadt * * 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. */ /* * ChaCha based random number generator for OpenBSD. */ /* OPENBSD ORIGINAL: lib/libc/crypt/arc4random.c */ #include "includes.h" #include #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include #include #include #ifndef HAVE_ARC4RANDOM /* * Always use the getentropy implementation from bsd-getentropy.c, which * will call a native getentropy if available then fall back as required. * We use a different name so that OpenSSL cannot call the wrong getentropy. */ int _ssh_compat_getentropy(void *, size_t); #ifdef getentropy # undef getentropy #endif #define getentropy(x, y) (_ssh_compat_getentropy((x), (y))) #include "log.h" #define KEYSTREAM_ONLY #include "chacha_private.h" #define minimum(a, b) ((a) < (b) ? (a) : (b)) #if defined(__GNUC__) || defined(_MSC_VER) #define inline __inline #else /* __GNUC__ || _MSC_VER */ #define inline #endif /* !__GNUC__ && !_MSC_VER */ #define KEYSZ 32 #define IVSZ 8 #define BLOCKSZ 64 #define RSBUFSZ (16*BLOCKSZ) #define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */ /* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */ static struct _rs { size_t rs_have; /* valid bytes at end of rs_buf */ size_t rs_count; /* bytes till reseed */ } *rs; /* Maybe be preserved in fork children, if _rs_allocate() decides. */ static struct _rsx { chacha_ctx rs_chacha; /* chacha context for random keystream */ u_char rs_buf[RSBUFSZ]; /* keystream blocks */ } *rsx; static inline int _rs_allocate(struct _rs **, struct _rsx **); static inline void _rs_forkdetect(void); #include "arc4random.h" static inline void _rs_rekey(u_char *dat, size_t datlen); static inline void _rs_init(u_char *buf, size_t n) { if (n < KEYSZ + IVSZ) return; if (rs == NULL) { if (_rs_allocate(&rs, &rsx) == -1) _exit(1); } chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8); chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ); } static void _rs_stir(void) { u_char rnd[KEYSZ + IVSZ]; uint32_t rekey_fuzz = 0; if (getentropy(rnd, sizeof rnd) == -1) _getentropy_fail(); if (!rs) _rs_init(rnd, sizeof(rnd)); else _rs_rekey(rnd, sizeof(rnd)); explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ /* invalidate rs_buf */ rs->rs_have = 0; memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); /* rekey interval should not be predictable */ chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz, (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz)); rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE); } static inline void _rs_stir_if_needed(size_t len) { _rs_forkdetect(); if (!rs || rs->rs_count <= len) _rs_stir(); if (rs->rs_count <= len) rs->rs_count = 0; else rs->rs_count -= len; } static inline void _rs_rekey(u_char *dat, size_t datlen) { #ifndef KEYSTREAM_ONLY memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); #endif /* fill rs_buf with the keystream */ chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf, rsx->rs_buf, sizeof(rsx->rs_buf)); /* mix in optional user provided data */ if (dat) { size_t i, m; m = minimum(datlen, KEYSZ + IVSZ); for (i = 0; i < m; i++) rsx->rs_buf[i] ^= dat[i]; } /* immediately reinit for backtracking resistance */ _rs_init(rsx->rs_buf, KEYSZ + IVSZ); memset(rsx->rs_buf, 0, KEYSZ + IVSZ); rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ; } static inline void _rs_random_buf(void *_buf, size_t n) { u_char *buf = (u_char *)_buf; u_char *keystream; size_t m; _rs_stir_if_needed(n); while (n > 0) { if (rs->rs_have > 0) { m = minimum(n, rs->rs_have); keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; memcpy(buf, keystream, m); memset(keystream, 0, m); buf += m; n -= m; rs->rs_have -= m; } if (rs->rs_have == 0) _rs_rekey(NULL, 0); } } static inline void _rs_random_u32(uint32_t *val) { u_char *keystream; _rs_stir_if_needed(sizeof(*val)); if (rs->rs_have < sizeof(*val)) _rs_rekey(NULL, 0); keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; memcpy(val, keystream, sizeof(*val)); memset(keystream, 0, sizeof(*val)); rs->rs_have -= sizeof(*val); } uint32_t arc4random(void) { uint32_t val; _ARC4_LOCK(); _rs_random_u32(&val); _ARC4_UNLOCK(); return val; } DEF_WEAK(arc4random); /* * If we are providing arc4random, then we can provide a more efficient * arc4random_buf(). */ # ifndef HAVE_ARC4RANDOM_BUF void arc4random_buf(void *buf, size_t n) { _ARC4_LOCK(); _rs_random_buf(buf, n); _ARC4_UNLOCK(); } DEF_WEAK(arc4random_buf); # endif /* !HAVE_ARC4RANDOM_BUF */ #endif /* !HAVE_ARC4RANDOM */ /* arc4random_buf() that uses platform arc4random() */ #if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) void arc4random_buf(void *_buf, size_t n) { size_t i; u_int32_t r = 0; char *buf = (char *)_buf; for (i = 0; i < n; i++) { if (i % 4 == 0) r = arc4random(); buf[i] = r & 0xff; r >>= 8; } explicit_bzero(&r, sizeof(r)); } #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/arc4random.h100644 001750 001750 0000000003614775415623 0020272xustar0030 atime=1744182234.647289611 openssh-10.0p1/openbsd-compat/arc4random.h010064400017500001750000000044771477541562300166710ustar00djmdjm/* $OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $ */ /* * Copyright (c) 1996, David Mazieres * Copyright (c) 2008, Damien Miller * Copyright (c) 2013, Markus Friedl * Copyright (c) 2014, Theo de Raadt * * 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. */ /* * Stub functions for portability. From LibreSSL with some adaptations. */ #ifdef HAVE_SYS_MMAN_H #include #endif #include /* OpenSSH isn't multithreaded */ #define _ARC4_LOCK() #define _ARC4_UNLOCK() #define _ARC4_ATFORK(f) static inline void _getentropy_fail(void) { fatal("getentropy failed"); } static volatile sig_atomic_t _rs_forked; static inline void _rs_forkhandler(void) { _rs_forked = 1; } static inline void _rs_forkdetect(void) { static pid_t _rs_pid = 0; pid_t pid = getpid(); if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) { _rs_pid = pid; _rs_forked = 0; if (rs) memset(rs, 0, sizeof(*rs)); } } static inline int _rs_allocate(struct _rs **rsp, struct _rsx **rsxp) { #if defined(MAP_ANON) && defined(MAP_PRIVATE) if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) return (-1); if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { munmap(*rsp, sizeof(**rsp)); *rsp = NULL; return (-1); } #else if ((*rsp = calloc(1, sizeof(**rsp))) == NULL) return (-1); if ((*rsxp = calloc(1, sizeof(**rsxp))) == NULL) { free(*rsp); *rsp = NULL; return (-1); } #endif _ARC4_ATFORK(_rs_forkhandler); return (0); } openssh-10.0p1/openbsd-compat/PaxHeaders.10889/arc4random_uniform.c100644 001750 001750 0000000003614775415623 0022024xustar0030 atime=1744182234.647289611 openssh-10.0p1/openbsd-compat/arc4random_uniform.c010064400017500001750000000036731477541562300204200ustar00djmdjm/* $OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $ */ /* * Copyright (c) 2008, Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* OPENBSD ORIGINAL: lib/libc/crypto/arc4random_uniform.c */ #include "includes.h" #ifdef HAVE_STDINT_H # include #endif #include #ifndef HAVE_ARC4RANDOM_UNIFORM /* * Calculate a uniformly distributed random number less than upper_bound * avoiding "modulo bias". * * Uniformity is achieved by generating new random numbers until the one * returned is outside the range [0, 2**32 % upper_bound). This * guarantees the selected random number will be inside * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) * after reduction modulo upper_bound. */ uint32_t arc4random_uniform(uint32_t upper_bound) { uint32_t r, min; if (upper_bound < 2) return 0; /* 2**32 % x == (2**32 - x) % x */ min = -upper_bound % upper_bound; /* * This could theoretically loop forever but each retry has * p > 0.5 (worst case, usually far better) of selecting a * number inside the range we need, so it should rarely need * to re-roll. */ for (;;) { r = arc4random(); if (r >= min) break; } return r % upper_bound; } #endif /* !HAVE_ARC4RANDOM_UNIFORM */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/base64.c100644 001750 001750 0000000003514775415623 0017316xustar0029 atime=1744182234.64826742 openssh-10.0p1/openbsd-compat/base64.c010064400017500001750000000243461477541562300157130ustar00djmdjm/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */ /* * Copyright (c) 1996 by 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. */ /* * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ /* OPENBSD ORIGINAL: lib/libc/net/base64.c */ #include "includes.h" #if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) #include #include #include #include #include #include #include #include #include "base64.h" static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char Pad64 = '='; /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) The following encoding technique is taken from RFC 1521 by Borenstein and Freed. It is reproduced here in a slightly edited form for convenience. A 65-character subset of US-ASCII is used, enabling 6 bits to be represented per printable character. (The extra 65th character, "=", is used to signify a special processing function.) The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index is placed in the output string. Table 1: The Base64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a quantity. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the ------------------------------------------------- following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ #if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { size_t datalength = 0; u_char input[3]; u_char output[4]; u_int i; while (2 < srclength) { input[0] = *src++; input[1] = *src++; input[2] = *src++; srclength -= 3; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; if (srclength == 1) target[datalength++] = Pad64; else target[datalength++] = Base64[output[2]]; target[datalength++] = Pad64; } if (datalength >= targsize) return (-1); target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (datalength); } #endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ #if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) /* skips all whitespace anywhere. converts characters, four at a time, starting at (or after) src from base - 64 numbers into three 8 bit bytes in the target area. it returns the number of data bytes stored at the target, or -1 on error. */ int b64_pton(char const *src, u_char *target, size_t targsize) { u_int tarindex, state; int ch; char *pos; state = 0; tarindex = 0; while ((ch = *src++) != '\0') { if (isspace(ch)) /* Skip whitespace anywhere. */ continue; if (ch == Pad64) break; pos = strchr(Base64, ch); if (pos == 0) /* A non-base64 character. */ return (-1); switch (state) { case 0: if (target) { if (tarindex >= targsize) return (-1); target[tarindex] = (pos - Base64) << 2; } state = 1; break; case 1: if (target) { if (tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; target[tarindex+1] = ((pos - Base64) & 0x0f) << 4 ; } tarindex++; state = 2; break; case 2: if (target) { if (tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; target[tarindex+1] = ((pos - Base64) & 0x03) << 6; } tarindex++; state = 3; break; case 3: if (target) { if (tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64); } tarindex++; state = 0; break; } } /* * We are done decoding Base-64 chars. Let's see if we ended * on a byte boundary, and/or with erroneous trailing characters. */ if (ch == Pad64) { /* We got a pad char. */ ch = *src++; /* Skip it, get next. */ switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ return (-1); case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ for (; ch != '\0'; ch = *src++) if (!isspace(ch)) break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) return (-1); ch = *src++; /* Skip the = */ /* Fall through to "single trailing =" case. */ /* FALLTHROUGH */ case 3: /* Valid, means two bytes of info */ /* * We know this char is an =. Is there anything but * whitespace after it? */ for (; ch != '\0'; ch = *src++) if (!isspace(ch)) return (-1); /* * Now make sure for cases 2 and 3 that the "extra" * bits that slopped past the last full byte were * zeros. If we don't check them, they become a * subliminal channel. */ if (target && target[tarindex] != 0) return (-1); } } else { /* * We ended by seeing the end of the string. Make sure we * have no partial bytes lying around. */ if (state != 0) return (-1); } return (tarindex); } #endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */ #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/base64.h100644 001750 001750 0000000003514775415623 0017323xustar0029 atime=1744182234.64826742 openssh-10.0p1/openbsd-compat/base64.h010064400017500001750000000053071477541562300157140ustar00djmdjm/* * Copyright (c) 1996 by 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. */ /* * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef _BSD_BASE64_H #define _BSD_BASE64_H #include "includes.h" #ifndef HAVE___B64_NTOP # ifndef HAVE_B64_NTOP 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) #endif /* HAVE___B64_NTOP */ #ifndef HAVE___B64_PTON # ifndef HAVE_B64_PTON int b64_pton(char const *src, u_char *target, size_t targsize); # endif /* !HAVE_B64_PTON */ # define __b64_pton(a,b,c) b64_pton(a,b,c) #endif /* HAVE___B64_PTON */ #endif /* _BSD_BASE64_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/basename.c100644 001750 001750 0000000003514775415623 0020005xustar0029 atime=1744182234.64826742 openssh-10.0p1/openbsd-compat/basename.c010064400017500001750000000034341477541562300163750ustar00djmdjm/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */ /* * Copyright (c) 1997, 2004 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* OPENBSD ORIGINAL: lib/libc/gen/basename.c */ #include "includes.h" #ifndef HAVE_BASENAME #include #include char * basename(const char *path) { static char bname[MAXPATHLEN]; size_t len; const char *endp, *startp; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { bname[0] = '.'; bname[1] = '\0'; return (bname); } /* Strip any trailing slashes */ endp = path + strlen(path) - 1; while (endp > path && *endp == '/') endp--; /* All slashes becomes "/" */ if (endp == path && *endp == '/') { bname[0] = '/'; bname[1] = '\0'; return (bname); } /* Find the start of the base */ startp = endp; while (startp > path && *(startp - 1) != '/') startp--; len = endp - startp + 1; if (len >= sizeof(bname)) { errno = ENAMETOOLONG; return (NULL); } memcpy(bname, startp, len); bname[len] = '\0'; return (bname); } #endif /* !defined(HAVE_BASENAME) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bcrypt_pbkdf.c100644 001750 001750 0000000003514775415623 0020703xustar0029 atime=1744182234.64826742 openssh-10.0p1/openbsd-compat/bcrypt_pbkdf.c010064400017500001750000000131651477541562300172750ustar00djmdjm/* $OpenBSD: bcrypt_pbkdf.c,v 1.16 2020/08/02 18:35:48 tb Exp $ */ /* * Copyright (c) 2013 Ted Unangst * * 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/libutil/bcrypt_pbkdf.c */ /* This version has been modified to use SHA512 from SUPERCOP */ #include "includes.h" #ifndef HAVE_BCRYPT_PBKDF #include #ifdef HAVE_STDLIB_H # include #endif #include #ifdef HAVE_BLF_H # include #endif #include "crypto_api.h" #ifdef SHA512_DIGEST_LENGTH # undef SHA512_DIGEST_LENGTH #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 * * The bcrypt hash function is derived from the bcrypt password hashing * 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 * to "OxychromaticBlowfishSwatDynamite" * 4. The hash function is defined to perform 64 rounds of initial state * expansion. (More rounds are performed by iterating the hash.) * * Note that this implementation pulls the SHA512 operations into the caller * as a performance optimization. * * One modification from official pbkdf2. Instead of outputting key material * linearly, we mix it. pbkdf2 has a known weakness where if one uses it to * generate (e.g.) 512 bits of key material for use as two 256 bit keys, an * attacker can merely run once through the outer loop, but the user * always runs it twice. Shuffling output bytes requires computing the * entirety of the key material to assemble any subkey. This is something a * wise caller could do; we just do it for you. */ #define BCRYPT_WORDS 8 #define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4) static void bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out) { blf_ctx state; uint8_t ciphertext[BCRYPT_HASHSIZE] = "OxychromaticBlowfishSwatDynamite"; uint32_t cdata[BCRYPT_WORDS]; int i; uint16_t j; size_t shalen = SHA512_DIGEST_LENGTH; /* key expansion */ Blowfish_initstate(&state); Blowfish_expandstate(&state, sha2salt, shalen, sha2pass, shalen); for (i = 0; i < 64; i++) { Blowfish_expand0state(&state, sha2salt, shalen); Blowfish_expand0state(&state, sha2pass, shalen); } /* encryption */ j = 0; 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, BCRYPT_WORDS / 2); /* copy out */ 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; out[4 * i + 0] = cdata[i] & 0xff; } /* zap */ explicit_bzero(ciphertext, sizeof(ciphertext)); explicit_bzero(cdata, sizeof(cdata)); explicit_bzero(&state, sizeof(state)); } int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, uint8_t *key, size_t keylen, unsigned int rounds) { uint8_t sha2pass[SHA512_DIGEST_LENGTH]; uint8_t sha2salt[SHA512_DIGEST_LENGTH]; uint8_t out[BCRYPT_HASHSIZE]; uint8_t tmpout[BCRYPT_HASHSIZE]; uint8_t *countsalt; size_t i, j, amt, stride; uint32_t count; size_t origkeylen = keylen; /* nothing crazy */ if (rounds < 1) goto bad; if (passlen == 0 || saltlen == 0 || keylen == 0 || keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20) goto bad; if ((countsalt = calloc(1, saltlen + 4)) == NULL) goto bad; stride = (keylen + sizeof(out) - 1) / sizeof(out); amt = (keylen + stride - 1) / stride; memcpy(countsalt, salt, saltlen); /* collapse password */ crypto_hash_sha512(sha2pass, pass, passlen); /* generate key, sizeof(out) at a time */ for (count = 1; keylen > 0; count++) { countsalt[saltlen + 0] = (count >> 24) & 0xff; countsalt[saltlen + 1] = (count >> 16) & 0xff; countsalt[saltlen + 2] = (count >> 8) & 0xff; countsalt[saltlen + 3] = count & 0xff; /* first round, salt is salt */ crypto_hash_sha512(sha2salt, countsalt, saltlen + 4); bcrypt_hash(sha2pass, sha2salt, tmpout); memcpy(out, tmpout, sizeof(out)); for (i = 1; i < rounds; i++) { /* subsequent rounds, salt is previous output */ crypto_hash_sha512(sha2salt, tmpout, sizeof(tmpout)); bcrypt_hash(sha2pass, sha2salt, tmpout); for (j = 0; j < sizeof(out); j++) out[j] ^= tmpout[j]; } /* * pbkdf2 deviation: output the key material non-linearly. */ amt = MINIMUM(amt, keylen); for (i = 0; i < amt; i++) { size_t dest = i * stride + (count - 1); if (dest >= origkeylen) break; key[dest] = out[i]; } keylen -= i; } /* zap */ freezero(countsalt, saltlen + 4); explicit_bzero(out, sizeof(out)); explicit_bzero(tmpout, sizeof(tmpout)); return 0; bad: /* overwrite with random in case caller doesn't check return code */ arc4random_buf(key, keylen); return -1; } #endif /* HAVE_BCRYPT_PBKDF */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bindresvport.c100644 001750 001750 0000000003514775415623 0020753xustar0029 atime=1744182234.64826742 openssh-10.0p1/openbsd-compat/bindresvport.c010064400017500001750000000064151477541562300173450ustar00djmdjm/* This file has be substantially modified from the original OpenBSD source */ /* $OpenBSD: bindresvport.c,v 1.17 2005/12/21 01:40:22 millert Exp $ */ /* * Copyright 1996, Jason Downs. All rights reserved. * Copyright 1998, Theo de Raadt. All rights reserved. * Copyright 2000, 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. */ /* OPENBSD ORIGINAL: lib/libc/rpc/bindresvport.c */ #include "includes.h" #ifndef HAVE_BINDRESVPORT_SA #include #include #include #include #include #include #include #define STARTPORT 600 #define ENDPORT (IPPORT_RESERVED - 1) #define NPORTS (ENDPORT - STARTPORT + 1) /* * Bind a socket to a privileged IP port */ int bindresvport_sa(int sd, struct sockaddr *sa) { int error, af; struct sockaddr_storage myaddr; struct sockaddr_in *in; struct sockaddr_in6 *in6; u_int16_t *portp; u_int16_t port; socklen_t salen; int i; 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 */ af = sa->sa_family; memset(&myaddr, 0, salen); } else af = sa->sa_family; if (af == AF_INET) { in = (struct sockaddr_in *)sa; salen = sizeof(struct sockaddr_in); portp = &in->sin_port; } else if (af == AF_INET6) { in6 = (struct sockaddr_in6 *)sa; salen = sizeof(struct sockaddr_in6); portp = &in6->sin6_port; } else { errno = EPFNOSUPPORT; return (-1); } sa->sa_family = af; port = ntohs(*portp); if (port == 0) port = arc4random_uniform(NPORTS) + STARTPORT; /* Avoid warning */ error = -1; for(i = 0; i < NPORTS; i++) { *portp = htons(port); error = bind(sd, sa, salen); /* Terminate on success */ if (error == 0) break; /* Terminate on errors, except "address already in use" */ if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) break; port++; if (port > ENDPORT) port = STARTPORT; } return (error); } #endif /* HAVE_BINDRESVPORT_SA */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/blf.h100644 001750 001750 0000000003514775415623 0017002xustar0029 atime=1744182234.64826742 openssh-10.0p1/openbsd-compat/blf.h010064400017500001750000000064641477541562300154000ustar00djmdjm/* $OpenBSD: blf.h,v 1.8 2021/11/29 01:04:45 djm Exp $ */ /* * Blowfish - a fast block cipher designed by Bruce Schneier * * Copyright 1997 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. 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. */ #ifndef _BLF_H_ #define _BLF_H_ #include "includes.h" #if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) /* Schneier specifies a maximum key length of 56 bytes. * This ensures that every key bit affects every cipher * bit. However, the subkeys can hold up to 72 bytes. * Warning: For normal blowfish encryption only 56 bytes * of the key affect all cipherbits. */ #define BLF_N 16 /* Number of Subkeys */ #define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ #define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */ /* Blowfish context */ typedef struct BlowfishContext { u_int32_t S[4][256]; /* S-Boxes */ u_int32_t P[BLF_N + 2]; /* Subkeys */ } blf_ctx; /* Raw access to customized Blowfish * blf_key is just: * Blowfish_initstate( state ) * Blowfish_expand0state( state, key, keylen ) */ void Blowfish_encipher(blf_ctx *, u_int32_t *, u_int32_t *); void Blowfish_decipher(blf_ctx *, u_int32_t *, u_int32_t *); void Blowfish_initstate(blf_ctx *); void Blowfish_expand0state(blf_ctx *, const u_int8_t *, u_int16_t); void Blowfish_expandstate (blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t); /* Standard Blowfish */ void blf_key(blf_ctx *, const u_int8_t *, u_int16_t); void blf_enc(blf_ctx *, u_int32_t *, u_int16_t); void blf_dec(blf_ctx *, u_int32_t *, u_int16_t); void blf_ecb_encrypt(blf_ctx *, u_int8_t *, u_int32_t); void blf_ecb_decrypt(blf_ctx *, u_int8_t *, u_int32_t); void blf_cbc_encrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t); void blf_cbc_decrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t); /* Converts u_int8_t to u_int32_t */ u_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t , u_int16_t *); #endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */ #endif /* _BLF_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/blowfish.c100644 001750 001750 0000000003614775415623 0020050xustar0030 atime=1744182234.649243376 openssh-10.0p1/openbsd-compat/blowfish.c010064400017500001750000000556521477541562300164500ustar00djmdjm/* $OpenBSD: blowfish.c,v 1.20 2021/11/29 01:04:45 djm Exp $ */ /* * Blowfish block cipher for OpenBSD * Copyright 1997 Niels Provos * All rights reserved. * * Implementation advice by David Mazieres . * * 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. */ /* * This code is derived from section 14.3 and the given source * in section V of Applied Cryptography, second edition. * Blowfish is an unpatented fast block cipher designed by * Bruce Schneier. */ #include "includes.h" #if !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \ !defined(HAVE_BLOWFISH_EXPAND0STATE) || !defined(HAVE_BLF_ENC)) #if 0 #include /* used for debugging */ #include #endif #include #ifdef HAVE_BLF_H #include #endif #undef inline #ifdef __GNUC__ #define inline __inline #else /* !__GNUC__ */ #define inline #endif /* !__GNUC__ */ /* Function for Feistel Networks */ #define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \ + (s)[0x100 + (((x)>>16)&0xFF)]) \ ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \ + (s)[0x300 + ( (x) &0xFF)]) #define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n]) void Blowfish_encipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr) { u_int32_t Xl; u_int32_t Xr; u_int32_t *s = c->S[0]; u_int32_t *p = c->P; Xl = *xl; Xr = *xr; Xl ^= p[0]; BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2); BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4); BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6); BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8); BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10); BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12); BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14); BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16); *xl = Xr ^ p[17]; *xr = Xl; } void Blowfish_decipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr) { u_int32_t Xl; u_int32_t Xr; u_int32_t *s = c->S[0]; u_int32_t *p = c->P; Xl = *xl; Xr = *xr; Xl ^= p[17]; BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15); BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13); BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11); BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9); BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7); BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5); BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3); BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1); *xl = Xr ^ p[0]; *xr = Xl; } void Blowfish_initstate(blf_ctx *c) { /* P-box and S-box tables initialized with digits of Pi */ static const blf_ctx initstate = { { { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a}, { 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}, { 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}, { 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6} }, { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b } }; *c = initstate; } u_int32_t Blowfish_stream2word(const u_int8_t *data, u_int16_t databytes, u_int16_t *current) { u_int8_t i; u_int16_t j; u_int32_t temp; temp = 0x00000000; j = *current; for (i = 0; i < 4; i++, j++) { if (j >= databytes) j = 0; temp = (temp << 8) | data[j]; } *current = j; return temp; } void Blowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes) { u_int16_t i; u_int16_t j; u_int16_t k; u_int32_t temp; u_int32_t datal; u_int32_t datar; j = 0; for (i = 0; i < BLF_N + 2; i++) { /* Extract 4 int8 to 1 int32 from keystream */ temp = Blowfish_stream2word(key, keybytes, &j); c->P[i] = c->P[i] ^ temp; } j = 0; datal = 0x00000000; datar = 0x00000000; for (i = 0; i < BLF_N + 2; i += 2) { Blowfish_encipher(c, &datal, &datar); c->P[i] = datal; c->P[i + 1] = datar; } for (i = 0; i < 4; i++) { for (k = 0; k < 256; k += 2) { Blowfish_encipher(c, &datal, &datar); c->S[i][k] = datal; c->S[i][k + 1] = datar; } } } void Blowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes, const u_int8_t *key, u_int16_t keybytes) { u_int16_t i; u_int16_t j; u_int16_t k; u_int32_t temp; u_int32_t datal; u_int32_t datar; j = 0; for (i = 0; i < BLF_N + 2; i++) { /* Extract 4 int8 to 1 int32 from keystream */ temp = Blowfish_stream2word(key, keybytes, &j); c->P[i] = c->P[i] ^ temp; } j = 0; datal = 0x00000000; datar = 0x00000000; for (i = 0; i < BLF_N + 2; i += 2) { datal ^= Blowfish_stream2word(data, databytes, &j); datar ^= Blowfish_stream2word(data, databytes, &j); Blowfish_encipher(c, &datal, &datar); c->P[i] = datal; c->P[i + 1] = datar; } for (i = 0; i < 4; i++) { for (k = 0; k < 256; k += 2) { datal ^= Blowfish_stream2word(data, databytes, &j); datar ^= Blowfish_stream2word(data, databytes, &j); Blowfish_encipher(c, &datal, &datar); c->S[i][k] = datal; c->S[i][k + 1] = datar; } } } void blf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len) { /* Initialize S-boxes and subkeys with Pi */ Blowfish_initstate(c); /* Transform S-boxes and subkeys with key */ Blowfish_expand0state(c, k, len); } void blf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks) { u_int32_t *d; u_int16_t i; d = data; for (i = 0; i < blocks; i++) { Blowfish_encipher(c, d, d + 1); d += 2; } } void blf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks) { u_int32_t *d; u_int16_t i; d = data; for (i = 0; i < blocks; i++) { Blowfish_decipher(c, d, d + 1); d += 2; } } void blf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len) { u_int32_t l, r; u_int32_t i; for (i = 0; i < len; i += 8) { l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_encipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; data += 8; } } void blf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len) { u_int32_t l, r; u_int32_t i; for (i = 0; i < len; i += 8) { l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_decipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; data += 8; } } void blf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len) { u_int32_t l, r; u_int32_t i, j; for (i = 0; i < len; i += 8) { for (j = 0; j < 8; j++) data[j] ^= iv[j]; l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_encipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; iv = data; data += 8; } } void blf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len) { u_int32_t l, r; u_int8_t *iv; u_int32_t i, j; iv = data + len - 16; data = data + len - 8; for (i = len - 8; i >= 8; i -= 8) { l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_decipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; for (j = 0; j < 8; j++) data[j] ^= iv[j]; iv -= 8; data -= 8; } l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_decipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; for (j = 0; j < 8; j++) data[j] ^= iva[j]; } #if 0 void report(u_int32_t data[], u_int16_t len) { u_int16_t i; for (i = 0; i < len; i += 2) printf("Block %0hd: %08lx %08lx.\n", i / 2, data[i], data[i + 1]); } void main(void) { blf_ctx c; char key[] = "AAAAA"; char key2[] = "abcdefghijklmnopqrstuvwxyz"; u_int32_t data[10]; u_int32_t data2[] = {0x424c4f57l, 0x46495348l}; u_int16_t i; /* First test */ for (i = 0; i < 10; i++) data[i] = i; blf_key(&c, (u_int8_t *) key, 5); blf_enc(&c, data, 5); blf_dec(&c, data, 1); blf_dec(&c, data + 2, 4); printf("Should read as 0 - 9.\n"); report(data, 10); /* Second test */ blf_key(&c, (u_int8_t *) key2, strlen(key2)); blf_enc(&c, data2, 1); printf("\nShould read as: 0x324ed0fe 0xf413a203.\n"); report(data2, 2); blf_dec(&c, data2, 1); report(data2, 2); } #endif #endif /* !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \ !defined(HAVE_BLOWFISH_EXPAND0STATE) || !defined(HAVE_BLF_ENC)) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-asprintf.c100644 001750 001750 0000000003614775415623 0020627xustar0030 atime=1744182234.649243376 openssh-10.0p1/openbsd-compat/bsd-asprintf.c010064400017500001750000000045221477541562300172150ustar00djmdjm/* * Copyright (c) 2004 Darren Tucker. * * Based originally on asprintf.c from OpenBSD: * Copyright (c) 1997 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #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 #include #include #include #define INIT_SZ 128 int vasprintf(char **str, const char *fmt, va_list ap) { int ret = -1; va_list ap2; char *string, *newstr; size_t len; VA_COPY(ap2, ap); if ((string = malloc(INIT_SZ)) == NULL) goto fail; ret = vsnprintf(string, INIT_SZ, fmt, ap2); if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ *str = string; } else if (ret == INT_MAX || ret < 0) { /* Bad length */ free(string); goto fail; } else { /* bigger than initial, realloc allowing for nul */ len = (size_t)ret + 1; if ((newstr = realloc(string, len)) == NULL) { free(string); goto fail; } else { va_end(ap2); VA_COPY(ap2, ap); ret = vsnprintf(newstr, len, fmt, ap2); if (ret >= 0 && (size_t)ret < len) { *str = newstr; } else { /* failed with realloc'ed string, give up */ free(newstr); goto fail; } } } va_end(ap2); return (ret); fail: *str = NULL; errno = ENOMEM; va_end(ap2); return (-1); } #endif #ifndef HAVE_ASPRINTF int asprintf(char **str, const char *fmt, ...) { va_list ap; int ret; *str = NULL; va_start(ap, fmt); ret = vasprintf(str, fmt, ap); va_end(ap); return ret; } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-closefrom.c100644 001750 001750 0000000003614775415623 0020772xustar0030 atime=1744182234.649243376 openssh-10.0p1/openbsd-compat/bsd-closefrom.c010064400017500001750000000076141477541562300173650ustar00djmdjm/* * Copyright (c) 2004-2005 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) #include #include #include #ifdef HAVE_FCNTL_H # include #endif #include #include #include #include #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif #if defined(HAVE_LIBPROC_H) # include #endif #ifndef OPEN_MAX # define OPEN_MAX 256 #endif #if 0 __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); } #elif defined(HAVE_LIBPROC_H) && defined(HAVE_PROC_PIDINFO) void closefrom(int lowfd) { 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; int len; #ifdef HAVE_CLOSE_RANGE if (close_range(lowfd, INT_MAX, 0) == 0) return; #endif /* 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))) { while ((dent = readdir(dirp)) != NULL) { fd = strtol(dent->d_name, &endp, 10); if (dent->d_name != endp && *endp == '\0' && fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) (void) close((int) fd); } (void) closedir(dirp); 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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-cygwin_util.c100644 001750 001750 0000000003614775415623 0021336xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-cygwin_util.c010064400017500001750000000151671477541562300177330ustar00djmdjm/* * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen * * 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: Sat Sep 02 12:17:00 2000 cv * * This file contains functions for forcing opened file descriptors to * binary mode on Windows systems. */ #define NO_BINARY_OPEN /* Avoid redefining open to binary_open for this file */ #include "includes.h" #ifdef HAVE_CYGWIN #include #include #include #include #include #include #include #include #include "xmalloc.h" 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); return (open(filename, flags | O_BINARY, mode)); } int check_ntsec(const char *filename) { return (pathconf(filename, _PC_POSIX_PERMISSIONS)); } const char * cygwin_ssh_privsep_user() { static char cyg_privsep_user[DNLEN + UNLEN + 2]; if (!cyg_privsep_user[0]) { #ifdef CW_CYGNAME_FROM_WINNAME if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user, sizeof cyg_privsep_user) != 0) #endif strlcpy(cyg_privsep_user, "sshd", sizeof(cyg_privsep_user)); } return cyg_privsep_user; } #define NL(x) x, (sizeof (x) - 1) #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) static struct wenv { const char *name; size_t namelen; } wenv_arr[] = { { NL("ALLUSERSPROFILE=") }, { NL("COMPUTERNAME=") }, { NL("COMSPEC=") }, { NL("CYGWIN=") }, { NL("OS=") }, { NL("PATH=") }, { NL("PATHEXT=") }, { NL("PROGRAMFILES=") }, { NL("SYSTEMDRIVE=") }, { NL("SYSTEMROOT=") }, { NL("WINDIR=") } }; char ** fetch_windows_environment(void) { char **e, **p; unsigned int i, idx = 0; p = xcalloc(WENV_SIZ + 1, sizeof(char *)); for (e = environ; *e != NULL; ++e) { for (i = 0; i < WENV_SIZ; ++i) { if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen)) p[idx++] = *e; } } p[idx] = NULL; return p; } void 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)) == (size_t) -1) return 0; ws = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t)); mbstowcs(ws, s, len + 1); if ((len = mbstowcs(NULL, pattern, 0)) == (size_t) -1) 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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-cygwin_util.h100644 001750 001750 0000000003614775415623 0021343xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-cygwin_util.h010064400017500001750000000046371477541562300177400ustar00djmdjm/* * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen * * 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: Sat Sep 02 12:17:00 2000 cv * * This file contains functions for forcing opened file descriptors to * binary mode on Windows systems. */ #ifndef _BSD_CYGWIN_UTIL_H #define _BSD_CYGWIN_UTIL_H #ifdef HAVE_CYGWIN #undef ERROR /* Avoid including windows headers. */ typedef void *HANDLE; #define INVALID_HANDLE_VALUE ((HANDLE) -1) #define DNLEN 16 #define UNLEN 256 /* Cygwin functions for which declarations are only available when including 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); #include #include #define CYGWIN_SSH_PRIVSEP_USER (cygwin_ssh_privsep_user()) const char *cygwin_ssh_privsep_user(); 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 #endif #endif /* HAVE_CYGWIN */ #endif /* _BSD_CYGWIN_UTIL_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-err.c100644 001750 001750 0000000003614775415623 0017571xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-err.c010064400017500001750000000042331477541562300161560ustar00djmdjm/* * Copyright (c) 2015 Tim Rice * * 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 #include #include #include #include #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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-flock.c100644 001750 001750 0000000003614775415623 0020077xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-flock.c010064400017500001750000000043551477541562300164710ustar00djmdjm/* $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 #include 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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-getentropy.c100644 001750 001750 0000000003614775415623 0021201xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-getentropy.c010064400017500001750000000045111477541562300175650ustar00djmdjm/* * Copyright (c) 1996, David Mazieres * Copyright (c) 2008, Damien Miller * Copyright (c) 2013, 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" #ifndef SSH_RANDOM_DEV # define SSH_RANDOM_DEV "/dev/urandom" #endif /* SSH_RANDOM_DEV */ #include #ifdef HAVE_SYS_RANDOM_H # include #endif #include #include #include #include #ifdef WITH_OPENSSL #include #include #endif #include "log.h" int _ssh_compat_getentropy(void *s, size_t len) { #if defined(WITH_OPENSSL) && defined(OPENSSL_PRNG_ONLY) if (RAND_bytes(s, len) <= 0) fatal("Couldn't obtain random bytes (error 0x%lx)", (unsigned long)ERR_get_error()); #else int fd, save_errno; ssize_t r; size_t o = 0; #ifdef WITH_OPENSSL if (RAND_bytes(s, len) == 1) return 0; #endif #ifdef HAVE_GETENTROPY if ((r = getentropy(s, len)) == 0) return 0; #endif /* HAVE_GETENTROPY */ #ifdef HAVE_GETRANDOM if ((r = getrandom(s, len, 0)) > 0 && (size_t)r == len) return 0; #endif /* HAVE_GETRANDOM */ if ((fd = open(SSH_RANDOM_DEV, O_RDONLY)) == -1) { save_errno = errno; /* Try egd/prngd before giving up. */ if (seed_from_prngd(s, len) == 0) return 0; fatal("Couldn't open %s: %s", SSH_RANDOM_DEV, strerror(save_errno)); } while (o < len) { r = read(fd, (u_char *)s + o, len - o); if (r < 0) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) continue; fatal("read %s: %s", SSH_RANDOM_DEV, strerror(errno)); } o += r; } close(fd); #endif /* WITH_OPENSSL */ return 0; } openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-getline.c100644 001750 001750 0000000003614775415623 0020430xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-getline.c010064400017500001750000000056751477541562300170300ustar00djmdjm/* $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 !defined(HAVE_GETLINE) || defined(BROKEN_GETLINE) #include #include #include #include #include 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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-getpagesize.c100644 001750 001750 0000000003614775415623 0021310xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-getpagesize.c010064400017500001750000000007171477541562300177000ustar00djmdjm/* Placed in the public domain */ #include "includes.h" #ifndef HAVE_GETPAGESIZE #include #include 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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-misc.c100644 001750 001750 0000000003614775415623 0017734xustar0030 atime=1744182234.651196681 openssh-10.0p1/openbsd-compat/bsd-misc.c010064400017500001750000000206071477541562300163240ustar00djmdjm /* * Copyright (c) 1999-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #include #ifndef HAVE___PROGNAME char *__progname; #endif /* * NB. duplicate __progname in case it is an alias for argv[0] * Otherwise it may get clobbered by setproctitle() */ char *ssh_get_progname(char *argv0) { char *p, *q; #ifdef HAVE___PROGNAME extern char *__progname; p = __progname; #else if (argv0 == NULL) return ("unknown"); /* XXX */ p = strrchr(argv0, '/'); if (p == NULL) p = argv0; else p++; #endif if ((q = strdup(p)) == NULL) { perror("strdup"); exit(1); } return q; } #ifndef HAVE_SETLOGIN int setlogin(const char *name) { return (0); } #endif /* !HAVE_SETLOGIN */ #ifndef HAVE_INNETGR int innetgr(const char *netgroup, const char *host, const char *user, const char *domain) { return (0); } #endif /* HAVE_INNETGR */ #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) int seteuid(uid_t euid) { return (setreuid(-1, euid)); } #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) int setegid(uid_t egid) { return(setresgid(-1, egid, -1)); } #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ #if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) const char *strerror(int e) { extern int sys_nerr; extern char *sys_errlist[]; if ((e >= 0) && (e < sys_nerr)) return (sys_errlist[e]); return ("unlisted error"); } #endif #ifndef HAVE_UTIMES int utimes(const char *filename, struct timeval *tvp) { struct utimbuf ub; ub.actime = tvp[0].tv_sec; ub.modtime = tvp[1].tv_sec; return (utime(filename, &ub)); } #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) { int fd, ret, saverrno; fd = open(path, O_WRONLY); if (fd < 0) return (-1); ret = ftruncate(fd, length); saverrno = errno; close(fd); if (ret == -1) errno = saverrno; return(ret); } #endif /* HAVE_TRUNCATE */ #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) int nanosleep(const struct timespec *req, struct timespec *rem) { int rc, saverrno; extern int errno; struct timeval tstart, tstop, tremain, time2wait; TIMESPEC_TO_TIMEVAL(&time2wait, req) (void) gettimeofday(&tstart, NULL); rc = select(0, NULL, NULL, NULL, &time2wait); if (rc == -1) { saverrno = errno; (void) gettimeofday (&tstop, NULL); errno = saverrno; tremain.tv_sec = time2wait.tv_sec - (tstop.tv_sec - tstart.tv_sec); tremain.tv_usec = time2wait.tv_usec - (tstop.tv_usec - tstart.tv_usec); tremain.tv_sec += tremain.tv_usec / 1000000L; tremain.tv_usec %= 1000000L; } else { tremain.tv_sec = 0; tremain.tv_usec = 0; } if (rem != NULL) TIMEVAL_TO_TIMESPEC(&tremain, rem) return(rc); } #endif #if !defined(HAVE_USLEEP) int usleep(unsigned int useconds) { struct timespec ts; ts.tv_sec = useconds / 1000000; ts.tv_nsec = (useconds % 1000000) * 1000; return nanosleep(&ts, NULL); } #endif #ifndef HAVE_TCGETPGRP pid_t tcgetpgrp(int fd) { int ctty_pgrp; if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) return(-1); else return(ctty_pgrp); } #endif /* HAVE_TCGETPGRP */ #ifndef HAVE_TCSENDBREAK int tcsendbreak(int fd, int duration) { # if defined(TIOCSBRK) && defined(TIOCCBRK) struct timeval sleepytime; sleepytime.tv_sec = 0; sleepytime.tv_usec = 400000; if (ioctl(fd, TIOCSBRK, 0) == -1) return (-1); (void)select(0, 0, 0, 0, &sleepytime); if (ioctl(fd, TIOCCBRK, 0) == -1) return (-1); return (0); # else return -1; # endif } #endif /* HAVE_TCSENDBREAK */ #ifndef HAVE_STRDUP char * strdup(const char *str) { size_t len; char *cp; len = strlen(str) + 1; cp = malloc(len); if (cp != NULL) return(memcpy(cp, str, len)); return NULL; } #endif #ifndef HAVE_ISBLANK int isblank(int c) { return (c == ' ' || c == '\t'); } #endif #ifndef HAVE_GETPGID pid_t getpgid(pid_t pid) { #if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) && GETPGRP_VOID == 0 return getpgrp(pid); #elif defined(HAVE_GETPGRP) if (pid == 0) return getpgrp(); #endif errno = ESRCH; 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 #ifndef HAVE_KILLPG int killpg(pid_t pgrp, int sig) { return kill(pgrp, sig); } #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 #ifdef ASAN_OPTIONS const char *__asan_default_options(void) { return ASAN_OPTIONS; } #endif #ifdef MSAN_OPTIONS const char *__msan_default_options(void) { return MSAN_OPTIONS; } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-getpeereid.c100644 001750 001750 0000000003614775415623 0021116xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-getpeereid.c010064400017500001750000000032651477541562300175070ustar00djmdjm/* * Copyright (c) 2002,2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #if !defined(HAVE_GETPEEREID) #include #include #include #if defined(SO_PEERCRED) int getpeereid(int s, uid_t *euid, gid_t *gid) { struct ucred cred; socklen_t len = sizeof(cred); if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0) return (-1); *euid = cred.uid; *gid = cred.gid; return (0); } #elif defined(HAVE_GETPEERUCRED) #ifdef HAVE_UCRED_H # include #endif int getpeereid(int s, uid_t *euid, gid_t *gid) { ucred_t *ucred = NULL; if (getpeerucred(s, &ucred) == -1) return (-1); if ((*euid = ucred_geteuid(ucred)) == -1) return (-1); if ((*gid = ucred_getrgid(ucred)) == -1) return (-1); ucred_free(ucred); return (0); } #else int getpeereid(int s, uid_t *euid, gid_t *gid) { *euid = geteuid(); *gid = getgid(); return (0); } #endif /* defined(SO_PEERCRED) */ #endif /* !defined(HAVE_GETPEEREID) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-malloc.c100644 001750 001750 0000000003614775415623 0020250xustar0030 atime=1744182234.650220475 openssh-10.0p1/openbsd-compat/bsd-malloc.c010064400017500001750000000026251477541562300166400ustar00djmdjm/* * 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 #include #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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-misc.h100644 001750 001750 0000000003614775415623 0017741xustar0030 atime=1744182234.651196681 openssh-10.0p1/openbsd-compat/bsd-misc.h010064400017500001750000000107371477541562300163340ustar00djmdjm/* * Copyright (c) 1999-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _BSD_MISC_H #define _BSD_MISC_H #include "includes.h" char *ssh_get_progname(char *); int seed_from_prngd(unsigned char *, size_t); #ifndef HAVE_SETSID #define setsid() setpgrp(0, getpid()) #endif /* !HAVE_SETSID */ #ifndef HAVE_SETENV int setenv(const char *, const char *, int); #endif /* !HAVE_SETENV */ #ifndef HAVE_SETLOGIN int setlogin(const char *); #endif /* !HAVE_SETLOGIN */ #ifndef HAVE_INNETGR int innetgr(const char *, const char *, const char *, const char *); #endif /* HAVE_INNETGR */ #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) int seteuid(uid_t); #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) int setegid(uid_t); #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ #if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) const char *strerror(int); #endif #if !defined(HAVE_SETLINEBUF) #define setlinebuf(a) (setvbuf((a), NULL, _IOLBF, 0)) #endif #ifndef HAVE_UTIMES #ifndef HAVE_STRUCT_TIMEVAL struct timeval { long tv_sec; long tv_usec; } #endif /* HAVE_STRUCT_TIMEVAL */ int utimes(const 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 */ #ifndef HAVE_STRUCT_TIMESPEC struct timespec { time_t tv_sec; long tv_nsec; }; #endif /* !HAVE_STRUCT_TIMESPEC */ #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) # include int nanosleep(const struct timespec *, struct timespec *); #endif #ifndef HAVE_UTIMENSAT # include /* start with the high bits and work down to minimise risk of overlap */ # ifndef AT_SYMLINK_NOFOLLOW # define AT_SYMLINK_NOFOLLOW 0x80000000 # endif int utimensat(int, const char *, const struct timespec[2], int); #endif /* !HAVE_UTIMENSAT */ #ifndef HAVE_USLEEP int usleep(unsigned int useconds); #endif #ifndef HAVE_TCGETPGRP pid_t tcgetpgrp(int); #endif #ifndef HAVE_TCSENDBREAK int tcsendbreak(int, int); #endif #ifndef HAVE_UNSETENV int unsetenv(const char *); #endif #ifndef HAVE_ISBLANK int isblank(int); #endif #ifndef HAVE_GETPGID pid_t getpgid(pid_t); #endif #ifndef HAVE_PSELECT int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *); #endif #ifndef HAVE_ENDGRENT # define endgrent() do { } while(0) #endif #ifndef HAVE_KRB5_GET_ERROR_MESSAGE # define krb5_get_error_message krb5_get_err_text #endif #ifndef HAVE_KRB5_FREE_ERROR_MESSAGE # 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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-nextstep.c100644 001750 001750 0000000003614775415623 0020653xustar0030 atime=1744182234.651196681 openssh-10.0p1/openbsd-compat/bsd-nextstep.c010064400017500001750000000050001477541562300172310ustar00djmdjm/* * Copyright (c) 2000,2001 Ben Lindstrom. 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 HAVE_NEXT #include #include #include "bsd-nextstep.h" pid_t posix_wait(int *status) { union wait statusp; pid_t wait_pid; #undef wait /* Use NeXT's wait() function */ wait_pid = wait(&statusp); if (status) *status = (int) statusp.w_status; return (wait_pid); } int tcgetattr(int fd, struct termios *t) { return (ioctl(fd, TIOCGETA, t)); } int tcsetattr(int fd, int opt, const struct termios *t) { struct termios localterm; if (opt & TCSASOFT) { localterm = *t; localterm.c_cflag |= CIGNORE; t = &localterm; } switch (opt & ~TCSASOFT) { case TCSANOW: return (ioctl(fd, TIOCSETA, t)); case TCSADRAIN: return (ioctl(fd, TIOCSETAW, t)); case TCSAFLUSH: return (ioctl(fd, TIOCSETAF, t)); default: errno = EINVAL; return (-1); } } int tcsetpgrp(int fd, pid_t pgrp) { return (ioctl(fd, TIOCSPGRP, &pgrp)); } speed_t cfgetospeed(const struct termios *t) { return (t->c_ospeed); } speed_t cfgetispeed(const struct termios *t) { return (t->c_ispeed); } int cfsetospeed(struct termios *t,int speed) { t->c_ospeed = speed; return (0); } int cfsetispeed(struct termios *t, int speed) { t->c_ispeed = speed; return (0); } #endif /* HAVE_NEXT */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-nextstep.h100644 001750 001750 0000000003614775415623 0020660xustar0030 atime=1744182234.651196681 openssh-10.0p1/openbsd-compat/bsd-nextstep.h010064400017500001750000000043441477541562300172500ustar00djmdjm/* * Copyright (c) 2000,2001 Ben Lindstrom. 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 _NEXT_POSIX_H #define _NEXT_POSIX_H #ifdef HAVE_NEXT #include /* NGROUPS_MAX is behind -lposix. Use the BSD version which is NGROUPS */ #undef NGROUPS_MAX #define NGROUPS_MAX NGROUPS /* NeXT's readdir() is BSD (struct direct) not POSIX (struct dirent) */ #define dirent direct /* Swap out NeXT's BSD wait() for a more POSIX compliant one */ pid_t posix_wait(int *); #define wait(a) posix_wait(a) /* #ifdef wrapped functions that need defining for clean compiling */ pid_t getppid(void); void vhangup(void); int innetgr(const char *, const char *, const char *, const char *); /* TERMCAP */ int tcgetattr(int, struct termios *); int tcsetattr(int, int, const struct termios *); int tcsetpgrp(int, pid_t); speed_t cfgetospeed(const struct termios *); speed_t cfgetispeed(const struct termios *); int cfsetospeed(struct termios *, int); int cfsetispeed(struct termios *, int); #endif /* HAVE_NEXT */ #endif /* _NEXT_POSIX_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-openpty.c100644 001750 001750 0000000003614775415623 0020477xustar0030 atime=1744182234.651196681 openssh-10.0p1/openbsd-compat/bsd-openpty.c010064400017500001750000000144061477541562300170670ustar00djmdjm/* * Please note: this implementation of openpty() is far from complete. * it is just enough for portable OpenSSH's needs. */ /* * Copyright (c) 2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Allocating a pseudo-terminal, and making it the controlling tty. * * 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" #if !defined(HAVE_OPENPTY) #include #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_IOCTL_H # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifdef HAVE_UTIL_H # include #endif /* HAVE_UTIL_H */ #ifdef HAVE_PTY_H # include #endif #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) # include #endif #include #include #include #include "misc.h" #include "log.h" #ifndef O_NOCTTY #define O_NOCTTY 0 #endif #if defined(HAVE_DEV_PTMX) && !defined(HAVE__GETPTY) static int openpty_streams(int *amaster, int *aslave) { /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ int ptm; char *pts; 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 = ssh_signal(SIGCHLD, SIG_DFL); if (grantpt(ptm) < 0) return (-1); ssh_signal(SIGCHLD, old_signal); if (unlockpt(ptm) < 0) return (-1); if ((pts = ptsname(ptm)) == NULL) return (-1); *amaster = ptm; /* Open the slave side. */ if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } # 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 * in Solaris pts(7). */ ioctl(*aslave, I_PUSH, "ptem"); ioctl(*aslave, I_PUSH, "ldterm"); # ifndef __hpux ioctl(*aslave, I_PUSH, "ttcompat"); # endif /* __hpux */ return (0); } #endif int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { #if defined(HAVE__GETPTY) /* * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more * pty's automagically when needed */ char *slave; if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL) return (-1); /* Open the slave side. */ if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); #elif defined(HAVE_DEV_PTMX) #ifdef SSHD_ACQUIRES_CTTY /* * On some (most? all?) SysV based systems with STREAMS based terminals, * sshd will acquire a controlling terminal when it pushes the "ptem" * module. On such platforms, first allocate a sacrificial pty so * that sshd already has a controlling terminal before allocating the * one that will be passed back to the user process. This ensures * the second pty is not already the controlling terminal for a * different session and is available to become controlling terminal * for the client's subprocess. See bugzilla #245 for details. */ int r, fd; static int junk_ptyfd = -1, junk_ttyfd; r = openpty_streams(amaster, aslave); if (junk_ptyfd == -1 && (fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) >= 0) { close(fd); junk_ptyfd = *amaster; junk_ttyfd = *aslave; debug("STREAMS bug workaround pty %d tty %d name %s", junk_ptyfd, junk_ttyfd, ttyname(junk_ttyfd)); } else return r; #endif return openpty_streams(amaster, aslave); #elif defined(HAVE_DEV_PTS_AND_PTC) /* AIX-style pty code. */ const char *ttname; if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) return (-1); if ((ttname = ttyname(*amaster)) == NULL) return (-1); if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); #else /* BSD-style pty code. */ char ptbuf[64], ttbuf[64]; int i; const char *ptymajors = "pqrstuvwxyzabcdefghijklmno" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; struct termios tio; for (i = 0; i < num_ptys; i++) { 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]); if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) { /* Try SCO style naming */ snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i); snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", 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); } /* set tty modes to a sane state for broken clients */ if (tcgetattr(*amaster, &tio) != -1) { tio.c_lflag |= (ECHO | ISIG | ICANON); tio.c_oflag |= (OPOST | ONLCR); tio.c_iflag |= ICRNL; tcsetattr(*amaster, TCSANOW, &tio); } return (0); } return (-1); #endif } #endif /* !defined(HAVE_OPENPTY) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-poll.c100644 001750 001750 0000000003614775415623 0017747xustar0030 atime=1744182234.651196681 openssh-10.0p1/openbsd-compat/bsd-poll.c010064400017500001750000000062311477541562300163340ustar00djmdjm/* * Copyright (c) 2004, 2005, 2007 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 "includes.h" #if !defined(HAVE_PPOLL) || !defined(HAVE_POLL) || defined(BROKEN_POLL) #include #include #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_SYS_SELECT_H # include #endif #include #include #include #include #include "bsd-poll.h" #if !defined(HAVE_PPOLL) || defined(BROKEN_POLL) /* * A minimal implementation of ppoll(2), built on top of pselect(2). * * Only supports POLLIN, POLLOUT and POLLPRI flags in pfd.events and * revents. Notably POLLERR, POLLHUP and POLLNVAL are not supported. * * Supports pfd.fd = -1 meaning "unused" although it's not standard. */ int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmoutp, const sigset_t *sigmask) { nfds_t i; int ret, fd, maxfd = 0; fd_set readfds, writefds, exceptfds; for (i = 0; i < nfds; i++) { fd = fds[i].fd; if (fd != -1 && fd >= FD_SETSIZE) { errno = EINVAL; return -1; } maxfd = MAX(maxfd, fd); } /* populate event bit vectors for the events we're interested in */ FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); for (i = 0; i < nfds; i++) { fd = fds[i].fd; if (fd == -1) continue; if (fds[i].events & POLLIN) FD_SET(fd, &readfds); if (fds[i].events & POLLOUT) FD_SET(fd, &writefds); if (fds[i].events & POLLPRI) FD_SET(fd, &exceptfds); } ret = pselect(maxfd + 1, &readfds, &writefds, &exceptfds, tmoutp, sigmask); /* scan through select results and set poll() flags */ for (i = 0; i < nfds; i++) { fd = fds[i].fd; fds[i].revents = 0; if (fd == -1) continue; if ((fds[i].events & POLLIN) && FD_ISSET(fd, &readfds)) fds[i].revents |= POLLIN; if ((fds[i].events & POLLOUT) && FD_ISSET(fd, &writefds)) fds[i].revents |= POLLOUT; if ((fds[i].events & POLLPRI) && FD_ISSET(fd, &exceptfds)) fds[i].revents |= POLLPRI; } return ret; } #endif /* !HAVE_PPOLL || BROKEN_POLL */ #if !defined(HAVE_POLL) || defined(BROKEN_POLL) int poll(struct pollfd *fds, nfds_t nfds, int timeout) { struct timespec ts, *tsp = NULL; /* poll timeout is msec, ppoll is timespec (sec + nsec) */ if (timeout >= 0) { ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout % 1000) * 1000000; tsp = &ts; } return ppoll(fds, nfds, tsp, NULL); } #endif /* !HAVE_POLL || BROKEN_POLL */ #endif /* !HAVE_PPOLL || !HAVE_POLL || BROKEN_POLL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-poll.h100644 001750 001750 0000000003614775415623 0017754xustar0030 atime=1744182234.652172607 openssh-10.0p1/openbsd-compat/bsd-poll.h010064400017500001750000000047271477541562300163510ustar00djmdjm/* $OpenBSD: poll.h,v 1.11 2003/12/10 23:10:08 millert Exp $ */ /* * Copyright (c) 1996 Theo de Raadt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* OPENBSD ORIGINAL: sys/sys/poll.h */ #ifndef _COMPAT_POLL_H_ #define _COMPAT_POLL_H_ #include #ifdef HAVE_POLL_H # include #elif HAVE_SYS_POLL_H # include #endif #ifndef HAVE_STRUCT_POLLFD_FD typedef struct pollfd { int fd; short events; short revents; } pollfd_t; #ifndef POLLIN # define POLLIN 0x0001 #endif #ifndef POLLPRI # define POLLPRI 0x0002 #endif #ifndef POLLOUT # define POLLOUT 0x0004 #endif #ifndef POLLERR # define POLLERR 0x0008 #endif #ifndef POLLHUP # define POLLHUP 0x0010 #endif #ifndef POLLNVAL # define POLLNVAL 0x0020 #endif #if 0 /* the following are currently not implemented */ #define POLLRDNORM 0x0040 #define POLLNORM POLLRDNORM #define POLLWRNORM POLLOUT #define POLLRDBAND 0x0080 #define POLLWRBAND 0x0100 #endif #define INFTIM (-1) /* not standard */ #endif /* !HAVE_STRUCT_POLLFD_FD */ #ifndef HAVE_NFDS_T typedef unsigned int nfds_t; #endif #ifndef HAVE_POLL int poll(struct pollfd *, nfds_t, int); #endif #ifndef HAVE_PPOLL int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *); #endif #endif /* !_COMPAT_POLL_H_ */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-pselect.c100644 001750 001750 0000000003614775415623 0020440xustar0030 atime=1744182234.652172607 openssh-10.0p1/openbsd-compat/bsd-pselect.c010064400017500001750000000127211477541562300170260ustar00djmdjm/* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2021 Darren Tucker (dtucker at dtucker net). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #ifndef HAVE_PSELECT #include #include #ifdef HAVE_SYS_SELECT_H # include #endif #include #include #include #include #include #include #include "log.h" #ifndef HAVE_SIGHANDLER_T typedef void (*sighandler_t)(int); #endif static sighandler_t saved_sighandler[_NSIG]; static int notify_pipe[2]; /* 0 = read end, 1 = write end */ /* * Because the debugging for this is so noisy, we only output on the first * call, and suppress it thereafter. */ static int suppress_debug; static void pselect_set_nonblock(int fd) { int val; if ((val = fcntl(fd, F_GETFL)) == -1 || fcntl(fd, F_SETFL, val|O_NONBLOCK) == -1) error_f("fcntl: %s", strerror(errno)); } /* * we write to this pipe if a SIGCHLD is caught in order to avoid * the race between select() and child_terminated. */ static int pselect_notify_setup(void) { if (pipe(notify_pipe) == -1) { error("pipe(notify_pipe) failed %s", strerror(errno)); notify_pipe[0] = notify_pipe[1] = -1; return -1; } pselect_set_nonblock(notify_pipe[0]); pselect_set_nonblock(notify_pipe[1]); if (!suppress_debug) debug3_f("pipe0 %d pipe1 %d", notify_pipe[0], notify_pipe[1]); return 0; } static void pselect_notify_parent(void) { if (notify_pipe[1] != -1) (void)write(notify_pipe[1], "", 1); } static void pselect_notify_prepare(fd_set *readset) { if (notify_pipe[0] != -1) FD_SET(notify_pipe[0], readset); } static void pselect_notify_done(fd_set *readset) { char c; if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) { while (read(notify_pipe[0], &c, 1) != -1) debug2_f("reading"); FD_CLR(notify_pipe[0], readset); } (void)close(notify_pipe[0]); (void)close(notify_pipe[1]); } /*ARGSUSED*/ static void pselect_sig_handler(int sig) { int save_errno = errno; pselect_notify_parent(); if (saved_sighandler[sig] != NULL) (*saved_sighandler[sig])(sig); /* call original handler */ errno = save_errno; } /* * A minimal implementation of pselect(2), built on top of select(2). */ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *mask) { int ret, sig, saved_errno, unmasked = 0; sigset_t osig; struct sigaction sa, osa; struct timeval tv, *tvp = NULL; if (timeout != NULL) { tv.tv_sec = timeout->tv_sec; tv.tv_usec = timeout->tv_nsec / 1000; tvp = &tv; } if (mask == NULL) /* no signal mask, just call select */ return select(nfds, readfds, writefds, exceptfds, tvp); /* For each signal unmasked, save old handler and install ours. */ for (sig = 0; sig < _NSIG; sig++) { saved_sighandler[sig] = NULL; if (sig == SIGKILL || sig == SIGSTOP || sigismember(mask, sig)) continue; if (sigaction(sig, NULL, &sa) == 0 && sa.sa_handler != SIG_IGN && sa.sa_handler != SIG_DFL) { unmasked = 1; sa.sa_handler = pselect_sig_handler; if (sigaction(sig, &sa, &osa) == 0) { if (!suppress_debug) debug3_f("installed signal handler for" " %s, previous 0x%p", strsignal(sig), osa.sa_handler); saved_sighandler[sig] = osa.sa_handler; } } } if (unmasked) { if ((ret = pselect_notify_setup()) == -1) { saved_errno = ENOMEM; goto out; } pselect_notify_prepare(readfds); nfds = MAX(nfds, notify_pipe[0] + 1); } /* Unmask signals, call select then restore signal mask. */ sigprocmask(SIG_SETMASK, mask, &osig); ret = select(nfds, readfds, writefds, exceptfds, tvp); saved_errno = errno; sigprocmask(SIG_SETMASK, &osig, NULL); if (unmasked) pselect_notify_done(readfds); out: /* Restore signal handlers. */ for (sig = 0; sig < _NSIG; sig++) { if (saved_sighandler[sig] == NULL) continue; if (sigaction(sig, NULL, &sa) == 0) { sa.sa_handler = saved_sighandler[sig]; if (sigaction(sig, &sa, NULL) == 0) { if (!suppress_debug) debug3_f("restored signal handler for " "%s", strsignal(sig)); } else { error_f("failed to restore signal handler for " "%s: %s", strsignal(sig), strerror(errno)); } } } suppress_debug = 1; errno = saved_errno; return ret; } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-setres_id.c100644 001750 001750 0000000003614775415623 0020762xustar0030 atime=1744182234.652172607 openssh-10.0p1/openbsd-compat/bsd-setres_id.c010064400017500001750000000046151477541562300173530ustar00djmdjm/* * Copyright (c) 2012 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 "includes.h" #include #include #include #include #include "log.h" #if !defined(HAVE_SETRESGID) || defined(BROKEN_SETRESGID) int setresgid(gid_t rgid, gid_t egid, gid_t sgid) { int ret = 0, saved_errno; if (rgid != sgid) { errno = ENOSYS; return -1; } #if defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID) if (setregid(rgid, egid) < 0) { saved_errno = 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 %lu: %.100s", (u_long)egid, strerror(errno)); errno = saved_errno; ret = -1; } if (setgid(rgid) < 0) { saved_errno = errno; error("setgid %lu: %.100s", (u_long)rgid, strerror(errno)); errno = saved_errno; ret = -1; } #endif return ret; } #endif #if !defined(HAVE_SETRESUID) || defined(BROKEN_SETRESUID) int setresuid(uid_t ruid, uid_t euid, uid_t suid) { int ret = 0, saved_errno; if (ruid != suid) { errno = ENOSYS; return -1; } #if defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID) if (setreuid(ruid, euid) < 0) { saved_errno = errno; error("setreuid %lu: %.100s", (u_long)ruid, strerror(errno)); errno = saved_errno; ret = -1; } #else # ifndef SETEUID_BREAKS_SETUID if (seteuid(euid) < 0) { saved_errno = 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 %lu: %.100s", (u_long)ruid, strerror(errno)); errno = saved_errno; ret = -1; } #endif return ret; } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-setres_id.h100644 001750 001750 0000000003614775415623 0020767xustar0030 atime=1744182234.652172607 openssh-10.0p1/openbsd-compat/bsd-setres_id.h010064400017500001750000000016421477541562300173550ustar00djmdjm/* * Copyright (c) 2012 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. */ #ifndef HAVE_SETRESGID int setresgid(gid_t, gid_t, gid_t); #endif #ifndef HAVE_SETRESUID int setresuid(uid_t, uid_t, uid_t); #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-signal.c100644 001750 001750 0000000003614775415623 0020256xustar0030 atime=1744182234.652172607 openssh-10.0p1/openbsd-compat/bsd-signal.c010064400017500001750000000020771477541562300166470ustar00djmdjm/* * Copyright (c) 1999-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-signal.h100644 001750 001750 0000000003614775415623 0020263xustar0030 atime=1744182234.652172607 openssh-10.0p1/openbsd-compat/bsd-signal.h010064400017500001750000000020461477541562300166500ustar00djmdjm/* * Copyright (c) 1999-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _BSD_SIGNAL_H #define _BSD_SIGNAL_H #include "includes.h" #include #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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-snprintf.c100644 001750 001750 0000000003614775415623 0020644xustar0030 atime=1744182234.653150076 openssh-10.0p1/openbsd-compat/bsd-snprintf.c010064400017500001750000000510061477541562300172310ustar00djmdjm/* * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions */ /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point... * * snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. * * More Recently: * Brandon Long 9/15/96 for mutt 0.43 * This was ugly. It is still ugly. I opted out of floating point * numbers, but the formatter understands just about everything * from the normal C string format, at least as far as I can tell from * the Solaris 2.5 printf(3S) man page. * * Brandon Long 10/22/97 for mutt 0.87.1 * Ok, added some minimal floating point support, which means this * 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, 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 * and run snprintf for results. * * Thomas Roessler 01/27/98 for mutt 0.89i * The PGP code was using unsigned hexadecimal formats. * Unfortunately, unsigned formats simply didn't work. * * Michael Elkins 03/05/98 for mutt 0.90.8 * The original code assumed that both snprintf() and vsnprintf() were * missing. Some systems only have snprintf() but not vsnprintf(), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * * Andrew Tridgell (tridge@samba.org) Oct 1998 * fixed handling of %.0f * added test for HAVE_LONG_DOUBLE * * tridge@samba.org, idra@samba.org, April 2001 * got rid of fcvt code (twas buggy and made testing harder) * added C99 semantics * * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 * actually print args for %g and %e * * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 * Since includes.h isn't included here, VA_COPY has to be defined here. I don't * see any include file that is guaranteed to be here, so I'm defining it * locally. Fixes AIX and Solaris builds. * * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 * put the ifdef for HAVE_VA_COPY in one place rather than in lots of * functions * * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 * Fix usage of va_list passed as an arg. Use __va_copy before using it * when it exists. * * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 * Fix incorrect zpadlen handling in fmtfp. * Thanks to Ollie Oldham for spotting it. * few mods to make it easier to compile the tests. * 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 * tree with less trouble. * Remove unnecessary SAFE_FREE() definition. * * Martin Pool (mbp@samba.org) May 2003 * Put in a prototype for dummy_snprintf() to quiet compiler warnings. * * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even * if the C library has some snprintf functions already. * * Damien Miller (djm@mindrot.org) Jan 2007 * Fix integer overflows in return value. * Make formatting quite a bit faster by inlining dopr_outch() * **************************************************************/ #include "includes.h" #if defined(BROKEN_SNPRINTF) /* For those with broken snprintf() */ # undef HAVE_SNPRINTF # undef HAVE_VSNPRINTF #endif #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) #include #include #include #include #include #include #ifdef HAVE_LONG_DOUBLE # define LDOUBLE long double #else # define LDOUBLE double #endif #ifdef HAVE_LONG_LONG # define LLONG long long #else # define LLONG long #endif /* * dopr(): poor man's version of doprintf */ /* format read states */ #define DP_S_DEFAULT 0 #define DP_S_FLAGS 1 #define DP_S_MIN 2 #define DP_S_DOT 3 #define DP_S_MAX 4 #define DP_S_MOD 5 #define DP_S_CONV 6 #define DP_S_DONE 7 /* format flags - Bits */ #define DP_F_MINUS (1 << 0) #define DP_F_PLUS (1 << 1) #define DP_F_SPACE (1 << 2) #define DP_F_NUM (1 << 3) #define DP_F_ZERO (1 << 4) #define DP_F_UP (1 << 5) #define DP_F_UNSIGNED (1 << 6) /* Conversion Flags */ #define DP_C_SHORT 1 #define DP_C_LONG 2 #define DP_C_LDOUBLE 3 #define DP_C_LLONG 4 #define DP_C_SIZE 5 #define DP_C_INTMAX 6 #define char_to_int(p) ((p)- '0') #ifndef MAX # define MAX(p,q) (((p) >= (q)) ? (p) : (q)) #endif #define DOPR_OUTCH(buf, pos, buflen, thechar) \ do { \ if (pos + 1 >= INT_MAX) { \ errno = ERANGE; \ return -1; \ } \ if (pos < buflen) \ buf[pos] = thechar; \ (pos)++; \ } while (0) static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in); static int fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max); static int fmtint(char *buffer, size_t *currlen, size_t maxlen, intmax_t value, int base, int min, int max, int flags); static int fmtfp(char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags); static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) { char ch; intmax_t value; LDOUBLE fvalue; char *strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; va_list args; VA_COPY(args, args_in); state = DP_S_DEFAULT; currlen = flags = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if (ch == '\0') state = DP_S_DONE; switch(state) { case DP_S_DEFAULT: if (ch == '%') state = DP_S_FLAGS; else DOPR_OUTCH(buffer, currlen, maxlen, ch); ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if (isdigit((unsigned char)ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { min = va_arg (args, int); ch = *format++; state = DP_S_DOT; } else { state = DP_S_DOT; } break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else { state = DP_S_MOD; } break; case DP_S_MAX: if (isdigit((unsigned char)ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); ch = *format++; } else if (ch == '*') { max = va_arg (args, int); ch = *format++; state = DP_S_MOD; } else { state = DP_S_MOD; } break; case DP_S_MOD: switch (ch) { case 'h': cflags = DP_C_SHORT; ch = *format++; break; case 'j': cflags = DP_C_INTMAX; ch = *format++; break; case 'l': cflags = DP_C_LONG; ch = *format++; if (ch == 'l') { /* It's a long long */ cflags = DP_C_LLONG; ch = *format++; } break; case 'L': cflags = DP_C_LDOUBLE; ch = *format++; break; case 'z': cflags = DP_C_SIZE; ch = *format++; break; default: break; } state = DP_S_CONV; break; case DP_S_CONV: switch (ch) { case 'd': case 'i': if (cflags == DP_C_SHORT) value = va_arg (args, int); else if (cflags == DP_C_LONG) value = va_arg (args, long int); else if (cflags == DP_C_LLONG) value = va_arg (args, LLONG); else if (cflags == DP_C_SIZE) value = va_arg (args, ssize_t); else if (cflags == DP_C_INTMAX) value = va_arg (args, intmax_t); else value = va_arg (args, int); if (fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags) == -1) goto fail; break; case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (long)va_arg (args, unsigned LLONG); else if (cflags == DP_C_SIZE) value = va_arg (args, size_t); #ifdef notyet else if (cflags == DP_C_INTMAX) value = va_arg (args, uintmax_t); #endif else value = (long)va_arg (args, unsigned int); if (fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags) == -1) goto fail; break; case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else if (cflags == DP_C_SIZE) value = va_arg (args, size_t); #ifdef notyet else if (cflags == DP_C_INTMAX) value = va_arg (args, uintmax_t); #endif else value = (long)va_arg (args, unsigned int); if (fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags) == -1) goto fail; break; case 'X': flags |= DP_F_UP; case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else if (cflags == DP_C_SIZE) value = va_arg (args, size_t); #ifdef notyet else if (cflags == DP_C_INTMAX) value = va_arg (args, uintmax_t); #endif else value = (long)va_arg (args, unsigned int); if (fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags) == -1) goto fail; break; case 'f': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); if (fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags) == -1) goto fail; break; case 'E': flags |= DP_F_UP; case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); if (fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags) == -1) goto fail; break; case 'G': flags |= DP_F_UP; case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); if (fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags) == -1) goto fail; break; case 'c': DOPR_OUTCH(buffer, currlen, maxlen, va_arg (args, int)); break; case 's': strvalue = va_arg (args, char *); if (!strvalue) strvalue = "(NULL)"; if (max == -1) { max = strlen(strvalue); } if (min > 0 && max >= 0 && min > max) max = min; if (fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max) == -1) goto fail; break; case 'p': strvalue = va_arg (args, void *); if (fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags) == -1) goto fail; break; #if we_dont_want_this_in_openssh case 'n': if (cflags == DP_C_SHORT) { short int *num; num = va_arg (args, short int *); *num = currlen; } else if (cflags == DP_C_LONG) { long int *num; num = va_arg (args, long int *); *num = (long int)currlen; } else if (cflags == DP_C_LLONG) { LLONG *num; num = va_arg (args, LLONG *); *num = (LLONG)currlen; } else if (cflags == DP_C_SIZE) { ssize_t *num; num = va_arg (args, ssize_t *); *num = (ssize_t)currlen; } else if (cflags == DP_C_INTMAX) { intmax_t *num; num = va_arg (args, intmax_t *); *num = (intmax_t)currlen; } else { int *num; num = va_arg (args, int *); *num = currlen; } break; #endif case '%': DOPR_OUTCH(buffer, currlen, maxlen, ch); break; case 'w': /* not supported yet, treat as next char */ ch = *format++; break; default: /* Unknown, skip */ break; } ch = *format++; state = DP_S_DEFAULT; flags = cflags = min = 0; max = -1; break; case DP_S_DONE: break; default: /* hmm? */ break; /* some picky compilers need this */ } } if (maxlen != 0) { if (currlen < maxlen - 1) buffer[currlen] = '\0'; else if (maxlen > 0) buffer[maxlen - 1] = '\0'; } va_end(args); return currlen < INT_MAX ? (int)currlen : -1; fail: va_end(args); return -1; } static int fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max) { int padlen, strln; /* amount to pad */ int cnt = 0; #ifdef DEBUG_SNPRINTF printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); #endif if (value == 0) { value = ""; } for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */ padlen = min - strln; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ while ((padlen > 0) && (cnt < max)) { DOPR_OUTCH(buffer, *currlen, maxlen, ' '); --padlen; ++cnt; } while (*value && (cnt < max)) { DOPR_OUTCH(buffer, *currlen, maxlen, *value); value++; ++cnt; } while ((padlen < 0) && (cnt < max)) { DOPR_OUTCH(buffer, *currlen, maxlen, ' '); ++padlen; ++cnt; } return 0; } /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ static int fmtint(char *buffer, size_t *currlen, size_t maxlen, intmax_t value, int base, int min, int max, int flags) { int signvalue = 0; unsigned LLONG uvalue; char convert[20]; int place = 0; int spadlen = 0; /* amount to space pad */ int zpadlen = 0; /* amount to zero pad */ int caps = 0; if (max < 0) max = 0; uvalue = value; if(!(flags & DP_F_UNSIGNED)) { if( value < 0 ) { signvalue = '-'; uvalue = -value; } else { if (flags & DP_F_PLUS) /* Do a sign (+/i) */ signvalue = '+'; else if (flags & DP_F_SPACE) signvalue = ' '; } } if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ do { convert[place++] = (caps? "0123456789ABCDEF":"0123456789abcdef") [uvalue % (unsigned)base ]; uvalue = (uvalue / (unsigned)base ); } while(uvalue && (place < 20)); if (place == 20) place--; convert[place] = 0; zpadlen = max - place; spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; if (flags & DP_F_ZERO) { zpadlen = MAX(zpadlen, spadlen); spadlen = 0; } if (flags & DP_F_MINUS) spadlen = -spadlen; /* Left Justifty */ #ifdef DEBUG_SNPRINTF printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", zpadlen, spadlen, min, max, place); #endif /* Spaces */ while (spadlen > 0) { DOPR_OUTCH(buffer, *currlen, maxlen, ' '); --spadlen; } /* Sign */ if (signvalue) DOPR_OUTCH(buffer, *currlen, maxlen, signvalue); /* Zeros */ if (zpadlen > 0) { while (zpadlen > 0) { DOPR_OUTCH(buffer, *currlen, maxlen, '0'); --zpadlen; } } /* Digits */ while (place > 0) { --place; DOPR_OUTCH(buffer, *currlen, maxlen, convert[place]); } /* Left Justified spaces */ while (spadlen < 0) { DOPR_OUTCH(buffer, *currlen, maxlen, ' '); ++spadlen; } return 0; } static LDOUBLE abs_val(LDOUBLE value) { LDOUBLE result = value; if (value < 0) result = -value; return result; } static LDOUBLE POW10(int val) { LDOUBLE result = 1; while (val) { result *= 10; val--; } return result; } static LLONG ROUND(LDOUBLE value) { LLONG intpart; intpart = (LLONG)value; value = value - intpart; if (value >= 0.5) intpart++; return intpart; } /* a replacement for modf that doesn't need the math library. Should be portable, but slow */ static double my_modf(double x0, double *iptr) { int i; long l; double x = x0; double f = 1.0; for (i=0;i<100;i++) { l = (long)x; if (l <= (x+1) && l >= (x-1)) break; x *= 0.1; f *= 10.0; } if (i == 100) { /* * yikes! the number is beyond what we can handle. * What do we do? */ (*iptr) = 0; return 0; } if (i != 0) { double i2; double ret; ret = my_modf(x0-l*f, &i2); (*iptr) = l*f + i2; return ret; } (*iptr) = l; return x - (*iptr); } static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags) { int signvalue = 0; double ufvalue; char iconvert[311]; char fconvert[311]; int iplace = 0; int fplace = 0; int padlen = 0; /* amount to pad */ int zpadlen = 0; #if 0 int caps = 0; #endif int idx; double intpart; double fracpart; double temp; /* * AIX manpage says the default is 0, but Solaris says the default * is 6, and sprintf on AIX defaults to 6 */ if (max < 0) max = 6; ufvalue = abs_val (fvalue); if (fvalue < 0) { signvalue = '-'; } else { if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ signvalue = '+'; } else { if (flags & DP_F_SPACE) signvalue = ' '; } } #if 0 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ #endif #if 0 if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ #endif /* * Sorry, we only support 16 digits past the decimal because of our * conversion method */ if (max > 16) max = 16; /* We "cheat" by converting the fractional part to integer by * multiplying by a factor of 10 */ temp = ufvalue; my_modf(temp, &intpart); fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); if (fracpart >= POW10(max)) { intpart++; fracpart -= POW10(max); } /* Convert integer part */ do { temp = intpart*0.1; my_modf(temp, &intpart); idx = (int) ((temp -intpart +0.05)* 10.0); /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ iconvert[iplace++] = "0123456789"[idx]; } while (intpart && (iplace < 311)); if (iplace == 311) iplace--; iconvert[iplace] = 0; /* Convert fractional part */ if (fracpart) { do { temp = fracpart*0.1; my_modf(temp, &fracpart); idx = (int) ((temp -fracpart +0.05)* 10.0); /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ fconvert[fplace++] = "0123456789"[idx]; } while(fracpart && (fplace < 311)); if (fplace == 311) fplace--; } fconvert[fplace] = 0; /* -1 for decimal point, another -1 if we are printing a sign */ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); zpadlen = max - fplace; if (zpadlen < 0) zpadlen = 0; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justifty */ if ((flags & DP_F_ZERO) && (padlen > 0)) { if (signvalue) { DOPR_OUTCH(buffer, *currlen, maxlen, signvalue); --padlen; signvalue = 0; } while (padlen > 0) { DOPR_OUTCH(buffer, *currlen, maxlen, '0'); --padlen; } } while (padlen > 0) { DOPR_OUTCH(buffer, *currlen, maxlen, ' '); --padlen; } if (signvalue) DOPR_OUTCH(buffer, *currlen, maxlen, signvalue); while (iplace > 0) { --iplace; DOPR_OUTCH(buffer, *currlen, maxlen, iconvert[iplace]); } #ifdef DEBUG_SNPRINTF printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); #endif /* * Decimal point. This should probably use locale to find the correct * char to print out. */ if (max > 0) { DOPR_OUTCH(buffer, *currlen, maxlen, '.'); while (zpadlen > 0) { DOPR_OUTCH(buffer, *currlen, maxlen, '0'); --zpadlen; } while (fplace > 0) { --fplace; DOPR_OUTCH(buffer, *currlen, maxlen, fconvert[fplace]); } } while (padlen < 0) { DOPR_OUTCH(buffer, *currlen, maxlen, ' '); ++padlen; } return 0; } #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ #if !defined(HAVE_VSNPRINTF) int vsnprintf (char *str, size_t count, const char *fmt, va_list args) { return dopr(str, count, fmt, args); } #endif #if !defined(HAVE_SNPRINTF) int snprintf(char *str, size_t count, SNPRINTF_CONST char *fmt, ...) { size_t ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); return ret; } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-statvfs.c100644 001750 001750 0000000003614775415623 0020473xustar0030 atime=1744182234.653150076 openssh-10.0p1/openbsd-compat/bsd-statvfs.c010064400017500001750000000043721477541562300170640ustar00djmdjm/* * Copyright (c) 2008,2014 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 MIND, 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_STATVFS) || !defined(HAVE_FSTATVFS) #ifdef HAVE_SYS_MOUNT_H # include #endif #include #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) { to->f_bsize = from->f_bsize; to->f_frsize = from->f_bsize; /* no exact equivalent */ to->f_blocks = from->f_blocks; to->f_bfree = from->f_bfree; to->f_bavail = from->f_bavail; to->f_files = from->f_files; to->f_ffree = from->f_ffree; to->f_favail = from->f_ffree; /* no exact equivalent */ to->f_fsid = 0; /* XXX fix me */ #ifdef HAVE_STRUCT_STATFS_F_FLAGS to->f_flag = from->f_flags; #else to->f_flag = 0; #endif to->f_namemax = MNAMELEN; } #endif # ifndef HAVE_STATVFS int statvfs(const char *path, struct statvfs *buf) { # if defined(HAVE_STATFS) && defined(HAVE_STRUCT_STATFS) struct statfs fs; memset(&fs, 0, sizeof(fs)); if (statfs(path, &fs) == -1) return -1; copy_statfs_to_statvfs(buf, &fs); return 0; # else errno = ENOSYS; return -1; # endif } # endif # ifndef HAVE_FSTATVFS int fstatvfs(int fd, struct statvfs *buf) { # if defined(HAVE_FSTATFS) && defined(HAVE_STRUCT_STATFS) struct statfs fs; memset(&fs, 0, sizeof(fs)); if (fstatfs(fd, &fs) == -1) return -1; copy_statfs_to_statvfs(buf, &fs); return 0; # else errno = ENOSYS; return -1; # endif } # endif #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-statvfs.h100644 001750 001750 0000000003614775415623 0020500xustar0030 atime=1744182234.653150076 openssh-10.0p1/openbsd-compat/bsd-statvfs.h010064400017500001750000000043671477541562300170750ustar00djmdjm/* * Copyright (c) 2008,2014 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 MIND, 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_STATVFS) || !defined(HAVE_FSTATVFS) #include #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifndef HAVE_FSBLKCNT_T typedef unsigned long fsblkcnt_t; #endif #ifndef HAVE_FSFILCNT_T typedef unsigned long fsfilcnt_t; #endif #ifndef ST_RDONLY #define ST_RDONLY 1 #endif #ifndef ST_NOSUID #define ST_NOSUID 2 #endif /* as defined in IEEE Std 1003.1, 2004 Edition */ struct statvfs { unsigned long f_bsize; /* File system block size. */ unsigned long f_frsize; /* Fundamental file system block size. */ fsblkcnt_t f_blocks; /* Total number of blocks on file system in */ /* units of f_frsize. */ fsblkcnt_t f_bfree; /* Total number of free blocks. */ fsblkcnt_t f_bavail; /* Number of free blocks available to */ /* non-privileged process. */ fsfilcnt_t f_files; /* Total number of file serial numbers. */ fsfilcnt_t f_ffree; /* Total number of free file serial numbers. */ fsfilcnt_t f_favail; /* Number of file serial numbers available to */ /* non-privileged process. */ unsigned long f_fsid; /* File system ID. */ unsigned long f_flag; /* BBit mask of f_flag values. */ unsigned long f_namemax;/* Maximum filename length. */ }; #endif #ifndef HAVE_STATVFS int statvfs(const char *, struct statvfs *); #endif #ifndef HAVE_FSTATVFS int fstatvfs(int, struct statvfs *); #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-timegm.c100644 001750 001750 0000000003614775415623 0020263xustar0030 atime=1744182234.654126303 openssh-10.0p1/openbsd-compat/bsd-timegm.c010064400017500001750000000050001477541562300166410ustar00djmdjm/* * Copyright (c) 1997 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. */ /* adapted for Samba4 by Andrew Tridgell */ #include "includes.h" #include #ifndef HAVE_TIMEGM static int is_leap(unsigned y) { y += 1900; return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); } time_t timegm(struct tm *tm) { static const unsigned ndays[2][12] ={ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; time_t res = 0; unsigned i; if (tm->tm_mon > 12 || tm->tm_mon < 0 || tm->tm_mday > 31 || tm->tm_min > 60 || tm->tm_sec > 60 || tm->tm_hour > 24) { /* invalid tm structure */ return 0; } for (i = 70; i < tm->tm_year; ++i) res += is_leap(i) ? 366 : 365; for (i = 0; i < tm->tm_mon; ++i) res += ndays[is_leap(tm->tm_year)][i]; res += tm->tm_mday - 1; res *= 24; res += tm->tm_hour; res *= 60; res += tm->tm_min; res *= 60; res += tm->tm_sec; return res; } #endif /* HAVE_TIMEGM */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-waitpid.c100644 001750 001750 0000000003614775415623 0020442xustar0030 atime=1744182234.654126303 openssh-10.0p1/openbsd-compat/bsd-waitpid.c010064400017500001750000000034271477541562300170330ustar00djmdjm/* * Copyright (c) 2000 Ben Lindstrom. 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" #ifndef HAVE_WAITPID #include #include #include "bsd-waitpid.h" pid_t waitpid(int pid, int *stat_loc, int options) { union wait statusp; pid_t wait_pid; if (pid <= 0) { if (pid != -1) { errno = EINVAL; return (-1); } /* wait4() wants pid=0 for indiscriminate wait. */ pid = 0; } wait_pid = wait4(pid, &statusp, options, NULL); if (stat_loc) *stat_loc = (int) statusp.w_status; return (wait_pid); } #endif /* !HAVE_WAITPID */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/bsd-waitpid.h100644 001750 001750 0000000003614775415623 0020447xustar0030 atime=1744182234.654126303 openssh-10.0p1/openbsd-compat/bsd-waitpid.h010064400017500001750000000040271477541562300170350ustar00djmdjm/* * Copyright (c) 2000 Ben Lindstrom. 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 _BSD_WAITPID_H #define _BSD_WAITPID_H #ifndef HAVE_WAITPID /* Clean out any potential issues */ #undef WIFEXITED #undef WIFSTOPPED #undef WIFSIGNALED /* Define required functions to mimic a POSIX look and feel */ #define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */ #define WIFEXITED(w) (!((_W_INT(w)) & 0377)) #define WIFSTOPPED(w) ((_W_INT(w)) & 0100) #define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w)) #define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1) #define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1) #define WCOREFLAG 0x80 #define WCOREDUMP(w) ((_W_INT(w)) & WCOREFLAG) /* Prototype */ pid_t waitpid(int, int *, int); #endif /* !HAVE_WAITPID */ #endif /* _BSD_WAITPID_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/chacha_private.h100644 001750 001750 0000000003614775415623 0021201xustar0030 atime=1744182234.654126303 openssh-10.0p1/openbsd-compat/chacha_private.h010064400017500001750000000124771477541562300175770ustar00djmdjm/* OPENBSD ORIGINAL: lib/libc/crypt/chacha_private.h */ /* chacha-merged.c version 20080118 D. J. Bernstein Public domain. */ /* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */ typedef unsigned char u8; typedef unsigned int u32; typedef struct { u32 input[16]; /* could be compressed */ } chacha_ctx; #define U8C(v) (v##U) #define U32C(v) (v##U) #define U8V(v) ((u8)(v) & U8C(0xFF)) #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) #define ROTL32(v, n) \ (U32V((v) << (n)) | ((v) >> (32 - (n)))) #define U8TO32_LITTLE(p) \ (((u32)((p)[0]) ) | \ ((u32)((p)[1]) << 8) | \ ((u32)((p)[2]) << 16) | \ ((u32)((p)[3]) << 24)) #define U32TO8_LITTLE(p, v) \ do { \ (p)[0] = U8V((v) ); \ (p)[1] = U8V((v) >> 8); \ (p)[2] = U8V((v) >> 16); \ (p)[3] = U8V((v) >> 24); \ } while (0) #define ROTATE(v,c) (ROTL32(v,c)) #define XOR(v,w) ((v) ^ (w)) #define PLUS(v,w) (U32V((v) + (w))) #define PLUSONE(v) (PLUS((v),1)) #define QUARTERROUND(a,b,c,d) \ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); static const char sigma[16] = "expand 32-byte k"; static const char tau[16] = "expand 16-byte k"; static void chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) { const char *constants; x->input[4] = U8TO32_LITTLE(k + 0); x->input[5] = U8TO32_LITTLE(k + 4); x->input[6] = U8TO32_LITTLE(k + 8); x->input[7] = U8TO32_LITTLE(k + 12); if (kbits == 256) { /* recommended */ k += 16; constants = sigma; } else { /* kbits == 128 */ constants = tau; } x->input[8] = U8TO32_LITTLE(k + 0); x->input[9] = U8TO32_LITTLE(k + 4); x->input[10] = U8TO32_LITTLE(k + 8); x->input[11] = U8TO32_LITTLE(k + 12); x->input[0] = U8TO32_LITTLE(constants + 0); x->input[1] = U8TO32_LITTLE(constants + 4); x->input[2] = U8TO32_LITTLE(constants + 8); x->input[3] = U8TO32_LITTLE(constants + 12); } static void chacha_ivsetup(chacha_ctx *x,const u8 *iv) { x->input[12] = 0; x->input[13] = 0; x->input[14] = U8TO32_LITTLE(iv + 0); x->input[15] = U8TO32_LITTLE(iv + 4); } static void chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) { u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; u8 *ctarget = NULL; u8 tmp[64]; u_int i; if (!bytes) return; j0 = x->input[0]; j1 = x->input[1]; j2 = x->input[2]; j3 = x->input[3]; j4 = x->input[4]; j5 = x->input[5]; j6 = x->input[6]; j7 = x->input[7]; j8 = x->input[8]; j9 = x->input[9]; j10 = x->input[10]; j11 = x->input[11]; j12 = x->input[12]; j13 = x->input[13]; j14 = x->input[14]; j15 = x->input[15]; for (;;) { if (bytes < 64) { for (i = 0;i < bytes;++i) tmp[i] = m[i]; m = tmp; ctarget = c; c = tmp; } x0 = j0; x1 = j1; x2 = j2; x3 = j3; x4 = j4; x5 = j5; x6 = j6; x7 = j7; x8 = j8; x9 = j9; x10 = j10; x11 = j11; x12 = j12; x13 = j13; x14 = j14; x15 = j15; for (i = 20;i > 0;i -= 2) { QUARTERROUND( x0, x4, x8,x12) QUARTERROUND( x1, x5, x9,x13) QUARTERROUND( x2, x6,x10,x14) QUARTERROUND( x3, x7,x11,x15) QUARTERROUND( x0, x5,x10,x15) QUARTERROUND( x1, x6,x11,x12) QUARTERROUND( x2, x7, x8,x13) QUARTERROUND( x3, x4, x9,x14) } x0 = PLUS(x0,j0); x1 = PLUS(x1,j1); x2 = PLUS(x2,j2); x3 = PLUS(x3,j3); x4 = PLUS(x4,j4); x5 = PLUS(x5,j5); x6 = PLUS(x6,j6); x7 = PLUS(x7,j7); x8 = PLUS(x8,j8); x9 = PLUS(x9,j9); x10 = PLUS(x10,j10); x11 = PLUS(x11,j11); x12 = PLUS(x12,j12); x13 = PLUS(x13,j13); x14 = PLUS(x14,j14); x15 = PLUS(x15,j15); #ifndef KEYSTREAM_ONLY x0 = XOR(x0,U8TO32_LITTLE(m + 0)); x1 = XOR(x1,U8TO32_LITTLE(m + 4)); x2 = XOR(x2,U8TO32_LITTLE(m + 8)); x3 = XOR(x3,U8TO32_LITTLE(m + 12)); x4 = XOR(x4,U8TO32_LITTLE(m + 16)); x5 = XOR(x5,U8TO32_LITTLE(m + 20)); x6 = XOR(x6,U8TO32_LITTLE(m + 24)); x7 = XOR(x7,U8TO32_LITTLE(m + 28)); x8 = XOR(x8,U8TO32_LITTLE(m + 32)); x9 = XOR(x9,U8TO32_LITTLE(m + 36)); x10 = XOR(x10,U8TO32_LITTLE(m + 40)); x11 = XOR(x11,U8TO32_LITTLE(m + 44)); x12 = XOR(x12,U8TO32_LITTLE(m + 48)); x13 = XOR(x13,U8TO32_LITTLE(m + 52)); x14 = XOR(x14,U8TO32_LITTLE(m + 56)); x15 = XOR(x15,U8TO32_LITTLE(m + 60)); #endif j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); /* stopping at 2^70 bytes per nonce is user's responsibility */ } U32TO8_LITTLE(c + 0,x0); U32TO8_LITTLE(c + 4,x1); U32TO8_LITTLE(c + 8,x2); U32TO8_LITTLE(c + 12,x3); U32TO8_LITTLE(c + 16,x4); U32TO8_LITTLE(c + 20,x5); U32TO8_LITTLE(c + 24,x6); U32TO8_LITTLE(c + 28,x7); U32TO8_LITTLE(c + 32,x8); U32TO8_LITTLE(c + 36,x9); U32TO8_LITTLE(c + 40,x10); U32TO8_LITTLE(c + 44,x11); U32TO8_LITTLE(c + 48,x12); U32TO8_LITTLE(c + 52,x13); U32TO8_LITTLE(c + 56,x14); U32TO8_LITTLE(c + 60,x15); if (bytes <= 64) { if (bytes < 64) { for (i = 0;i < bytes;++i) ctarget[i] = c[i]; } x->input[12] = j12; x->input[13] = j13; return; } bytes -= 64; c += 64; #ifndef KEYSTREAM_ONLY m += 64; #endif } } openssh-10.0p1/openbsd-compat/PaxHeaders.10889/charclass.h100644 001750 001750 0000000003614775415623 0020203xustar0030 atime=1744182234.654126303 openssh-10.0p1/openbsd-compat/charclass.h010064400017500001750000000012761477541562300165740ustar00djmdjm/* * Public domain, 2008, Todd C. Miller * * $OpenBSD: charclass.h,v 1.1 2008/10/01 23:04:13 millert Exp $ */ /* OPENBSD ORIGINAL: lib/libc/gen/charclass.h */ /* * POSIX character class support for fnmatch() and glob(). */ static struct cclass { const char *name; int (*isctype)(int); } cclasses[] = { { "alnum", isalnum }, { "alpha", isalpha }, { "blank", isblank }, { "cntrl", iscntrl }, { "digit", isdigit }, { "graph", isgraph }, { "lower", islower }, { "print", isprint }, { "punct", ispunct }, { "space", isspace }, { "upper", isupper }, { "xdigit", isxdigit }, { NULL, NULL } }; #define NCCLASSES (sizeof(cclasses) / sizeof(cclasses[0]) - 1) openssh-10.0p1/openbsd-compat/PaxHeaders.10889/glob.c100644 001750 001750 0000000003514775415623 0017155xustar0029 atime=1744182234.65900978 openssh-10.0p1/openbsd-compat/glob.c010064400017500001750000000633331477541562300155510ustar00djmdjm/* $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. * * This code is derived from software contributed to Berkeley by * Guido van Rossum. * * 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/gen/glob.c */ /* * glob(3) -- a superset of the one defined in POSIX 1003.2. * * The [!...] convention to negate a range is supported (SysV, Posix, ksh). * * Optional extra services, controlled by flags not defined by POSIX: * * GLOB_QUOTE: * Escaping convention: \ inhibits any special meaning the following * character might have (except \ at end of string is retained). * GLOB_MAGCHAR: * Set in gl_flags if pattern contained a globbing character. * GLOB_NOMAGIC: * Same as GLOB_NOCHECK, but it will only append pattern if it did * not contain any magic characters. [Used in csh style globbing] * GLOB_ALTDIRFUNC: * Use alternately specified directory access functions. * GLOB_TILDE: * expand ~user/foo to the /home/dir/of/user/foo * GLOB_BRACE: * expand {1,2}{a,b} to 1a 1b 2a 2b * gl_matchc: * Number of matches in the current invocation of glob. */ #include "includes.h" #include "glob.h" #include #include #include #include #include #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #if !defined(HAVE_GLOB) || !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 "charclass.h" #ifdef TILDE # undef TILDE #endif #define DOLLAR '$' #define DOT '.' #define EOS '\0' #define LBRACKET '[' #define NOT '!' #define QUESTION '?' #define QUOTE '\\' #define RANGE '-' #define RBRACKET ']' #define SEP '/' #define STAR '*' #define TILDE '~' #define UNDERSCORE '_' #define LBRACE '{' #define RBRACE '}' #define SLASH '/' #define COMMA ',' #ifndef DEBUG #define M_QUOTE 0x8000 #define M_PROTECT 0x4000 #define M_MASK 0xffff #define M_ASCII 0x00ff typedef u_short Char; #else #define M_QUOTE 0x80 #define M_PROTECT 0x40 #define M_MASK 0xff #define M_ASCII 0x7f typedef char Char; #endif #define CHAR(c) ((Char)((c)&M_ASCII)) #define META(c) ((Char)((c)|M_QUOTE)) #define M_ALL META('*') #define M_END META(']') #define M_NOT META('!') #define M_ONE META('?') #define M_RNG META('-') #define M_SET META('[') #define M_CLASS META(':') #define ismeta(c) (((c)&M_QUOTE) != 0) #define GLOB_LIMIT_MALLOC 65536 #define GLOB_LIMIT_STAT 2048 #define GLOB_LIMIT_READDIR 16384 struct glob_lim { size_t glim_malloc; size_t glim_stat; size_t glim_readdir; }; struct glob_path_stat { char *gps_path; struct stat *gps_stat; }; static int compare(const void *, const void *); static int compare_gps(const void *, const void *); 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); static int g_strncmp(const Char *, const char *, size_t); static int g_stat(Char *, struct stat *, glob_t *); static int glob0(const Char *, glob_t *, struct glob_lim *); static int glob1(Char *, Char *, glob_t *, struct glob_lim *); static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, glob_t *, struct glob_lim *); static int glob3(Char *, Char *, Char *, Char *, Char *, Char *, Char *, glob_t *, struct glob_lim *); static int globextend(const Char *, glob_t *, struct glob_lim *, struct stat *); static const Char * globtilde(const Char *, Char *, size_t, glob_t *); 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 *); #ifdef DEBUG static void qprintf(const char *, Char *); #endif int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const u_char *patnext; int c; Char *bufnext, *bufend, patbuf[PATH_MAX]; struct glob_lim limit = { 0, 0, 0 }; patnext = (u_char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; pglob->gl_statv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; 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 + PATH_MAX - 1; if (flags & GLOB_NOESCAPE) while (bufnext < bufend && (c = *patnext++) != EOS) *bufnext++ = c; else { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != EOS) if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; } *bufnext = EOS; if (flags & GLOB_BRACE) return globexp1(patbuf, pglob, &limit); else return glob0(patbuf, pglob, &limit); } /* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char* ptr = pattern; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) return glob0(pattern, pglob, limitp); if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) return globexp2(ptr, pattern, pglob, limitp); return glob0(pattern, pglob, limitp); } /* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { int i, rv; Char *lm, *ls; const Char *pe, *pm, *pl; Char patbuf[PATH_MAX]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) ; *lm = EOS; ls = lm; /* Find the balanced brace */ for (i = 0, pe = ++ptr; *pe; pe++) if (*pe == LBRACKET) { /* Ignore everything between [] */ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) ; if (*pe == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pe = pm; } } else if (*pe == LBRACE) i++; else if (*pe == RBRACE) { if (i == 0) break; i--; } /* Non matching braces; just glob the pattern */ if (i != 0 || *pe == EOS) return glob0(patbuf, pglob, limitp); for (i = 0, pl = pm = ptr; pm <= pe; pm++) { switch (*pm) { case LBRACKET: /* Ignore everything between [] */ for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) ; if (*pm == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pm = pl; } break; case LBRACE: i++; break; case RBRACE: if (i) { i--; break; } /* FALLTHROUGH */ case COMMA: if (i && *pm == COMMA) break; else { /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) ; /* * Append the rest of the pattern after the * closing brace */ for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) ; /* Expand the current pattern */ #ifdef DEBUG qprintf("globexp2:", patbuf); #endif rv = globexp1(patbuf, pglob, limitp); if (rv && rv != GLOB_NOMATCH) return rv; /* move after the comma, to the next string */ pl = pm + 1; } break; default: break; } } return 0; } /* * expand tilde from the passwd file. */ static const Char * globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) { struct passwd *pwd; char *h; const Char *p; Char *b, *eb; if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) return pattern; /* Copy up to the end of the string or / */ eb = &patbuf[patbuf_len - 1]; for (p = pattern + 1, h = (char *) patbuf; h < (char *)eb && *p && *p != SLASH; *h++ = *p++) ; *h = EOS; #if 0 if (h == (char *)eb) return what; #endif if (((char *) patbuf)[0] == EOS) { /* * handle a plain ~ or ~/ by expanding $HOME * first and then trying the password file */ #if 0 if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { #endif if ((getuid() != geteuid()) || (h = getenv("HOME")) == NULL) { if ((pwd = getpwuid(getuid())) == NULL) return pattern; else h = pwd->pw_dir; } } else { /* * Expand a ~user */ if ((pwd = getpwnam((char*) patbuf)) == NULL) return pattern; else h = pwd->pw_dir; } /* Copy the home directory */ for (b = patbuf; b < eb && *h; *b++ = *h++) ; /* Append the rest of the pattern */ while (b < eb && (*b++ = *p++) != EOS) ; *b = EOS; return patbuf; } static int g_strncmp(const Char *s1, const char *s2, size_t n) { int rv = 0; while (n--) { rv = *(Char *)s1 - *(const unsigned char *)s2++; if (rv) break; if (*s1++ == '\0') break; } return rv; } static int g_charclass(const Char **patternp, Char **bufnextp) { const Char *pattern = *patternp + 1; Char *bufnext = *bufnextp; const Char *colon; struct cclass *cc; size_t len; if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']') return 1; /* not a character class */ len = (size_t)(colon - pattern); for (cc = cclasses; cc->name != NULL; cc++) { if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0') break; } if (cc->name == NULL) return -1; /* invalid character class */ *bufnext++ = M_CLASS; *bufnext++ = (Char)(cc - &cclasses[0]); *bufnextp = bufnext; *patternp += len + 3; return 0; } /* * The main glob() routine: compiles the pattern (optionally processing * quotes), calls glob1() to do the real pattern matching, and finally * sorts the list (unless unsorted operation is requested). Returns 0 * if things went well, nonzero if errors occurred. It is not an error * to find no matches. */ static int glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char *qpatnext; int c, err; size_t oldpathc; Char *bufnext, patbuf[PATH_MAX]; qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob); oldpathc = pglob->gl_pathc; bufnext = patbuf; /* We don't need to check for buffer overflow any more. */ while ((c = *qpatnext++) != EOS) { switch (c) { case LBRACKET: c = *qpatnext; if (c == NOT) ++qpatnext; if (*qpatnext == EOS || g_strchr(qpatnext+1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == NOT) --qpatnext; break; } *bufnext++ = M_SET; if (c == NOT) *bufnext++ = M_NOT; c = *qpatnext++; do { if (c == LBRACKET && *qpatnext == ':') { do { err = g_charclass(&qpatnext, &bufnext); if (err) break; c = *qpatnext++; } while (c == LBRACKET && *qpatnext == ':'); if (err == -1 && !(pglob->gl_flags & GLOB_NOCHECK)) return GLOB_NOMATCH; if (c == RBRACKET) break; } *bufnext++ = CHAR(c); if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET) { *bufnext++ = M_RNG; *bufnext++ = CHAR(c); qpatnext += 2; } } while ((c = *qpatnext++) != RBRACKET); pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_END; break; case QUESTION: pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_ONE; break; case STAR: pglob->gl_flags |= GLOB_MAGCHAR; /* collapse adjacent stars to one, * to avoid exponential behavior */ if (bufnext == patbuf || bufnext[-1] != M_ALL) *bufnext++ = M_ALL; break; default: *bufnext++ = CHAR(c); break; } } *bufnext = EOS; #ifdef DEBUG qprintf("glob0:", patbuf); #endif if ((err = glob1(patbuf, patbuf+PATH_MAX-1, pglob, limitp)) != 0) return(err); /* * If there was no match we are going to append the pattern * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified * and the pattern did not contain any magic characters * GLOB_NOMAGIC is there just for compatibility with csh. */ if (pglob->gl_pathc == oldpathc) { if ((pglob->gl_flags & GLOB_NOCHECK) || ((pglob->gl_flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR))) return(globextend(pattern, pglob, limitp, NULL)); else return(GLOB_NOMATCH); } if (!(pglob->gl_flags & GLOB_NOSORT)) { if ((pglob->gl_flags & GLOB_KEEPSTAT)) { /* Keep the paths and stat info synced during sort */ struct glob_path_stat *path_stat; 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; for (i = 0; i < n; i++) { path_stat[i].gps_path = pglob->gl_pathv[o + i]; path_stat[i].gps_stat = pglob->gl_statv[o + i]; } qsort(path_stat, n, sizeof(*path_stat), compare_gps); for (i = 0; i < n; i++) { pglob->gl_pathv[o + i] = path_stat[i].gps_path; pglob->gl_statv[o + i] = path_stat[i].gps_stat; } free(path_stat); } else { qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), compare); } } return(0); } static int compare(const void *p, const void *q) { return(strcmp(*(char **)p, *(char **)q)); } static int compare_gps(const void *_p, const void *_q) { const struct glob_path_stat *p = (const struct glob_path_stat *)_p; const struct glob_path_stat *q = (const struct glob_path_stat *)_q; return(strcmp(p->gps_path, q->gps_path)); } static int glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { Char pathbuf[PATH_MAX]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == EOS) return(0); return(glob2(pathbuf, pathbuf+PATH_MAX-1, pathbuf, pathbuf+PATH_MAX-1, pattern, pattern_last, pglob, limitp)); } /* * The functions glob2 and glob3 are mutually recursive; there is one level * of recursion for each segment in the pattern that contains one or more * meta characters. */ static int glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { struct stat sb; Char *p, *q; int anymeta; /* * Loop over pattern segments until end of pattern or until * segment with meta character found. */ for (anymeta = 0;;) { if (*pattern == EOS) { /* End of pattern? */ *pathend = EOS; if ((pglob->gl_flags & GLOB_LIMIT) && limitp->glim_stat++ >= GLOB_LIMIT_STAT) { errno = 0; *pathend++ = SEP; *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) || (S_ISLNK(sb.st_mode) && (g_stat(pathbuf, &sb, pglob) == 0) && S_ISDIR(sb.st_mode)))) { if (pathend+1 > pathend_last) return (1); *pathend++ = SEP; *pathend = EOS; } ++pglob->gl_matchc; return(globextend(pathbuf, pglob, limitp, &sb)); } /* Find end of next segment, copy tentatively to pathend. */ q = pathend; p = pattern; while (*p != EOS && *p != SEP) { if (ismeta(*p)) anymeta = 1; if (q+1 > pathend_last) return (1); *q++ = *p++; } if (!anymeta) { /* No expansion, do next segment. */ pathend = q; pattern = p; while (*pattern == SEP) { if (pathend+1 > pathend_last) return (1); *pathend++ = *pattern++; } } else /* Need expansion, recurse. */ return(glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, p, pattern_last, pglob, limitp)); } /* NOTREACHED */ } static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, struct glob_lim *limitp) { struct dirent *dp; DIR *dirp; int err; char buf[PATH_MAX]; /* * The readdirfunc declaration can't be prototyped, because it is * assigned, below, to two functions which are prototyped in glob.h * and dirent.h as taking pointers to differently typed opaque * structures. */ struct dirent *(*readdirfunc)(void *); if (pathend > pathend_last) return (1); *pathend = EOS; errno = 0; if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { /* TODO: don't call for ENOENT or ENOTDIR? */ if (pglob->gl_errfunc) { if (g_Ctoc(pathbuf, buf, sizeof(buf))) return(GLOB_ABORTED); if (pglob->gl_errfunc(buf, errno) || pglob->gl_flags & GLOB_ERR) return(GLOB_ABORTED); } return(0); } err = 0; /* Search directory for matching names. */ if (pglob->gl_flags & GLOB_ALTDIRFUNC) readdirfunc = pglob->gl_readdir; else readdirfunc = (struct dirent *(*)(void *))readdir; while ((dp = (*readdirfunc)(dirp))) { u_char *sc; Char *dc; if ((pglob->gl_flags & GLOB_LIMIT) && limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { errno = 0; *pathend++ = SEP; *pathend = EOS; err = GLOB_NOSPACE; break; } /* Initial DOT must be matched literally. */ if (dp->d_name[0] == DOT && *pattern != DOT) continue; dc = pathend; sc = (u_char *) dp->d_name; while (dc < pathend_last && (*dc++ = *sc++) != EOS) ; if (dc >= pathend_last) { *dc = EOS; err = 1; break; } if (!match(pathend, pattern, restpattern)) { *pathend = EOS; continue; } err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, restpattern, restpattern_last, pglob, limitp); if (err) break; } if (pglob->gl_flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir)(dirp); else closedir(dirp); return(err); } /* * Extend the gl_pathv member of a glob_t structure to accommodate a new item, * add the new item, and update gl_pathc. * * This assumes the BSD realloc, which only copies the block when its size * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic * behavior. * * Return 0 if new item added, error code if memory couldn't be allocated. * * Invariant of the glob_t structure: * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ static int globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, struct stat *sb) { char **pathv; 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 >= 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 < 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]); } free(pglob->gl_pathv); pglob->gl_pathv = NULL; free(pglob->gl_statv); pglob->gl_statv = NULL; return(GLOB_NOSPACE); } 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; i--) *--pathv = NULL; } pglob->gl_pathv = pathv; if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { 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; i--) *--statv = NULL; } pglob->gl_statv = statv; if (sb == NULL) statv[pglob->gl_offs + pglob->gl_pathc] = NULL; else { limitp->glim_malloc += sizeof(**statv); if ((pglob->gl_flags & GLOB_LIMIT) && limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { errno = 0; return(GLOB_NOSPACE); } if ((statv[pglob->gl_offs + pglob->gl_pathc] = malloc(sizeof(**statv))) == NULL) goto copy_error; memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, sizeof(*sb)); } statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL; } for (p = path; *p++;) ; len = (size_t)(p - path); limitp->glim_malloc += len; if ((copy = malloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { free(copy); return(GLOB_NOSPACE); } pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; } pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; if ((pglob->gl_flags & GLOB_LIMIT) && (newn * sizeof(*pathv)) + limitp->glim_malloc > GLOB_LIMIT_MALLOC) { errno = 0; return(GLOB_NOSPACE); } copy_error: return(copy == NULL ? GLOB_NOSPACE : 0); } /* * pattern matching function for filenames. Each occurrence of the * * 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 ok, negate_range; Char c, k; Char *nextp = NULL; Char *nextn = NULL; loop: while (pat < patend) { c = *pat++; switch (c & M_MASK) { case M_ALL: while (pat < patend && (*pat & M_MASK) == M_ALL) pat++; /* eat consecutive '*' */ if (pat == patend) return(1); if (*name == EOS) return(0); nextn = name + 1; nextp = pat - 1; break; case M_ONE: if (*name++ == EOS) goto fail; break; case M_SET: ok = 0; if ((k = *name++) == EOS) goto fail; if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) ++pat; while (((c = *pat++) & M_MASK) != M_END) { if ((c & M_MASK) == M_CLASS) { Char idx = *pat & M_MASK; if (idx < NCCLASSES && cclasses[idx].isctype(k)) ok = 1; ++pat; } if ((*pat & M_MASK) == M_RNG) { if (c <= k && k <= pat[1]) ok = 1; pat += 2; } else if (c == k) ok = 1; } if (ok == negate_range) goto fail; break; default: if (*name++ != c) goto fail; break; } } 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) { size_t i; char **pp; if (pglob->gl_pathv != NULL) { pp = pglob->gl_pathv + pglob->gl_offs; for (i = pglob->gl_pathc; i--; ++pp) free(*pp); free(pglob->gl_pathv); pglob->gl_pathv = NULL; } if (pglob->gl_statv != NULL) { for (i = 0; i < pglob->gl_pathc; i++) { free(pglob->gl_statv[i]); } free(pglob->gl_statv); pglob->gl_statv = NULL; } } static DIR * g_opendir(Char *str, glob_t *pglob) { char buf[PATH_MAX]; if (!*str) strlcpy(buf, ".", sizeof buf); else { if (g_Ctoc(str, buf, sizeof(buf))) return(NULL); } if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_opendir)(buf)); return(opendir(buf)); } static int g_lstat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[PATH_MAX]; if (g_Ctoc(fn, buf, sizeof(buf))) return(-1); if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_lstat)(buf, sb)); return(lstat(buf, sb)); } static int g_stat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[PATH_MAX]; if (g_Ctoc(fn, buf, sizeof(buf))) return(-1); if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_stat)(buf, sb)); return(stat(buf, sb)); } static Char * g_strchr(const Char *str, int ch) { do { if (*str == ch) return ((Char *)str); } while (*str++); return (NULL); } static int g_Ctoc(const Char *str, char *buf, size_t len) { while (len--) { if ((*buf++ = *str++) == EOS) return (0); } return (1); } #ifdef DEBUG static void qprintf(const char *str, Char *s) { Char *p; (void)printf("%s:\n", str); for (p = s; *p; p++) (void)printf("%c", CHAR(*p)); (void)printf("\n"); for (p = s; *p; p++) (void)printf("%c", *p & M_PROTECT ? '"' : ' '); (void)printf("\n"); for (p = s; *p; p++) (void)printf("%c", ismeta(*p) ? '_' : ' '); (void)printf("\n"); } #endif #endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/daemon.c100644 001750 001750 0000000003614775415623 0017476xustar0030 atime=1744182234.654126303 openssh-10.0p1/openbsd-compat/daemon.c010064400017500001750000000045131477541562300160640ustar00djmdjm/* $OpenBSD: daemon.c,v 1.6 2005/08/08 08:05:33 espie Exp $ */ /*- * Copyright (c) 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: * 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/gen/daemon.c */ #include "includes.h" #ifndef HAVE_DAEMON #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifdef HAVE_UNISTD_H # include #endif int daemon(int nochdir, int noclose) { int fd; switch (fork()) { case -1: return (-1); case 0: break; default: _exit(0); } if (setsid() == -1) return (-1); if (!nochdir) (void)chdir("/"); if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDERR_FILENO); if (fd > 2) (void)close (fd); } return (0); } #endif /* !HAVE_DAEMON */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/dirname.c100644 001750 001750 0000000003614775415623 0017652xustar0030 atime=1744182234.654126303 openssh-10.0p1/openbsd-compat/dirname.c010064400017500001750000000035411477541562300162400ustar00djmdjm/* $OpenBSD: dirname.c,v 1.13 2005/08/08 08:05:33 espie Exp $ */ /* * Copyright (c) 1997, 2004 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* OPENBSD ORIGINAL: lib/libc/gen/dirname.c */ #include "includes.h" #ifndef HAVE_DIRNAME #include #include char * dirname(const char *path) { static char dname[MAXPATHLEN]; size_t len; const char *endp; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { dname[0] = '.'; dname[1] = '\0'; return (dname); } /* Strip any trailing slashes */ endp = path + strlen(path) - 1; while (endp > path && *endp == '/') endp--; /* Find the start of the dir */ while (endp > path && *endp != '/') endp--; /* Either the dir is "/" or there are no slashes */ if (endp == path) { dname[0] = *endp == '/' ? '/' : '.'; dname[1] = '\0'; return (dname); } else { /* Move forward past the separating slashes */ do { endp--; } while (endp > path && *endp == '/'); } len = endp - path + 1; if (len >= sizeof(dname)) { errno = ENAMETOOLONG; return (NULL); } memcpy(dname, path, len); dname[len] = '\0'; return (dname); } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/explicit_bzero.c100644 001750 001750 0000000003514775415623 0021254xustar0029 atime=1744182234.65510298 openssh-10.0p1/openbsd-compat/explicit_bzero.c010064400017500001750000000023151477541562300176410ustar00djmdjm/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */ /* $OpenBSD: explicit_bzero.c,v 1.1 2014/01/22 21:06:45 tedu Exp $ */ /* * Public domain. * Written by Ted Unangst */ #include "includes.h" #include /* * explicit_bzero - don't let the compiler optimize away bzero */ #ifndef HAVE_EXPLICIT_BZERO #ifdef HAVE_EXPLICIT_MEMSET void explicit_bzero(void *p, size_t n) { (void)explicit_memset(p, 0, n); } #elif defined(HAVE_MEMSET_S) void explicit_bzero(void *p, size_t n) { if (n == 0) return; (void)memset_s(p, n, 0, n); } #else /* HAVE_MEMSET_S */ /* * Indirect bzero through a volatile pointer to hopefully avoid * dead-store optimisation eliminating the call. */ static void (* volatile ssh_bzero)(void *, size_t) = bzero; void explicit_bzero(void *p, size_t 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 */ #endif /* HAVE_EXPLICIT_BZERO */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/fake-rfc2553.c100644 001750 001750 0000000003514775415623 0020227xustar0029 atime=1744182234.65510298 openssh-10.0p1/openbsd-compat/fake-rfc2553.c010064400017500001750000000142271477541562300166210ustar00djmdjm/* * 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: * 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 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 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT 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. */ /* * Pseudo-implementation of RFC2553 name / address resolution functions * * But these functions are not implemented correctly. The minimum subset * is implemented for ssh use only. For example, this routine assumes * that ai_family is AF_INET. Don't use it for another purpose. */ #include "includes.h" #include #include #include #include #ifndef HAVE_GETNAMEINFO 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; char tmpserv[16]; if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET) return (EAI_FAMILY); if (serv != NULL) { snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); if (strlcpy(serv, tmpserv, servlen) >= servlen) return (EAI_MEMORY); } if (host != NULL) { if (flags & NI_NUMERICHOST) { if (strlcpy(host, inet_ntoa(sin->sin_addr), hostlen) >= hostlen) return (EAI_MEMORY); else return (0); } else { 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 return (0); } } return (0); } #endif /* !HAVE_GETNAMEINFO */ #ifndef HAVE_GAI_STRERROR #ifdef HAVE_CONST_GAI_STRERROR_PROTO const char * #else char * #endif gai_strerror(int err) { switch (err) { case EAI_NODATA: return ("no address associated with name"); case EAI_MEMORY: return ("memory allocation failure."); case EAI_NONAME: return ("nodename nor servname provided, or not known"); case EAI_FAMILY: return ("ai_family not supported"); default: return ("unknown/invalid error."); } } #endif /* !HAVE_GAI_STRERROR */ #ifndef HAVE_FREEADDRINFO void freeaddrinfo(struct addrinfo *ai) { struct addrinfo *next; for(; ai != NULL;) { next = ai->ai_next; free(ai); ai = next; } } #endif /* !HAVE_FREEADDRINFO */ #ifndef HAVE_GETADDRINFO static struct addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) { struct addrinfo *ai; 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); ai->ai_addr->sa_family = ai->ai_family = AF_INET; ((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; else ai->ai_socktype = SOCK_STREAM; if (hints->ai_protocol) ai->ai_protocol = hints->ai_protocol; return (ai); } int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { struct hostent *hp; struct servent *sp; struct in_addr in; int i; long int port; u_long addr; port = 0; if (hints && hints->ai_family != AF_UNSPEC && hints->ai_family != AF_INET) return (EAI_FAMILY); if (servname != NULL) { char *cp; port = strtol(servname, &cp, 10); if (port > 0 && port <= 65535 && *cp == '\0') port = htons(port); else if ((sp = getservbyname(servname, NULL)) != NULL) port = sp->s_port; else port = 0; } if (hints && hints->ai_flags & AI_PASSIVE) { addr = htonl(0x00000000); if (hostname && inet_aton(hostname, &in) != 0) addr = in.s_addr; *res = malloc_ai(port, addr, hints); if (*res == NULL) return (EAI_MEMORY); return (0); } if (!hostname) { *res = malloc_ai(port, htonl(0x7f000001), hints); if (*res == NULL) return (EAI_MEMORY); return (0); } if (inet_aton(hostname, &in)) { *res = malloc_ai(port, in.s_addr, hints); 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; cur = prev = *res = NULL; for (i = 0; hp->h_addr_list[i]; i++) { struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; cur = malloc_ai(port, in->s_addr, hints); if (cur == NULL) { if (*res != NULL) freeaddrinfo(*res); return (EAI_MEMORY); } if (prev) prev->ai_next = cur; else *res = cur; prev = cur; } return (0); } return (EAI_NODATA); } #endif /* !HAVE_GETADDRINFO */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/fake-rfc2553.h100644 001750 001750 0000000003514775415623 0020234xustar0029 atime=1744182234.65510298 openssh-10.0p1/openbsd-compat/fake-rfc2553.h010064400017500001750000000123151477541562300166220ustar00djmdjm/* * 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: * 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 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 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT 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. */ /* * Pseudo-implementation of RFC2553 name / address resolution functions * * But these functions are not implemented correctly. The minimum subset * is implemented for ssh use only. For example, this routine assumes * that ai_family is AF_INET. Don't use it for another purpose. */ #ifndef _FAKE_RFC2553_H #define _FAKE_RFC2553_H #include "includes.h" #include #if defined(HAVE_NETDB_H) # include #endif /* * First, socket and INET6 related definitions */ #ifndef HAVE_STRUCT_SOCKADDR_STORAGE # define _SS_MAXSIZE 128 /* Implementation specific max size */ # define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) struct sockaddr_storage { struct sockaddr ss_sa; char __ss_pad2[_SS_PADSIZE]; }; # 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 HAVE_STRUCT_IN6_ADDR struct in6_addr { u_int8_t s6_addr[16]; }; #endif /* !HAVE_STRUCT_IN6_ADDR */ #ifndef HAVE_STRUCT_SOCKADDR_IN6 struct sockaddr_in6 { unsigned short sin6_family; u_int16_t sin6_port; u_int32_t sin6_flowinfo; struct in6_addr sin6_addr; u_int32_t sin6_scope_id; }; #endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ #ifndef AF_INET6 /* Define it to something that should never appear */ #define AF_INET6 AF_MAX #endif /* * Next, RFC2553 name / address resolution API */ #ifndef NI_NUMERICHOST # define NI_NUMERICHOST (1) #endif #ifndef NI_NAMEREQD # define NI_NAMEREQD (1<<1) #endif #ifndef NI_NUMERICSERV # define NI_NUMERICSERV (1<<2) #endif #ifndef AI_PASSIVE # define AI_PASSIVE (1) #endif #ifndef AI_CANONNAME # define AI_CANONNAME (1<<1) #endif #ifndef AI_NUMERICHOST # define AI_NUMERICHOST (1<<2) #endif #ifndef AI_NUMERICSERV # define AI_NUMERICSERV (1<<3) #endif #ifndef NI_MAXSERV # define NI_MAXSERV 32 #endif /* !NI_MAXSERV */ #ifndef NI_MAXHOST # define NI_MAXHOST 1025 #endif /* !NI_MAXHOST */ #ifndef EAI_NODATA # define EAI_NODATA (INT_MAX - 1) #endif #ifndef EAI_MEMORY # define EAI_MEMORY (INT_MAX - 2) #endif #ifndef EAI_NONAME # define EAI_NONAME (INT_MAX - 3) #endif #ifndef EAI_SYSTEM # define EAI_SYSTEM (INT_MAX - 4) #endif #ifndef EAI_FAMILY # define EAI_FAMILY (INT_MAX - 5) #endif #ifndef HAVE_STRUCT_ADDRINFO struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ size_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; #endif /* !HAVE_STRUCT_ADDRINFO */ #ifndef HAVE_GETADDRINFO #ifdef getaddrinfo # undef getaddrinfo #endif #define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d)) int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); #endif /* !HAVE_GETADDRINFO */ #if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO) #define gai_strerror(a) (_ssh_compat_gai_strerror(a)) char *gai_strerror(int); #endif /* !HAVE_GAI_STRERROR */ #ifndef HAVE_FREEADDRINFO #define freeaddrinfo(a) (ssh_freeaddrinfo(a)) void freeaddrinfo(struct addrinfo *); #endif /* !HAVE_FREEADDRINFO */ #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, char *, size_t, int); #endif /* !HAVE_GETNAMEINFO */ #endif /* !_FAKE_RFC2553_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/fmt_scaled.c100644 001750 001750 0000000003514775415623 0020333xustar0029 atime=1744182234.65510298 openssh-10.0p1/openbsd-compat/fmt_scaled.c010064400017500001750000000175221477541562300167260ustar00djmdjm/* $OpenBSD: fmt_scaled.c,v 1.21 2022/03/11 07:29:53 dtucker Exp $ */ /* * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. 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. 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. */ /* OPENBSD ORIGINAL: lib/libutil/fmt_scaled.c */ /* * fmt_scaled: Format numbers scaled for human comprehension * scan_scaled: Scan numbers in this format. * * "Human-readable" output uses 4 digits max, and puts a unit suffix at * the end. Makes output compact and easy-to-read esp. on huge disks. * Formatting code was originally in OpenBSD "df", converted to library routine. * Scanning code written for OpenBSD libutil. */ #include "includes.h" #ifndef HAVE_FMT_SCALED #include #include #include #include #include #include typedef enum { NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6 } unit_type; /* These three arrays MUST be in sync! XXX make a struct */ static const unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA }; static const char scale_chars[] = "BKMGTPE"; static const long long scale_factors[] = { 1LL, 1024LL, 1024LL*1024, 1024LL*1024*1024, 1024LL*1024*1024*1024, 1024LL*1024*1024*1024*1024, 1024LL*1024*1024*1024*1024*1024, }; #define SCALE_LENGTH (sizeof(units)/sizeof(units[0])) #define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ /* Convert the given input string "scaled" into numeric in "result". * Return 0 on success, -1 and errno set on error. */ int scan_scaled(char *scaled, long long *result) { char *p = scaled; int sign = 0; unsigned int i, ndigits = 0, fract_digits = 0; long long scale_fact = 1, whole = 0, fpart = 0; /* Skip leading whitespace */ while (isascii((unsigned char)*p) && isspace((unsigned char)*p)) ++p; /* Then at most one leading + or - */ while (*p == '-' || *p == '+') { if (*p == '-') { if (sign) { errno = EINVAL; return -1; } sign = -1; ++p; } else if (*p == '+') { if (sign) { errno = EINVAL; return -1; } sign = +1; ++p; } } /* Main loop: Scan digits, find decimal point, if present. * We don't allow exponentials, so no scientific notation * (but note that E for Exa might look like e to some!). * Advance 'p' to end, to get scale factor. */ for (; isascii((unsigned char)*p) && (isdigit((unsigned char)*p) || *p=='.'); ++p) { if (*p == '.') { if (fract_digits > 0) { /* oops, more than one '.' */ errno = EINVAL; return -1; } fract_digits = 1; continue; } i = (*p) - '0'; /* whew! finally a digit we can use */ if (fract_digits > 0) { if (fract_digits >= MAX_DIGITS-1) /* 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; } } if (sign) whole *= sign; /* If no scale factor given, we're done. fraction is discarded. */ if (!*p) { *result = whole; return 0; } /* Validate scale factor, and scale whole and fraction by it. */ for (i = 0; i < SCALE_LENGTH; i++) { /* Are we there yet? */ if (*p == scale_chars[i] || *p == tolower((unsigned char)scale_chars[i])) { /* If it ends with alphanumerics after the scale char, bad. */ 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 doesn't overflow. * then scale fractional part. */ while (fpart >= LLONG_MAX / scale_fact || fpart <= LLONG_MIN / scale_fact) { fpart /= 10; fract_digits--; } fpart *= scale_fact; if (fract_digits > 0) { for (i = 0; i < fract_digits -1; i++) fpart /= 10; } if (sign == -1) whole -= fpart; else whole += fpart; *result = whole; return 0; } } /* Invalid unit or character */ errno = EINVAL; return -1; } /* Format the given "number" into human-readable form in "result". * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE. * Return 0 on success, -1 and errno set if error. */ int fmt_scaled(long long number, char *result) { long long abval, fract = 0; unsigned int i; unit_type unit = NONE; /* Not every negative long long has a positive representation. */ if (number == LLONG_MIN) { errno = ERANGE; return -1; } abval = llabs(number); /* Also check for numbers that are just too darned big to format. */ if (abval / 1024 >= scale_factors[SCALE_LENGTH-1]) { errno = ERANGE; return -1; } /* scale whole part; get unscaled fraction */ for (i = 0; i < SCALE_LENGTH; i++) { if (abval/1024 < scale_factors[i]) { unit = units[i]; fract = (i == 0) ? 0 : abval % scale_factors[i]; number /= scale_factors[i]; if (i > 0) fract /= scale_factors[i - 1]; break; } } fract = (10 * fract + 512) / 1024; /* if the result would be >= 10, round main number */ if (fract >= 10) { if (number >= 0) number++; else number--; fract = 0; } else if (fract < 0) { /* shouldn't happen */ fract = 0; } if (number == 0) strlcpy(result, "0B", FMT_SCALED_STRSIZE); else if (unit == NONE || number >= 100 || number <= -100) { if (fract >= 5) { if (number >= 0) number++; else number--; } (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c", number, scale_chars[unit]); } else (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c", number, fract, scale_chars[unit]); return 0; } #ifdef MAIN /* * This is the original version of the program in the man page. * Copy-and-paste whatever you need from it. */ int main(int argc, char **argv) { char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE]; long long ninput = 10483892, result; if (scan_scaled(cinput, &result) == 0) printf("\"%s\" -> %lld\n", cinput, result); else perror(cinput); if (fmt_scaled(ninput, buf) == 0) printf("%lld -> \"%s\"\n", ninput, buf); else fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno)); return 0; } #endif #endif /* HAVE_FMT_SCALED */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/fnmatch.c100644 001750 001750 0000000003614775415623 0017653xustar0030 atime=1744182234.656079457 openssh-10.0p1/openbsd-compat/fnmatch.c010064400017500001750000000363161477541562300162470ustar00djmdjm/* $OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $ */ /* Copyright (c) 2011, VMware, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the VMware, Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2008, 2016 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Authored by William A. Rowe Jr. , April 2011 * * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008 * as described in; * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html * * Filename pattern matches defined in section 2.13, "Pattern Matching Notation" * from chapter 2. "Shell Command Language" * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13 * where; 1. A bracket expression starting with an unquoted '^' * character CONTINUES to specify a non-matching list; 2. an explicit '.' * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading * in a filename; 3. a '[' which does not introduce * a valid bracket expression is treated as an ordinary character; 4. a differing * number of consecutive slashes within pattern and string will NOT match; * 5. a trailing '\' in FNM_ESCAPE mode is treated as an ordinary '\' character. * * Bracket expansion defined in section 9.3.5, "RE Bracket Expression", * from chapter 9, "Regular Expressions" * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05 * with no support for collating symbols, equivalence class expressions or * character class expressions. A partial range expression with a leading * hyphen following a valid range expression will match only the ordinary * and the ending character (e.g. "[a-m-z]" will match characters * 'a' through 'm', a '-', or a 'z'). * * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one * path segment of string, and FNM_CASEFOLD to ignore alpha case. * * NOTE: Only POSIX/C single byte locales are correctly supported at this time. * Notably, non-POSIX locales with FNM_CASEFOLD produce undefined results, * particularly in ranges of mixed case (e.g. "[A-z]") or spanning alpha and * nonalpha characters within a range. * * XXX comments below indicate porting required for multi-byte character sets * and non-POSIX locale collation orders; requires mbr* APIs to track shift * state of pattern and string (rewinding pattern and string repeatedly). * * Certain parts of the code assume 0x00-0x3F are unique with any MBCS (e.g. * UTF-8, SHIFT-JIS, etc). Any implementation allowing '\' as an alternate * path delimiter must be aware that 0x5C is NOT unique within SHIFT-JIS. */ /* OPENBSD ORIGINAL: lib/libc/gen/fnmatch.c */ #include "includes.h" #ifndef HAVE_FNMATCH #include #include #include #include "charclass.h" #define RANGE_MATCH 1 #define RANGE_NOMATCH 0 #define RANGE_ERROR (-1) static int classmatch(const char *pattern, char test, int foldcase, const char **ep) { const char * const mismatch = pattern; const char *colon; struct cclass *cc; int rval = RANGE_NOMATCH; size_t len; if (pattern[0] != '[' || pattern[1] != ':') { *ep = mismatch; return RANGE_ERROR; } pattern += 2; if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') { *ep = mismatch; return RANGE_ERROR; } *ep = colon + 2; len = (size_t)(colon - pattern); if (foldcase && strncmp(pattern, "upper:]", 7) == 0) pattern = "lower:]"; for (cc = cclasses; cc->name != NULL; cc++) { if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') { if (cc->isctype((unsigned char)test)) rval = RANGE_MATCH; break; } } if (cc->name == NULL) { /* invalid character class, treat as normal text */ *ep = mismatch; rval = RANGE_ERROR; } return rval; } /* Most MBCS/collation/case issues handled here. Wildcard '*' is not handled. * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over, * however the "\/" sequence is advanced to '/'. * * Both pattern and string are **char to support pointer increment of arbitrary * multibyte characters for the given locale, in a later iteration of this code */ static int fnmatch_ch(const char **pattern, const char **string, int flags) { const char * const mismatch = *pattern; const int nocase = !!(flags & FNM_CASEFOLD); const int escape = !(flags & FNM_NOESCAPE); const int slash = !!(flags & FNM_PATHNAME); int result = FNM_NOMATCH; const char *startch; int negate; if (**pattern == '[') { ++*pattern; /* Handle negation, either leading ! or ^ operators */ negate = (**pattern == '!') || (**pattern == '^'); if (negate) ++*pattern; /* ']' is an ordinary char at the start of the range pattern */ if (**pattern == ']') goto leadingclosebrace; while (**pattern) { if (**pattern == ']') { ++*pattern; /* XXX: Fix for MBCS character width */ ++*string; return (result ^ negate); } if (escape && (**pattern == '\\')) { ++*pattern; /* Patterns must terminate with ']', not EOS */ if (!**pattern) break; } /* Patterns must terminate with ']' not '/' */ if (slash && (**pattern == '/')) break; /* Match character classes. */ switch (classmatch(*pattern, **string, nocase, pattern)) { case RANGE_MATCH: result = 0; continue; case RANGE_NOMATCH: /* Valid character class but no match. */ continue; default: /* Not a valid character class. */ break; } if (!**pattern) break; leadingclosebrace: /* Look at only well-formed range patterns; * "x-]" is not allowed unless escaped ("x-\]") * XXX: Fix for locale/MBCS character width */ if (((*pattern)[1] == '-') && ((*pattern)[2] != ']')) { startch = *pattern; *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2; /* * NOT a properly balanced [expr] pattern, EOS * terminated or ranges containing a slash in * FNM_PATHNAME mode pattern fall out to to the * rewind and test '[' literal code path. */ if (!**pattern || (slash && (**pattern == '/'))) break; /* XXX: handle locale/MBCS comparison, advance by MBCS char width */ if ((**string >= *startch) && (**string <= **pattern)) result = 0; else if (nocase && (isupper((unsigned char)**string) || isupper((unsigned char)*startch) || isupper((unsigned char)**pattern)) && (tolower((unsigned char)**string) >= tolower((unsigned char)*startch)) && (tolower((unsigned char)**string) <= tolower((unsigned char)**pattern))) result = 0; ++*pattern; continue; } /* XXX: handle locale/MBCS comparison, advance by MBCS char width */ if ((**string == **pattern)) result = 0; else if (nocase && (isupper((unsigned char)**string) || isupper((unsigned char)**pattern)) && (tolower((unsigned char)**string) == tolower((unsigned char)**pattern))) result = 0; ++*pattern; } /* * NOT a properly balanced [expr] pattern; * Rewind and reset result to test '[' literal */ *pattern = mismatch; result = FNM_NOMATCH; } else if (**pattern == '?') { /* Optimize '?' match before unescaping **pattern */ if (!**string || (slash && (**string == '/'))) return FNM_NOMATCH; result = 0; goto fnmatch_ch_success; } else if (escape && (**pattern == '\\') && (*pattern)[1]) { ++*pattern; } /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */ if (**string == **pattern) result = 0; else if (nocase && (isupper((unsigned char)**string) || isupper((unsigned char)**pattern)) && (tolower((unsigned char)**string) == tolower((unsigned char)**pattern))) result = 0; /* Refuse to advance over trailing slash or NULs */ if (**string == '\0' || **pattern == '\0' || (slash && ((**string == '/') || (**pattern == '/')))) return result; fnmatch_ch_success: ++*pattern; ++*string; return result; } int fnmatch(const char *pattern, const char *string, int flags) { static const char dummystring[2] = {' ', 0}; const int escape = !(flags & FNM_NOESCAPE); const int slash = !!(flags & FNM_PATHNAME); const int leading_dir = !!(flags & FNM_LEADING_DIR); const char *dummyptr, *matchptr, *strendseg; int wild; /* For '*' wild processing only; suppress 'used before initialization' * warnings with dummy initialization values; */ const char *strstartseg = NULL; const char *mismatch = NULL; int matchlen = 0; if (*pattern == '*') goto firstsegment; while (*pattern && *string) { /* * Pre-decode "\/" which has no special significance, and * match balanced slashes, starting a new segment pattern. */ if (slash && escape && (*pattern == '\\') && (pattern[1] == '/')) ++pattern; if (slash && (*pattern == '/') && (*string == '/')) { ++pattern; ++string; } firstsegment: /* * At the beginning of each segment, validate leading period * behavior. */ if ((flags & FNM_PERIOD) && (*string == '.')) { if (*pattern == '.') ++pattern; else if (escape && (*pattern == '\\') && (pattern[1] == '.')) pattern += 2; else return FNM_NOMATCH; ++string; } /* * Determine the end of string segment. Presumes '/' * character is unique, not composite in any MBCS encoding */ if (slash) { strendseg = strchr(string, '/'); if (!strendseg) strendseg = strchr(string, '\0'); } else { strendseg = strchr(string, '\0'); } /* * Allow pattern '*' to be consumed even with no remaining * string to match. */ while (*pattern) { if ((string > strendseg) || ((string == strendseg) && (*pattern != '*'))) break; if (slash && ((*pattern == '/') || (escape && (*pattern == '\\') && (pattern[1] == '/')))) break; /* * Reduce groups of '*' and '?' to n '?' matches * followed by one '*' test for simplicity. */ for (wild = 0; (*pattern == '*') || (*pattern == '?'); ++pattern) { if (*pattern == '*') { wild = 1; } else if (string < strendseg) { /* && (*pattern == '?') */ /* XXX: Advance 1 char for MBCS locale */ ++string; } else { /* (string >= strendseg) && (*pattern == '?') */ return FNM_NOMATCH; } } if (wild) { strstartseg = string; mismatch = pattern; /* * Count fixed (non '*') char matches remaining * in pattern * excluding '/' (or "\/") and '*'. */ for (matchptr = pattern, matchlen = 0; 1; ++matchlen) { if ((*matchptr == '\0') || (slash && ((*matchptr == '/') || (escape && (*matchptr == '\\') && (matchptr[1] == '/'))))) { /* Compare precisely this many * trailing string chars, the * resulting match needs no * wildcard loop. */ /* XXX: Adjust for MBCS */ if (string + matchlen > strendseg) return FNM_NOMATCH; string = strendseg - matchlen; wild = 0; break; } if (*matchptr == '*') { /* * Ensure at least this many * trailing string chars remain * for the first comparison. */ /* XXX: Adjust for MBCS */ if (string + matchlen > strendseg) return FNM_NOMATCH; /* * Begin first wild comparison * at the current position. */ break; } /* * Skip forward in pattern by a single * character match Use a dummy * fnmatch_ch() test to count one * "[range]" escape. */ /* XXX: Adjust for MBCS */ if (escape && (*matchptr == '\\') && matchptr[1]) { matchptr += 2; } else if (*matchptr == '[') { dummyptr = dummystring; fnmatch_ch(&matchptr, &dummyptr, flags); } else { ++matchptr; } } } /* Incrementally match string against the pattern. */ while (*pattern && (string < strendseg)) { /* Success; begin a new wild pattern search. */ if (*pattern == '*') break; if (slash && ((*string == '/') || (*pattern == '/') || (escape && (*pattern == '\\') && (pattern[1] == '/')))) break; /* * Compare ch's (the pattern is advanced over * "\/" to the '/', but slashes will mismatch, * and are not consumed). */ if (!fnmatch_ch(&pattern, &string, flags)) continue; /* * Failed to match, loop against next char * offset of string segment until not enough * string chars remain to match the fixed * pattern. */ if (wild) { /* XXX: Advance 1 char for MBCS locale */ string = ++strstartseg; if (string + matchlen > strendseg) return FNM_NOMATCH; pattern = mismatch; continue; } else return FNM_NOMATCH; } } if (*string && !((slash || leading_dir) && (*string == '/'))) return FNM_NOMATCH; if (*pattern && !(slash && ((*pattern == '/') || (escape && (*pattern == '\\') && (pattern[1] == '/'))))) return FNM_NOMATCH; if (leading_dir && !*pattern && *string == '/') return 0; } /* Where both pattern and string are at EOS, declare success. */ if (!*string && !*pattern) return 0; /* Pattern didn't match to the end of string. */ return FNM_NOMATCH; } #endif /* HAVE_FNMATCH */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/fnmatch.h100644 001750 001750 0000000003614775415623 0017660xustar0030 atime=1744182234.656079457 openssh-10.0p1/openbsd-compat/fnmatch.h010064400017500001750000000051171477541562300162470ustar00djmdjm/* $OpenBSD: fnmatch.h,v 1.8 2005/12/13 00:35:22 millert Exp $ */ /* $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 */ /* OPENBSD ORIGINAL: include/fnmatch.h */ #ifndef HAVE_FNMATCH_H /* Ensure we define FNM_CASEFOLD */ #define __BSD_VISIBLE 1 #ifndef _FNMATCH_H_ #define _FNMATCH_H_ #ifdef HAVE_SYS_CDEFS_H #include #endif #define FNM_NOMATCH 1 /* Match failed. */ #define FNM_NOSYS 2 /* Function not supported (unused). */ #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ #define FNM_PERIOD 0x04 /* Period must be matched by period. */ #if __BSD_VISIBLE #define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ #define FNM_CASEFOLD 0x10 /* Case insensitive search. */ #define FNM_IGNORECASE FNM_CASEFOLD #define FNM_FILE_NAME FNM_PATHNAME #endif /* __BEGIN_DECLS */ int fnmatch(const char *, const char *, int); /* __END_DECLS */ #endif /* !_FNMATCH_H_ */ #endif /* ! HAVE_FNMATCH_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/freezero.c100644 001750 001750 0000000003614775415623 0020054xustar0030 atime=1744182234.656079457 openssh-10.0p1/openbsd-compat/freezero.c010064400017500001750000000020061477541562300164350ustar00djmdjm/* * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #ifndef HAVE_FREEZERO void freezero(void *ptr, size_t sz) { if (ptr == NULL) return; explicit_bzero(ptr, sz); free(ptr); } #endif /* HAVE_FREEZERO */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/getcwd.c100644 001750 001750 0000000003614775415623 0017510xustar0030 atime=1744182234.656079457 openssh-10.0p1/openbsd-compat/getcwd.c010064400017500001750000000137641477541562300161060ustar00djmdjm/* $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. * * 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/gen/getcwd.c */ #include "includes.h" #if !defined(HAVE_GETCWD) #include #include #include #include #include #include #include #include "includes.h" #define ISDOT(dp) \ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \ (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) char * getcwd(char *pt, size_t size) { struct dirent *dp; DIR *dir = NULL; dev_t dev; ino_t ino; int first; char *bpt, *bup; struct stat s; dev_t root_dev; ino_t root_ino; size_t ptsize, upsize; int save_errno; char *ept, *eup, *up; /* * If no buffer specified by the user, allocate one as necessary. * If a buffer is specified, the size has to be non-zero. The path * is built from the end of the buffer backwards. */ if (pt) { ptsize = 0; if (size == 0) { errno = EINVAL; return (NULL); } else if (size == 1) { errno = ERANGE; return (NULL); } ept = pt + size; } else { if ((pt = malloc(ptsize = MAXPATHLEN)) == NULL) return (NULL); ept = pt + ptsize; } bpt = ept - 1; *bpt = '\0'; /* * Allocate bytes for the string of "../"'s. * Should always be enough (it's 340 levels). If it's not, allocate * as necessary. Special * case the first stat, it's ".", not "..". */ if ((up = malloc(upsize = MAXPATHLEN)) == NULL) goto err; eup = up + upsize; bup = up; up[0] = '.'; up[1] = '\0'; /* Save root values, so know when to stop. */ if (stat("/", &s)) goto err; root_dev = s.st_dev; root_ino = s.st_ino; errno = 0; /* XXX readdir has no error return. */ for (first = 1;; first = 0) { /* Stat the current level. */ if (lstat(up, &s)) goto err; /* Save current node values. */ ino = s.st_ino; dev = s.st_dev; /* Check for reaching root. */ if (root_dev == dev && root_ino == ino) { *--bpt = '/'; /* * It's unclear that it's a requirement to copy the * path to the beginning of the buffer, but it's always * been that way and stuff would probably break. */ memmove(pt, bpt, ept - bpt); free(up); return (pt); } /* * Build pointer to the parent directory, allocating memory * as necessary. Max length is 3 for "../", the largest * possible component name, plus a trailing NUL. */ if (bup + 3 + MAXNAMLEN + 1 >= eup) { char *nup; if ((nup = realloc(up, upsize *= 2)) == NULL) goto err; bup = nup + (bup - up); up = nup; eup = up + upsize; } *bup++ = '.'; *bup++ = '.'; *bup = '\0'; /* Open and stat parent directory. */ if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) goto err; /* Add trailing slash for next directory. */ *bup++ = '/'; /* * If it's a mount point, have to stat each element because * the inode number in the directory is for the entry in the * parent directory, not the inode number of the mounted file. */ save_errno = 0; if (s.st_dev == dev) { for (;;) { if (!(dp = readdir(dir))) goto notfound; if (dp->d_fileno == ino) break; } } else for (;;) { if (!(dp = readdir(dir))) goto notfound; if (ISDOT(dp)) continue; memcpy(bup, dp->d_name, dp->d_namlen + 1); /* Save the first error for later. */ if (lstat(up, &s)) { if (!save_errno) save_errno = errno; errno = 0; continue; } if (s.st_dev == dev && s.st_ino == ino) break; } /* * Check for length of the current name, preceding slash, * leading slash. */ if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) { size_t len; char *npt; if (!ptsize) { errno = ERANGE; goto err; } len = ept - bpt; if ((npt = realloc(pt, ptsize *= 2)) == NULL) goto err; bpt = npt + (bpt - pt); pt = npt; ept = pt + ptsize; memmove(ept - len, bpt, len); bpt = ept - len; } if (!first) *--bpt = '/'; bpt -= dp->d_namlen; memcpy(bpt, dp->d_name, dp->d_namlen); (void)closedir(dir); /* Truncate any file name. */ *bup = '\0'; } notfound: /* * If readdir set errno, use it, not any saved error; otherwise, * didn't find the current directory in its parent directory, set * errno to ENOENT. */ if (!errno) errno = save_errno ? save_errno : ENOENT; /* FALLTHROUGH */ err: save_errno = errno; if (ptsize) free(pt); free(up); if (dir) (void)closedir(dir); errno = save_errno; return (NULL); } #endif /* !defined(HAVE_GETCWD) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/getgrouplist.c100644 001750 001750 0000000003614775415623 0020763xustar0030 atime=1744182234.656079457 openssh-10.0p1/openbsd-compat/getgrouplist.c010064400017500001750000000053171477541562300173540ustar00djmdjm/* $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. * * 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/gen/getgrouplist.c */ #include "includes.h" #ifndef HAVE_GETGROUPLIST /* * get credential */ #include #include #include #include int getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) { struct group *grp; int i, ngroups; int ret, maxgroups; int bail; ret = 0; ngroups = 0; maxgroups = *grpcnt; /* * install primary group */ if (ngroups >= maxgroups) { *grpcnt = ngroups; return (-1); } groups[ngroups++] = agroup; /* * Scan the group file to find additional groups. */ setgrent(); while ((grp = getgrent())) { if (grp->gr_gid == agroup) continue; for (bail = 0, i = 0; bail == 0 && i < ngroups; i++) if (groups[i] == grp->gr_gid) bail = 1; if (bail) continue; for (i = 0; grp->gr_mem[i]; i++) { if (!strcmp(grp->gr_mem[i], uname)) { if (ngroups >= maxgroups) { ret = -1; goto out; } groups[ngroups++] = grp->gr_gid; break; } } } out: endgrent(); *grpcnt = ngroups; return (ret); } #endif /* HAVE_GETGROUPLIST */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/getopt.h100644 001750 001750 0000000003614775415623 0017542xustar0030 atime=1744182234.657056094 openssh-10.0p1/openbsd-compat/getopt.h010064400017500001750000000055341477541562300161340ustar00djmdjm/* $OpenBSD: getopt.h,v 1.2 2008/06/26 05:42:04 ray Exp $ */ /* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Dieter Baron and Thomas Klausner. * * 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. */ #ifndef _GETOPT_H_ #define _GETOPT_H_ #ifndef __THROW # if defined __cplusplus # define __THROW throw() # else # define __THROW # endif #endif /* * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if 0 struct option { /* name of long option */ const char *name; /* * one of no_argument, required_argument, and optional_argument: * whether option takes an argument */ int has_arg; /* if not NULL, set *flag to val when option found */ int *flag; /* if flag not NULL, value to set *flag to; else return value */ int val; }; int getopt_long(int, char * const *, const char *, const struct option *, int *); int getopt_long_only(int, char * const *, const char *, const struct option *, int *); #endif #ifndef _GETOPT_DEFINED_ #define _GETOPT_DEFINED_ int getopt(int, char * const *, const char *) __THROW; int getsubopt(char **, char * const *, char **) __THROW; extern char *optarg; /* getopt(3) external variables */ extern int opterr; extern int optind; extern int optopt; extern int optreset; extern char *suboptarg; /* getsubopt(3) external variable */ #endif #endif /* !_GETOPT_H_ */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/getopt_long.c100644 001750 001750 0000000003614775415623 0020554xustar0030 atime=1744182234.657056094 openssh-10.0p1/openbsd-compat/getopt_long.c010064400017500001750000000354521477541562300171500ustar00djmdjm/* $OpenBSD: getopt_long.c,v 1.25 2011/03/05 22:10:11 guenther Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ /* * Copyright (c) 2002 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * 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. */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Dieter Baron and Thomas Klausner. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* OPENBSD ORIGINAL: lib/libc/stdlib/getopt_long.c */ #include "includes.h" #if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) /* * Some defines to make it easier to keep the code in sync with upstream. * getopt opterr optind optopt optreset optarg are all in defines.h which is * pulled in by includes.h. */ #define warnx logit #if 0 #include #include #endif #include #include #include #include #include "log.h" struct option { /* name of long option */ const char *name; /* * one of no_argument, required_argument, and optional_argument: * whether option takes an argument */ int has_arg; /* if not NULL, set *flag to val when option found */ int *flag; /* if flag not NULL, value to set *flag to; else return value */ int val; }; int opterr = 1; /* if error message should be printed */ int optind = 1; /* index into parent argv vector */ int optopt = '?'; /* character checked for validity */ int optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #define PRINT_ERROR ((opterr) && (*options != ':')) #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ /* return values */ #define BADCH (int)'?' #define BADARG ((*options == ':') ? (int)':' : (int)'?') #define INORDER (int)1 #define EMSG "" static int getopt_internal(int, char * const *, const char *, const struct option *, int *, int); static int parse_long_options(char * const *, const char *, const struct option *, int *, int); static int gcd(int, int); static void permute_args(int, int, int, char * const *); static char *place = EMSG; /* option letter processing */ /* XXX: set optreset to 1 rather than these two */ static int nonopt_start = -1; /* first non option argument (for permute) */ static int nonopt_end = -1; /* first option after non options (for permute) */ /* Error messages */ static const char recargchar[] = "option requires an argument -- %c"; static const char recargstring[] = "option requires an argument -- %s"; static const char ambig[] = "ambiguous option -- %.*s"; static const char noarg[] = "option doesn't take an argument -- %.*s"; static const char illoptchar[] = "unknown option -- %c"; static const char illoptstring[] = "unknown option -- %s"; /* * Compute the greatest common divisor of a and b. */ static int gcd(int a, int b) { int c; c = a % b; while (c != 0) { a = b; b = c; c = a % b; } return (b); } /* * Exchange the block from nonopt_start to nonopt_end with the block * from nonopt_end to opt_end (keeping the same order of arguments * in each block). */ static void permute_args(int panonopt_start, int panonopt_end, int opt_end, char * const *nargv) { int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; char *swap; /* * compute lengths of blocks and number and size of cycles */ nnonopts = panonopt_end - panonopt_start; nopts = opt_end - panonopt_end; ncycle = gcd(nnonopts, nopts); cyclelen = (opt_end - panonopt_start) / ncycle; for (i = 0; i < ncycle; i++) { cstart = panonopt_end+i; pos = cstart; for (j = 0; j < cyclelen; j++) { if (pos >= panonopt_end) pos -= nnonopts; else pos += nopts; swap = nargv[pos]; /* LINTED const cast */ ((char **) nargv)[pos] = nargv[cstart]; /* LINTED const cast */ ((char **)nargv)[cstart] = swap; } } } /* * parse_long_options -- * Parse long options in argc/argv argument vector. * Returns -1 if short_too is set and the option does not match long_options. */ static int parse_long_options(char * const *nargv, const char *options, const struct option *long_options, int *idx, int short_too) { char *current_argv, *has_equal; size_t current_argv_len; int i, match; current_argv = place; match = -1; optind++; if ((has_equal = strchr(current_argv, '=')) != NULL) { /* argument found (--option=arg) */ current_argv_len = has_equal - current_argv; has_equal++; } else current_argv_len = strlen(current_argv); for (i = 0; long_options[i].name; i++) { /* find matching long option */ if (strncmp(current_argv, long_options[i].name, current_argv_len)) continue; if (strlen(long_options[i].name) == current_argv_len) { /* exact match */ match = i; break; } /* * If this is a known short option, don't allow * a partial match of a single character. */ if (short_too && current_argv_len == 1) continue; if (match == -1) /* partial match */ match = i; else { /* ambiguous abbreviation */ if (PRINT_ERROR) warnx(ambig, (int)current_argv_len, current_argv); optopt = 0; return (BADCH); } } if (match != -1) { /* option found */ if (long_options[match].has_arg == no_argument && has_equal) { if (PRINT_ERROR) warnx(noarg, (int)current_argv_len, current_argv); /* * XXX: GNU sets optopt to val regardless of flag */ if (long_options[match].flag == NULL) optopt = long_options[match].val; else optopt = 0; return (BADARG); } if (long_options[match].has_arg == required_argument || long_options[match].has_arg == optional_argument) { if (has_equal) optarg = has_equal; else if (long_options[match].has_arg == required_argument) { /* * optional argument doesn't use next nargv */ optarg = nargv[optind++]; } } if ((long_options[match].has_arg == required_argument) && (optarg == NULL)) { /* * Missing argument; leading ':' indicates no error * should be generated. */ if (PRINT_ERROR) warnx(recargstring, current_argv); /* * XXX: GNU sets optopt to val regardless of flag */ if (long_options[match].flag == NULL) optopt = long_options[match].val; else optopt = 0; --optind; return (BADARG); } } else { /* unknown option */ if (short_too) { --optind; return (-1); } if (PRINT_ERROR) warnx(illoptstring, current_argv); optopt = 0; return (BADCH); } if (idx) *idx = match; if (long_options[match].flag) { *long_options[match].flag = long_options[match].val; return (0); } else return (long_options[match].val); } /* * getopt_internal -- * Parse argc/argv argument vector. Called by user level routines. */ static int getopt_internal(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx, int flags) { char *oli; /* option letter list index */ int optchar, short_too; static int posixly_correct = -1; if (options == NULL) return (-1); /* * XXX Some GNU programs (like cvs) set optind to 0 instead of * XXX using optreset. Work around this braindamage. */ if (optind == 0) optind = optreset = 1; /* * Disable GNU extensions if POSIXLY_CORRECT is set or options * string begins with a '+'. */ if (posixly_correct == -1 || optreset) posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); if (*options == '-') flags |= FLAG_ALLARGS; else if (posixly_correct || *options == '+') flags &= ~FLAG_PERMUTE; if (*options == '+' || *options == '-') options++; optarg = NULL; if (optreset) nonopt_start = nonopt_end = -1; start: if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc) { /* end of argument vector */ place = EMSG; if (nonopt_end != -1) { /* do permutation, if we have to */ permute_args(nonopt_start, nonopt_end, optind, nargv); optind -= nonopt_end - nonopt_start; } else if (nonopt_start != -1) { /* * If we skipped non-options, set optind * to the first of them. */ optind = nonopt_start; } nonopt_start = nonopt_end = -1; return (-1); } if (*(place = nargv[optind]) != '-' || (place[1] == '\0' && strchr(options, '-') == NULL)) { place = EMSG; /* found non-option */ if (flags & FLAG_ALLARGS) { /* * GNU extension: * return non-option as argument to option 1 */ optarg = nargv[optind++]; return (INORDER); } if (!(flags & FLAG_PERMUTE)) { /* * If no permutation wanted, stop parsing * at first non-option. */ return (-1); } /* do permutation */ if (nonopt_start == -1) nonopt_start = optind; else if (nonopt_end != -1) { permute_args(nonopt_start, nonopt_end, optind, nargv); nonopt_start = optind - (nonopt_end - nonopt_start); nonopt_end = -1; } optind++; /* process next argument */ goto start; } if (nonopt_start != -1 && nonopt_end == -1) nonopt_end = optind; /* * If we have "-" do nothing, if "--" we are done. */ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { optind++; place = EMSG; /* * We found an option (--), so if we skipped * non-options, we have to permute. */ if (nonopt_end != -1) { permute_args(nonopt_start, nonopt_end, optind, nargv); optind -= nonopt_end - nonopt_start; } nonopt_start = nonopt_end = -1; return (-1); } } /* * Check long options if: * 1) we were passed some * 2) the arg is not just "-" * 3) either the arg starts with -- we are getopt_long_only() */ if (long_options != NULL && place != nargv[optind] && (*place == '-' || (flags & FLAG_LONGONLY))) { short_too = 0; if (*place == '-') place++; /* --foo long option */ else if (*place != ':' && strchr(options, *place) != NULL) short_too = 1; /* could be short option too */ optchar = parse_long_options(nargv, options, long_options, idx, short_too); if (optchar != -1) { place = EMSG; return (optchar); } } if ((optchar = (int)*place++) == (int)':' || (optchar == (int)'-' && *place != '\0') || (oli = strchr(options, optchar)) == NULL) { /* * If the user specified "-" and '-' isn't listed in * options, return -1 (non-option) as per POSIX. * Otherwise, it is an unknown option character (or ':'). */ if (optchar == (int)'-' && *place == '\0') return (-1); if (!*place) ++optind; if (PRINT_ERROR) warnx(illoptchar, optchar); optopt = optchar; return (BADCH); } if (long_options != NULL && optchar == 'W' && oli[1] == ';') { /* -W long-option */ if (*place) /* no space */ /* NOTHING */; else if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; return (BADARG); } else /* white space */ place = nargv[optind]; optchar = parse_long_options(nargv, options, long_options, idx, 0); place = EMSG; return (optchar); } if (*++oli != ':') { /* doesn't take argument */ if (!*place) ++optind; } else { /* takes (optional) argument */ optarg = NULL; if (*place) /* no white space */ optarg = place; else if (oli[1] != ':') { /* arg not optional */ if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; return (BADARG); } else optarg = nargv[optind]; } place = EMSG; ++optind; } /* dump back option letter */ return (optchar); } /* * getopt -- * Parse argc/argv argument vector. * * [eventually this will replace the BSD getopt] */ int getopt(int nargc, char * const *nargv, const char *options) { /* * We don't pass FLAG_PERMUTE to getopt_internal() since * the BSD getopt(3) (unlike GNU) has never done this. * * Furthermore, since many privileged programs call getopt() * before dropping privileges it makes sense to keep things * as simple (and bug-free) as possible. */ return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); } #if 0 /* * getopt_long -- * Parse argc/argv argument vector. */ int getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE)); } /* * getopt_long_only -- * Parse argc/argv argument vector. */ int getopt_long_only(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE|FLAG_LONGONLY)); } #endif #endif /* !defined(HAVE_GETOPT) || !defined(HAVE_OPTRESET) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/getrrsetbyname-ldns.c100644 001750 001750 0000000003614775415623 0022224xustar0030 atime=1744182234.657056094 openssh-10.0p1/openbsd-compat/getrrsetbyname-ldns.c010064400017500001750000000174761477541562300206260ustar00djmdjm/* $OpenBSD: getrrsetbyname.c,v 1.10 2005/03/30 02:58:28 tedu Exp $ */ /* * Copyright (c) 2007 Simon Vallet / Genoscope * * 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. */ #include "includes.h" #if !defined (HAVE_GETRRSETBYNAME) && defined (HAVE_LDNS) #include #include #include #include "getrrsetbyname.h" #include "log.h" #include "xmalloc.h" #define malloc(x) (xmalloc(x)) #define calloc(x, y) (xcalloc((x),(y))) int getrrsetbyname(const char *hostname, unsigned int rdclass, unsigned int rdtype, unsigned int flags, struct rrsetinfo **res) { int result; unsigned int i, j, index_ans, index_sig; struct rrsetinfo *rrset = NULL; struct rdatainfo *rdata; size_t len; ldns_resolver *ldns_res = NULL; ldns_rdf *domain = NULL; ldns_pkt *pkt = NULL; ldns_rr_list *rrsigs = NULL, *rrdata = NULL; ldns_status err; ldns_rr *rr; /* 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 from resolv.conf */ domain = ldns_dname_new_frm_str(hostname); if ((err = ldns_resolver_new_frm_file(&ldns_res, NULL)) != \ LDNS_STATUS_OK) { result = ERRSET_FAIL; goto fail; } #ifdef LDNS_DEBUG ldns_resolver_set_debug(ldns_res, true); #endif /* LDNS_DEBUG */ ldns_resolver_set_dnssec(ldns_res, true); /* Use DNSSEC */ /* make query */ pkt = ldns_resolver_query(ldns_res, domain, rdtype, rdclass, LDNS_RD); /*** TODO: finer errcodes -- see original **/ if (!pkt || ldns_pkt_ancount(pkt) < 1) { result = ERRSET_FAIL; goto fail; } /* initialize rrset */ rrset = calloc(1, sizeof(struct rrsetinfo)); if (rrset == NULL) { result = ERRSET_NOMEMORY; goto fail; } rrdata = ldns_pkt_rr_list_by_type(pkt, rdtype, LDNS_SECTION_ANSWER); rrset->rri_nrdatas = ldns_rr_list_rr_count(rrdata); if (!rrset->rri_nrdatas) { result = ERRSET_NODATA; goto fail; } /* copy name from answer section */ len = ldns_rdf_size(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))); if ((rrset->rri_name = malloc(len)) == NULL) { result = ERRSET_NOMEMORY; goto fail; } memcpy(rrset->rri_name, ldns_rdf_data(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))), len); rrset->rri_rdclass = ldns_rr_get_class(ldns_rr_list_rr(rrdata, 0)); rrset->rri_rdtype = ldns_rr_get_type(ldns_rr_list_rr(rrdata, 0)); rrset->rri_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrdata, 0)); debug2("ldns: got %u answers from DNS", rrset->rri_nrdatas); /* Check for authenticated data */ if (ldns_pkt_ad(pkt)) { rrset->rri_flags |= RRSET_VALIDATED; } else { /* AD is not set, try autonomous validation */ ldns_rr_list * trusted_keys = ldns_rr_list_new(); debug2("ldns: trying to validate RRset"); /* Get eventual sigs */ rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER); rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs); debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS", rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG); if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs, trusted_keys)) == LDNS_STATUS_OK) { rrset->rri_flags |= RRSET_VALIDATED; debug2("ldns: RRset is signed with a valid key"); } else { debug2("ldns: RRset validation failed: %s", ldns_get_errorstr_by_id(err)); } ldns_rr_list_deep_free(trusted_keys); } /* 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 (i=0, index_ans=0, index_sig=0; i< pkt->_header->_ancount; i++) { rdata = NULL; rr = ldns_rr_list_rr(ldns_pkt_answer(pkt), i); if (ldns_rr_get_class(rr) == rrset->rri_rdclass && ldns_rr_get_type(rr) == rrset->rri_rdtype) { rdata = &rrset->rri_rdatas[index_ans++]; } if (rr->_rr_class == rrset->rri_rdclass && rr->_rr_type == LDNS_RR_TYPE_RRSIG && rrset->rri_sigs) { rdata = &rrset->rri_sigs[index_sig++]; } if (rdata) { size_t rdata_offset = 0; rdata->rdi_length = 0; for (j=0; j< rr->_rd_count; j++) { rdata->rdi_length += ldns_rdf_size(ldns_rr_rdf(rr, j)); } rdata->rdi_data = malloc(rdata->rdi_length); if (rdata->rdi_data == NULL) { result = ERRSET_NOMEMORY; goto fail; } /* Re-create the raw DNS RDATA */ for (j=0; j< rr->_rd_count; j++) { len = ldns_rdf_size(ldns_rr_rdf(rr, j)); memcpy(rdata->rdi_data + rdata_offset, ldns_rdf_data(ldns_rr_rdf(rr, j)), len); rdata_offset += len; } } } *res = rrset; result = ERRSET_SUCCESS; fail: /* freerrset(rrset); */ ldns_rdf_deep_free(domain); ldns_pkt_free(pkt); ldns_rr_list_deep_free(rrsigs); ldns_rr_list_deep_free(rrdata); ldns_resolver_deep_free(ldns_res); 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); } #endif /* !defined (HAVE_GETRRSETBYNAME) && defined (HAVE_LDNS) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/getrrsetbyname.c100644 001750 001750 0000000003614775415623 0021266xustar0030 atime=1744182234.658032672 openssh-10.0p1/openbsd-compat/getrrsetbyname.c010064400017500001750000000345021477541562300176550ustar00djmdjm/* $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 #include #include #include #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) { \ 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) { \ 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 /* * If the system doesn't have _getshort/_getlong or that are not exactly what * we need then use local replacements, avoiding name collisions. */ #if !defined(HAVE__GETSHORT) || !defined(HAVE__GETLONG) || \ !defined(HAVE_DECL__GETSHORT) || HAVE_DECL__GETSHORT == 0 || \ !defined(HAVE_DECL__GETLONG) || HAVE_DECL__GETLONG == 0 # ifdef _getshort # undef _getshort # endif # ifdef _getlong # undef _getlong # endif # define _getshort(x) (_ssh_compat_getshort(x)) # define _getlong(x) (_ssh_compat_getlong(x)) /* * Routines to insert/extract short/long's. */ static u_int16_t _getshort(const u_char *msgp) { u_int16_t u; GETSHORT(u, msgp); return (u); } static u_int32_t _getlong(const u_char *msgp) { u_int32_t u; GETLONG(u, msgp); return (u); } #endif /* missing _getshort/_getlong */ /* ************** */ #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; if (rr->size != 0) { 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; if (size < HFIXEDSZ) return (NULL); /* 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]; #define NEED(need) \ do { \ if (*cp + need > answer + size) \ goto fail; \ } while (0) for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { if (*cp >= answer + size) { fail: free_dns_query(head); return (NULL); } /* allocate and initialize struct */ curr = calloc(1, sizeof(struct dns_query)); if (curr == NULL) goto fail; 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); } NEED(length); *cp += length; /* type */ NEED(INT16SZ); curr->type = _getshort(*cp); *cp += INT16SZ; /* class */ NEED(INT16SZ); curr->class = _getshort(*cp); *cp += INT16SZ; } #undef NEED 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]; #define NEED(need) \ do { \ if (*cp + need > answer + size) \ goto fail; \ } while (0) for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { if (*cp >= answer + size) { fail: free_dns_rr(head); return (NULL); } /* allocate and initialize struct */ curr = calloc(1, sizeof(struct dns_rr)); if (curr == NULL) goto fail; 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); } NEED(length); *cp += length; /* type */ NEED(INT16SZ); curr->type = _getshort(*cp); *cp += INT16SZ; /* class */ NEED(INT16SZ); curr->class = _getshort(*cp); *cp += INT16SZ; /* ttl */ NEED(INT32SZ); curr->ttl = _getlong(*cp); *cp += INT32SZ; /* rdata size */ NEED(INT16SZ); curr->size = _getshort(*cp); *cp += INT16SZ; /* rdata itself */ NEED(curr->size); if (curr->size != 0) { if ((curr->rdata = malloc(curr->size)) == NULL) { free_dns_rr(head); return (NULL); } memcpy(curr->rdata, *cp, curr->size); } *cp += curr->size; } #undef NEED 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) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/getrrsetbyname.h100644 001750 001750 0000000003614775415623 0021273xustar0030 atime=1744182234.658032672 openssh-10.0p1/openbsd-compat/getrrsetbyname.h010064400017500001750000000071741477541562300176670ustar00djmdjm/* OPENBSD BASED ON : include/netdb.h */ /* $OpenBSD: getrrsetbyname.c,v 1.4 2001/08/16 18:16:43 ho 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. */ #ifndef _GETRRSETBYNAME_H #define _GETRRSETBYNAME_H #include "includes.h" #ifndef HAVE_GETRRSETBYNAME #include #include #include #include #include #ifndef HFIXEDSZ #define HFIXEDSZ 12 #endif #ifndef T_RRSIG #define T_RRSIG 46 #endif /* * Flags for getrrsetbyname() */ #ifndef RRSET_VALIDATED # define RRSET_VALIDATED 1 #endif /* * Return codes for getrrsetbyname() */ #ifndef ERRSET_SUCCESS # define ERRSET_SUCCESS 0 # define ERRSET_NOMEMORY 1 # define ERRSET_FAIL 2 # define ERRSET_INVAL 3 # define ERRSET_NONAME 4 # define ERRSET_NODATA 5 #endif struct rdatainfo { unsigned int rdi_length; /* length of data */ unsigned char *rdi_data; /* record data */ }; struct rrsetinfo { unsigned int rri_flags; /* RRSET_VALIDATED ... */ unsigned int rri_rdclass; /* class number */ unsigned int rri_rdtype; /* RR type number */ unsigned int rri_ttl; /* time to live */ unsigned int rri_nrdatas; /* size of rdatas array */ unsigned int rri_nsigs; /* size of sigs array */ char *rri_name; /* canonical name */ struct rdatainfo *rri_rdatas; /* individual records */ struct rdatainfo *rri_sigs; /* individual signatures */ }; int getrrsetbyname(const char *, unsigned int, unsigned int, unsigned int, struct rrsetinfo **); void freerrset(struct rrsetinfo *); #endif /* !defined(HAVE_GETRRSETBYNAME) */ #endif /* _GETRRSETBYNAME_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/glob.h100644 001750 001750 0000000003514775415623 0017162xustar0029 atime=1744182234.65900978 openssh-10.0p1/openbsd-compat/glob.h010064400017500001750000000111141477541562300155440ustar00djmdjm/* $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 $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Guido van Rossum. * * 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. * * @(#)glob.h 8.1 (Berkeley) 6/2/93 */ /* OPENBSD ORIGINAL: include/glob.h */ #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) #ifndef _COMPAT_GLOB_H_ #define _COMPAT_GLOB_H_ #include #include # define glob_t _ssh_compat_glob_t # define glob(a, b, c, d) _ssh__compat_glob(a, b, c, d) # define globfree(a) _ssh__compat_globfree(a) struct stat; typedef struct { 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 */ /* Copy of errfunc parameter to glob. */ int (*gl_errfunc)(const char *, int); /* * Alternate filesystem access methods for glob; replacement * versions of closedir(3), readdir(3), opendir(3), stat(2) * and lstat(2). */ void (*gl_closedir)(void *); struct dirent *(*gl_readdir)(void *); void *(*gl_opendir)(const char *); int (*gl_lstat)(const char *, struct stat *); int (*gl_stat)(const char *, struct stat *); } glob_t; #define GLOB_APPEND 0x0001 /* Append to output from previous call. */ #define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ #define GLOB_ERR 0x0004 /* Return on error. */ #define GLOB_MARK 0x0008 /* Append / to matching directories. */ #define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ #define GLOB_NOSORT 0x0020 /* Don't sort. */ #define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ #define GLOB_NOSPACE (-1) /* Malloc call failed. */ #define GLOB_ABORTED (-2) /* Unignored error. */ #define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ #define GLOB_NOSYS (-4) /* Function not supported. */ #define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ #define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ #define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ #define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ #define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */ #define GLOB_KEEPSTAT 0x4000 /* Retain stat data for paths in gl_statv. */ #define GLOB_ABEND GLOB_ABORTED /* backward compatibility */ int glob(const char *, int, int (*)(const char *, int), glob_t *); void globfree(glob_t *); #endif /* !_GLOB_H_ */ #endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOH_HAS_GL_STATV) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/inet_aton.c100644 001750 001750 0000000003514775415623 0020212xustar0029 atime=1744182234.65900978 openssh-10.0p1/openbsd-compat/inet_aton.c010064400017500001750000000123211477541562300165750ustar00djmdjm/* $OpenBSD: inet_addr.c,v 1.9 2005/08/06 20:30:03 espie Exp $ */ /* * 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: * 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. * - * 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 * CORPORATION 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. * - * --Copyright-- */ /* OPENBSD ORIGINAL: lib/libc/net/inet_addr.c */ #include "includes.h" #if !defined(HAVE_INET_ATON) #include #include #include #include #if 0 /* * Ascii internet address interpretation routine. * The value returned is in network order. */ in_addr_t inet_addr(const char *cp) { struct in_addr val; if (inet_aton(cp, &val)) return (val.s_addr); return (INADDR_NONE); } #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. * This replaces inet_addr, the return value from which * cannot distinguish between failure and a local broadcast address. */ int inet_aton(const char *cp, struct in_addr *addr) { u_int32_t val; int base, n; char c; u_int parts[4]; u_int *pp = parts; c = *cp; for (;;) { /* * Collect number up to ``.''. * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ if (!isdigit(c)) return (0); val = 0; base = 10; if (c == '0') { c = *++cp; if (c == 'x' || c == 'X') base = 16, c = *++cp; else base = 8; } for (;;) { if (isascii(c) && isdigit(c)) { val = (val * base) + (c - '0'); c = *++cp; } else if (base == 16 && isascii(c) && isxdigit(c)) { val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A')); c = *++cp; } else break; } if (c == '.') { /* * Internet format: * a.b.c.d * a.b.c (with c treated as 16 bits) * a.b (with b treated as 24 bits) */ if (pp >= parts + 3) return (0); *pp++ = val; c = *++cp; } else break; } /* * Check for trailing characters. */ if (c != '\0' && (!isascii(c) || !isspace(c))) return (0); /* * Concoct the address according to * the number of parts specified. */ n = pp - parts + 1; switch (n) { case 0: return (0); /* initial nondigit */ case 1: /* a -- 32 bits */ break; case 2: /* a.b -- 8.24 bits */ if ((val > 0xffffff) || (parts[0] > 0xff)) return (0); val |= parts[0] << 24; break; case 3: /* a.b.c -- 8.8.16 bits */ if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) return (0); val |= (parts[0] << 24) | (parts[1] << 16); break; case 4: /* a.b.c.d -- 8.8.8.8 bits */ if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) return (0); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); break; } if (addr) addr->s_addr = htonl(val); return (1); } #endif /* !defined(HAVE_INET_ATON) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/inet_ntoa.c100644 001750 001750 0000000003514775415623 0020212xustar0029 atime=1744182234.65900978 openssh-10.0p1/openbsd-compat/inet_ntoa.c010064400017500001750000000043271477541562300166040ustar00djmdjm/* $OpenBSD: inet_ntoa.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */ /* * Copyright (c) 1983, 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. */ /* OPENBSD ORIGINAL: lib/libc/net/inet_ntoa.c */ #include "includes.h" #if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) /* * Convert network-format internet address * to base 256 d.d.d.d representation. */ #include #include #include #include char * inet_ntoa(struct in_addr in) { static char b[18]; char *p; p = (char *)∈ #define UC(b) (((int)b)&0xff) (void)snprintf(b, sizeof(b), "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); return (b); } #endif /* defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/inet_ntop.c100644 001750 001750 0000000003614775415623 0020232xustar0030 atime=1744182234.659985415 openssh-10.0p1/openbsd-compat/inet_ntop.c010064400017500001750000000126331477541562300166220ustar00djmdjm/* $OpenBSD: inet_ntop.c,v 1.8 2008/12/09 19:38:38 otto Exp $ */ /* Copyright (c) 1996 by 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/inet_ntop.c */ #include "includes.h" #ifndef HAVE_INET_NTOP #include #include #include #include #include #include #include #include #ifndef IN6ADDRSZ #define IN6ADDRSZ 16 /* IPv6 T_AAAA */ #endif #ifndef INT16SZ #define INT16SZ 2 /* for systems without 16-bit ints */ #endif /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ static const char *inet_ntop4(const u_char *src, char *dst, size_t size); static const char *inet_ntop6(const u_char *src, char *dst, size_t size); /* char * * inet_ntop(af, src, dst, size) * convert a network format address to presentation format. * return: * pointer to presentation format address (`dst'), or NULL (see errno). * author: * Paul Vixie, 1996. */ const char * inet_ntop(int af, const void *src, char *dst, socklen_t size) { switch (af) { case AF_INET: return (inet_ntop4(src, dst, (size_t)size)); case AF_INET6: return (inet_ntop6(src, dst, (size_t)size)); default: errno = EAFNOSUPPORT; return (NULL); } /* NOTREACHED */ } /* const char * * inet_ntop4(src, dst, size) * format an IPv4 address, more or less like inet_ntoa() * return: * `dst' (as a const) * notes: * (1) uses no statics * (2) takes a u_char* not an in_addr as input * author: * Paul Vixie, 1996. */ static const char * inet_ntop4(const u_char *src, char *dst, size_t size) { static const char fmt[] = "%u.%u.%u.%u"; char tmp[sizeof "255.255.255.255"]; int l; l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); if (l <= 0 || l >= size) { errno = ENOSPC; return (NULL); } strlcpy(dst, tmp, size); return (dst); } /* const char * * inet_ntop6(src, dst, size) * convert IPv6 binary address into presentation (printable) format * author: * Paul Vixie, 1996. */ static const char * inet_ntop6(const u_char *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; char *tp, *ep; struct { int base, len; } best, cur; u_int words[IN6ADDRSZ / INT16SZ]; int i; int advance; /* * Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset(words, '\0', sizeof words); for (i = 0; i < IN6ADDRSZ; i++) words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); best.base = -1; cur.base = -1; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else { if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } } if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; } if (best.base != -1 && best.len < 2) best.base = -1; /* * Format the result. */ tp = tmp; ep = tmp + sizeof(tmp); for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) return (NULL); tp += strlen(tp); break; } advance = snprintf(tp, ep - tp, "%x", words[i]); if (advance <= 0 || advance >= ep - tp) return (NULL); tp += advance; } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } if (tp + 1 >= ep) return (NULL); *tp++ = '\0'; /* * Check for overflow, copy, and we're done. */ if ((size_t)(tp - tmp) > size) { errno = ENOSPC; return (NULL); } strlcpy(dst, tmp, size); return (dst); } #endif /* !HAVE_INET_NTOP */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/kludge-fd_set.c100644 001750 001750 0000000003614775415623 0020750xustar0030 atime=1744182234.659985415 openssh-10.0p1/openbsd-compat/kludge-fd_set.c010064400017500001750000000015621477541562300173370ustar00djmdjm/* Placed in the public domain. */ /* * _FORTIFY_SOURCE includes a misguided check for FD_SET(n)/FD_ISSET(b) * where n > FD_SETSIZE. This breaks OpenSSH and other programs that * explicitly allocate fd_sets. To avoid this, we wrap FD_SET in a * function compiled without _FORTIFY_SOURCE. */ #include "config.h" #if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE) # include # if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ) # if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) # undef _FORTIFY_SOURCE # undef __USE_FORTIFY_LEVEL # include void kludge_FD_SET(int n, fd_set *set) { FD_SET(n, set); } int kludge_FD_ISSET(int n, fd_set *set) { return FD_ISSET(n, set); } # endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */ # endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */ #endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/libressl-api-compat.c100644 001750 001750 0000000003614775415623 0022102xustar0030 atime=1744182234.659985415 openssh-10.0p1/openbsd-compat/libressl-api-compat.c010064400017500001750000000045621477541562300204740ustar00djmdjm/* * Copyright (c) 2018 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" #ifdef WITH_OPENSSL #include #include #include #include #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 */ #endif /* WITH_OPENSSL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/md5.c100644 001750 001750 0000000003614775415623 0016720xustar0030 atime=1744182234.659985415 openssh-10.0p1/openbsd-compat/md5.c010064400017500001750000000175161477541562300153150ustar00djmdjm/* $OpenBSD: md5.c,v 1.9 2014/01/08 06:14:57 tedu Exp $ */ /* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #include "includes.h" #ifndef WITH_OPENSSL #include #include #include "md5.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) static u_int8_t PADDING[MD5_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 }; /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(MD5_CTX *ctx) { ctx->count = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89; ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len) { size_t have, need; /* Check how many bytes we already have and how many more we need. */ have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); need = MD5_BLOCK_LENGTH - have; /* Update bitcount */ ctx->count += (u_int64_t)len << 3; if (len >= need) { if (have != 0) { memcpy(ctx->buffer + have, input, need); MD5Transform(ctx->state, ctx->buffer); input += need; len -= need; have = 0; } /* Process data in MD5_BLOCK_LENGTH-byte chunks. */ while (len >= MD5_BLOCK_LENGTH) { MD5Transform(ctx->state, input); input += MD5_BLOCK_LENGTH; len -= MD5_BLOCK_LENGTH; } } /* Handle any remaining bytes of data. */ if (len != 0) memcpy(ctx->buffer + have, input, len); } /* * Pad pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Pad(MD5_CTX *ctx) { u_int8_t count[8]; size_t padlen; /* Convert count to 8 bytes in little endian order. */ PUT_64BIT_LE(count, ctx->count); /* Pad out to 56 mod 64. */ padlen = MD5_BLOCK_LENGTH - ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); if (padlen < 1 + 8) padlen += MD5_BLOCK_LENGTH; MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ MD5Update(ctx, count, 8); } /* * Final wrapup--call MD5Pad, fill in digest and zero out ctx. */ void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) { int i; MD5Pad(ctx); for (i = 0; i < 4; i++) PUT_32BIT_LE(digest + i * 4, ctx->state[i]); memset(ctx, 0, sizeof(*ctx)); } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ void MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH]) { u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4]; #if BYTE_ORDER == LITTLE_ENDIAN memcpy(in, block, sizeof(in)); #else for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) { in[a] = (u_int32_t)( (u_int32_t)(block[a * 4 + 0]) | (u_int32_t)(block[a * 4 + 1]) << 8 | (u_int32_t)(block[a * 4 + 2]) << 16 | (u_int32_t)(block[a * 4 + 3]) << 24); } #endif a = state[0]; b = state[1]; c = state[2]; d = state[3]; MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21); state[0] += a; state[1] += b; state[2] += c; state[3] += d; } #endif /* !WITH_OPENSSL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/md5.h100644 001750 001750 0000000003614775415623 0016725xustar0030 atime=1744182234.659985415 openssh-10.0p1/openbsd-compat/md5.h010064400017500001750000000035431477541562300153150ustar00djmdjm/* $OpenBSD: md5.h,v 1.17 2012/12/05 23:19:57 deraadt Exp $ */ /* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. */ #ifndef _MD5_H_ #define _MD5_H_ #ifndef WITH_OPENSSL #define MD5_BLOCK_LENGTH 64 #define MD5_DIGEST_LENGTH 16 #define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) typedef struct MD5Context { u_int32_t state[4]; /* state */ u_int64_t count; /* number of bits, mod 2^64 */ u_int8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */ } MD5_CTX; void MD5Init(MD5_CTX *); void MD5Update(MD5_CTX *, const u_int8_t *, size_t) __attribute__((__bounded__(__string__,2,3))); void MD5Pad(MD5_CTX *); void MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *) __attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH))); void MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH]) __attribute__((__bounded__(__minbytes__,1,4))) __attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH))); char *MD5End(MD5_CTX *, char *) __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); char *MD5File(const char *, char *) __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); char *MD5FileChunk(const char *, char *, off_t, off_t) __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); char *MD5Data(const u_int8_t *, size_t, char *) __attribute__((__bounded__(__string__,1,2))) __attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH))); #endif /* !WITH_OPENSSL */ #endif /* _MD5_H_ */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/memmem.c100644 001750 001750 0000000003614775415623 0017510xustar0030 atime=1744182234.659985415 openssh-10.0p1/openbsd-compat/memmem.c010064400017500001750000000116261477541562300161010ustar00djmdjm/* $OpenBSD: memmem.c,v 1.5 2020/04/16 12:39:28 claudio Exp $ */ /* * Copyright (c) 2005-2020 Rich Felker, et al. * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* OPENBSD ORIGINAL: lib/libc/string/memmem.c */ #include "includes.h" #ifndef HAVE_MEMMEM #include #ifdef HAVE_STDINT_H #include #endif static char * twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) { uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++) if (hw == nw) return (char *)h-2; return hw == nw ? (char *)h-2 : 0; } static char * threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) { uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8) if (hw == nw) return (char *)h-3; return hw == nw ? (char *)h-3 : 0; } static char * fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) { uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++) if (hw == nw) return (char *)h-4; return hw == nw ? (char *)h-4 : 0; } #if 0 /* In -portable, defines.h ensures that these are already defined. */ #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #endif #define BITOP(a,b,op) \ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) /* * Maxime Crochemore and Dominique Perrin, Two-way string-matching, * Journal of the ACM, 38(3):651-675, July 1991. */ static char * twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l) { size_t i, ip, jp, k, p, ms, p0, mem, mem0; size_t byteset[32 / sizeof(size_t)] = { 0 }; size_t shift[256]; /* Computing length of needle and fill shift table */ for (i=0; i n[jp+k]) { jp += k; k = 1; p = jp - ip; } else { ip = jp++; k = p = 1; } } ms = ip; p0 = p; /* And with the opposite comparison */ ip = -1; jp = 0; k = p = 1; while (jp+k ms+1) ms = ip; else p = p0; /* Periodic needle? */ if (memcmp(n, n+p, ms+1)) { mem0 = 0; p = MAX(ms, l-ms-1) + 1; } else mem0 = l-p; mem = 0; /* Search loop */ for (;;) { /* If remainder of haystack is shorter than needle, done */ if (z-h < l) return 0; /* Check last byte first; advance by shift on mismatch */ if (BITOP(byteset, h[l-1], &)) { k = l-shift[h[l-1]]; if (k) { if (k < mem) k = mem; h += k; mem = 0; continue; } } else { h += l; mem = 0; continue; } /* Compare right half */ for (k=MAX(ms+1,mem); kmem && n[k-1] == h[k-1]; k--); if (k <= mem) return (char *)h; h += p; mem = mem0; } } void * memmem(const void *h0, size_t k, const void *n0, size_t l) { const unsigned char *h = h0, *n = n0; /* Return immediately on empty needle */ if (!l) return (void *)h; /* Return immediately when needle is longer than haystack */ if (k #include #include #include #include #include #include #include #include #include #ifdef mkstemp #undef mkstemp #endif int mkstemp(char *); /* * From glibc man page: 'In glibc versions 2.06 and earlier, the file is * created with permissions 0666, that is, read and write for all users.' * Provide a wrapper to make sure the mask is reasonable (POSIX requires * mode 0600, so mask off any other bits). */ int _ssh_mkstemp(char *template) { mode_t mask; int ret; mask = umask(0177); ret = mkstemp(template); (void)umask(mask); return ret; } #if !defined(HAVE_MKDTEMP) #define MKTEMP_NAME 0 #define MKTEMP_FILE 1 #define MKTEMP_DIR 2 #define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" #define NUM_CHARS (sizeof(TEMPCHARS) - 1) static int mktemp_internal(char *path, int slen, int mode) { char *start, *cp, *ep; const char *tempchars = TEMPCHARS; unsigned int r, tries; struct stat sb; size_t len; int fd; len = strlen(path); if (len == 0 || slen < 0 || (size_t)slen >= len) { errno = EINVAL; return(-1); } ep = path + len - slen; tries = 1; for (start = ep; start > path && start[-1] == 'X'; start--) { if (tries < INT_MAX / NUM_CHARS) tries *= NUM_CHARS; } tries *= 2; do { for (cp = start; cp != ep; cp++) { r = arc4random_uniform(NUM_CHARS); *cp = tempchars[r]; } switch (mode) { case MKTEMP_NAME: if (lstat(path, &sb) != 0) return(errno == ENOENT ? 0 : -1); break; case MKTEMP_FILE: fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); if (fd != -1 || errno != EEXIST) return(fd); break; case MKTEMP_DIR: if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0) return(0); if (errno != EEXIST) return(-1); break; } } while (--tries); errno = EEXIST; return(-1); } #if 0 char *_mktemp(char *); char * _mktemp(char *path) { if (mktemp_internal(path, 0, MKTEMP_NAME) == -1) return(NULL); return(path); } __warn_references(mktemp, "warning: mktemp() possibly used unsafely; consider using mkstemp()"); char * mktemp(char *path) { return(_mktemp(path)); } #endif int mkstemp(char *path) { return(mktemp_internal(path, 0, MKTEMP_FILE)); } int mkstemps(char *path, int slen) { return(mktemp_internal(path, slen, MKTEMP_FILE)); } char * mkdtemp(char *path) { int error; error = mktemp_internal(path, 0, MKTEMP_DIR); return(error ? NULL : path); } #endif /* !defined(HAVE_MKDTEMP) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/openbsd-compat.h100644 001750 001750 0000000003614775415623 0021153xustar0030 atime=1744182234.660960459 openssh-10.0p1/openbsd-compat/openbsd-compat.h010064400017500001750000000224141477541562300175410ustar00djmdjm/* * Copyright (c) 1999-2003 Damien Miller. All rights reserved. * Copyright (c) 2003 Ben Lindstrom. All rights reserved. * Copyright (c) 2002 Tim Rice. 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 _OPENBSD_COMPAT_H #define _OPENBSD_COMPAT_H #include "includes.h" #include #include #include #include /* for wchar_t */ /* OpenBSD function replacements */ #include "base64.h" #include "sigact.h" #include "readpassphrase.h" #include "vis.h" #include "getrrsetbyname.h" #include "sha1.h" #include "sha2.h" #include "md5.h" #include "blf.h" #include "fnmatch.h" #ifndef __THROW # if defined __cplusplus # define __THROW throw() # else # define __THROW # endif #endif #if defined(HAVE_LOGIN_CAP) && !defined(HAVE_LOGIN_GETPWCLASS) # include # define login_getpwclass(pw) login_getclass(pw->pw_class) #endif #ifndef HAVE_BASENAME char *basename(const char *path); #endif #ifndef HAVE_BINDRESVPORT_SA int bindresvport_sa(int sd, struct sockaddr *sa); #endif #ifndef HAVE_CLOSEFROM void closefrom(int); #endif #if defined(HAVE_DECL_FTRUNCATE) && HAVE_DECL_FTRUNCATE == 0 int ftruncate(int filedes, off_t length); #endif #ifndef HAVE_GETLINE #include 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 #ifndef HAVE_KILLPG int killpg(pid_t, int); #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 #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 size_t strlcpy(char *dst, const char *src, size_t siz); #endif #ifndef HAVE_STRLCAT size_t strlcat(char *dst, const char *src, size_t siz); #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); #endif #ifndef HAVE_STRMODE void strmode(int mode, char *p); #endif #ifndef HAVE_STRPTIME #include char *strptime(const char *buf, const char *fmt, struct tm *tm); #endif #if !defined(HAVE_MKDTEMP) int mkstemps(char *path, int slen); int mkstemp(char *path); char *mkdtemp(char *path); #endif #define mkstemp(x) _ssh_mkstemp(x) int _ssh_mkstemp(char *); #ifndef HAVE_DAEMON int daemon(int nochdir, int noclose); #endif #ifndef HAVE_DIRNAME char *dirname(const char *path); #endif #ifndef HAVE_FMT_SCALED #define FMT_SCALED_STRSIZE 7 int fmt_scaled(long long number, char *result); #endif #ifndef HAVE_SCAN_SCALED int scan_scaled(char *, long long *); #endif #if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) char *inet_ntoa(struct in_addr in); #endif #ifndef HAVE_INET_NTOP const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); #endif #ifndef HAVE_INET_ATON int inet_aton(const char *cp, struct in_addr *addr); #endif #ifndef HAVE_STRSEP char *strsep(char **stringp, const char *delim); #endif #ifndef HAVE_SETPROCTITLE void setproctitle(const char *fmt, ...); void compat_init_setproctitle(int argc, char *argv[]); #endif #ifndef HAVE_GETGROUPLIST int getgrouplist(const char *, gid_t, gid_t *, int *); #endif #if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) int BSDgetopt(int argc, char * const *argv, const char *opts) __THROW; #include "openbsd-compat/getopt.h" #endif #if ((defined(HAVE_DECL_READV) && HAVE_DECL_READV == 0) || \ (defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0)) # include # include # 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-signal.h" #include "bsd-misc.h" #include "bsd-setres_id.h" #include "bsd-statvfs.h" #include "bsd-waitpid.h" #include "bsd-poll.h" #if defined(HAVE_DECL_GETPEEREID) && HAVE_DECL_GETPEEREID == 0 int getpeereid(int , uid_t *, gid_t *); #endif #ifndef HAVE_ARC4RANDOM uint32_t arc4random(void); #endif /* !HAVE_ARC4RANDOM */ #ifndef HAVE_ARC4RANDOM_BUF void arc4random_buf(void *, size_t); #endif #ifndef HAVE_ARC4RANDOM_STIR # define arc4random_stir() #endif #ifndef HAVE_ARC4RANDOM_UNIFORM uint32_t arc4random_uniform(uint32_t); #endif #ifndef HAVE_ASPRINTF int asprintf(char **, const char *, ...); #endif #ifndef HAVE_OPENPTY # include /* for struct winsize */ int openpty(int *, int *, char *, struct termios *, struct winsize *); #endif /* HAVE_OPENPTY */ #ifndef HAVE_SNPRINTF int snprintf(char *, size_t, SNPRINTF_CONST char *, ...); #endif #ifndef HAVE_STRTOLL long long strtoll(const char *, char **, int); #endif #ifndef HAVE_STRTOUL unsigned long strtoul(const char *, char **, int); #endif #ifndef HAVE_STRTOULL unsigned long long strtoull(const char *, char **, int); #endif #ifndef HAVE_STRTONUM long long strtonum(const char *, long long, long long, const char **); #endif /* multibyte character support */ #ifndef HAVE_MBLEN # 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 #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 #ifndef HAVE_VSNPRINTF int vsnprintf(char *, size_t, const char *, va_list); #endif #ifndef HAVE_USER_FROM_UID char *user_from_uid(uid_t, int); #endif #ifndef HAVE_GROUP_FROM_GID char *group_from_gid(gid_t, int); #endif #ifndef HAVE_TIMINGSAFE_BCMP int timingsafe_bcmp(const void *, const void *, size_t); #endif #ifndef HAVE_BCRYPT_PBKDF int bcrypt_pbkdf(const char *, size_t, const uint8_t *, size_t, uint8_t *, size_t, unsigned int); #endif #ifndef HAVE_EXPLICIT_BZERO void explicit_bzero(void *p, size_t n); #endif #ifndef HAVE_FREEZERO void freezero(void *, size_t); #endif #ifndef HAVE_LOCALTIME_R struct tm *localtime_r(const time_t *, struct tm *); #endif #ifndef HAVE_TIMEGM #include time_t timegm(struct tm *); #endif char *xcrypt(const char *password, const char *salt); char *shadow_pw(struct passwd *pw); /* rfc2553 socket API replacements */ #include "fake-rfc2553.h" /* Routines for a single OS platform */ #include "bsd-cygwin_util.h" #include "port-aix.h" #include "port-irix.h" #include "port-linux.h" #include "port-solaris.h" #include "port-net.h" #include "port-uw.h" /* _FORTIFY_SOURCE breaks FD_ISSET(n)/FD_SET(n) for n > FD_SETSIZE. Avoid. */ #if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE) # include # if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ) # if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) # include /* Ensure include guard is defined */ # undef FD_SET # undef FD_ISSET # define FD_SET(n, set) kludge_FD_SET(n, set) # define FD_ISSET(n, set) kludge_FD_ISSET(n, set) void kludge_FD_SET(int, fd_set *); int kludge_FD_ISSET(int, fd_set *); # endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */ # endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */ #endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */ #endif /* _OPENBSD_COMPAT_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/openssl-compat.c100644 001750 001750 0000000003614775415623 0021177xustar0030 atime=1744182234.660960459 openssh-10.0p1/openbsd-compat/openssl-compat.c010064400017500001750000000067231477541562300175720ustar00djmdjm/* * Copyright (c) 2005 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 MIND, 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 SSH_DONT_OVERLOAD_OPENSSL_FUNCS #include "includes.h" #ifdef WITH_OPENSSL #include #include #ifdef USE_OPENSSL_ENGINE # include # include #endif #include "log.h" #include "openssl-compat.h" /* * OpenSSL version numbers: MNNFFPPS: major minor fix patch status * Versions >=3 require only major versions to match. * For versions <3, we accept compatible fix versions (so we allow 1.0.1 * to work with 1.0.0). Going backwards is only allowed within a patch series. * See https://www.openssl.org/policies/releasestrat.html */ int ssh_compatible_openssl(long headerver, long libver) { long mask, hfix, lfix; /* exact match is always OK */ if (headerver == libver) return 1; /* * For versions >= 3.0, only the major and status must match. */ if (headerver >= 0x3000000f) { mask = 0xf000000fL; /* major,status */ return (headerver & mask) == (libver & mask); } /* * For versions >= 1.0.0, but <3, major,minor,status must match and * library fix version must be equal to or newer than the header. */ mask = 0xfff0000fL; /* major,minor,status */ hfix = (headerver & 0x000ff000) >> 12; lfix = (libver & 0x000ff000) >> 12; if ( (headerver & mask) == (libver & mask) && lfix >= hfix) return 1; return 0; } 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 */ } #ifndef HAVE_EVP_DIGESTSIGN int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, const unsigned char *tbs, size_t tbslen) { if (sigret != NULL) { if (EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0) return 0; } return EVP_DigestSignFinal(ctx, sigret, siglen); } #endif #ifndef HAVE_EVP_DIGESTVERIFY int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen, const unsigned char *tbs, size_t tbslen) { if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) return -1; return EVP_DigestVerifyFinal(ctx, sigret, siglen); } #endif #endif /* WITH_OPENSSL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/openssl-compat.h100644 001750 001750 0000000003614775415623 0021204xustar0030 atime=1744182234.660960459 openssh-10.0p1/openbsd-compat/openssl-compat.h010064400017500001750000000054571477541562300176020ustar00djmdjm/* * Copyright (c) 2005 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 MIND, 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 _OPENSSL_COMPAT_H #define _OPENSSL_COMPAT_H #include "includes.h" #ifdef WITH_OPENSSL #include #include #include #include #include #ifdef OPENSSL_HAS_ECC #include #endif #include int ssh_compatible_openssl(long, long); void ssh_libcrypto_init(void); #if (OPENSSL_VERSION_NUMBER < 0x10100000L) # error OpenSSL 1.1.0 or greater is required #endif #ifdef LIBRESSL_VERSION_NUMBER # if LIBRESSL_VERSION_NUMBER < 0x3010000fL # error LibreSSL 3.1.0 or greater is required # endif #endif #ifndef OPENSSL_RSA_MAX_MODULUS_BITS # define OPENSSL_RSA_MAX_MODULUS_BITS 16384 #endif #ifndef OPENSSL_DSA_MAX_MODULUS_BITS # define OPENSSL_DSA_MAX_MODULUS_BITS 10000 #endif #ifdef LIBRESSL_VERSION_NUMBER # if LIBRESSL_VERSION_NUMBER < 0x3010000fL # define HAVE_BROKEN_CHACHA20 # endif #endif #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) /* * BoringSSL and AWS-LC (rightly) got rid of the BN_FLG_CONSTTIME flag, along with * the entire BN_set_flags() interface. * https://boringssl.googlesource.com/boringssl/+/0a211dfe9 */ # define BN_set_flags(a, b) #endif #ifndef HAVE_EVP_CIPHER_CTX_GET_IV # ifdef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV # define EVP_CIPHER_CTX_get_iv EVP_CIPHER_CTX_get_updated_iv # else /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */ int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len); # endif /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */ #endif /* HAVE_EVP_CIPHER_CTX_GET_IV */ #ifndef HAVE_EVP_CIPHER_CTX_SET_IV 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_EVP_DIGESTSIGN int EVP_DigestSign(EVP_MD_CTX *, unsigned char *, size_t *, const unsigned char *, size_t); #endif #ifndef HAVE_EVP_DIGESTVERIFY int EVP_DigestVerify(EVP_MD_CTX *, const unsigned char *, size_t, const unsigned char *, size_t); #endif #endif /* WITH_OPENSSL */ #endif /* _OPENSSL_COMPAT_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-aix.c100644 001750 001750 0000000003614775415623 0017776xustar0030 atime=1744182234.661937197 openssh-10.0p1/openbsd-compat/port-aix.c010064400017500001750000000313031477541562300163610ustar00djmdjm/* * * Copyright (c) 2001 Gert Doering. All rights reserved. * Copyright (c) 2003,2004,2005,2006 Darren Tucker. 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 _AIX #include "xmalloc.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" #include #if defined(HAVE_NETDB_H) # include #endif #include #include #include #include #include #ifdef WITH_AIXAUTHENTICATE # include # include # if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG) # include # endif # include #endif #include "port-aix.h" static char *lastlogin_msg = NULL; # ifdef HAVE_SETAUTHDB static char old_registry[REGISTRY_SIZE] = ""; # endif /* * AIX has a "usrinfo" area where logname and other stuff is stored - * a few applications actually use this and die if it's not set * * NOTE: TTY= should be set, but since no one uses it and it's hard to * acquire due to privsep code. We will just drop support. */ void aix_usrinfo(struct passwd *pw) { u_int i; size_t len; char *cp; len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name)); cp = xmalloc(len); i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0', pw->pw_name, '\0'); if (usrinfo(SETUINFO, cp, i) == -1) fatal("Couldn't set usrinfo: %s", strerror(errno)); debug3("AIX/UsrInfo: set len %d", i); free(cp); } # ifdef WITH_AIXAUTHENTICATE /* * Remove embedded newlines in string (if any). * Used before logging messages returned by AIX authentication functions * so the message is logged on one line. */ void aix_remove_embedded_newlines(char *p) { if (p == NULL) return; for (; *p; p++) { if (*p == '\n') *p = ' '; } /* Remove trailing whitespace */ if (*--p == ' ') *p = '\0'; } /* * Test specifically for the case where SYSTEM == NONE and AUTH1 contains * anything other than NONE or SYSTEM, which indicates that the admin has * configured the account for purely AUTH1-type authentication. * * Since authenticate() doesn't check AUTH1, and sshd can't sanely support * AUTH1 itself, in such a case authenticate() will allow access without * authentation, which is almost certainly not what the admin intends. * * (The native tools, eg login, will process the AUTH1 list in addition to * the SYSTEM list by using ckuserID(), however ckuserID() and AUTH1 methods * have been deprecated since AIX 4.2.x and would be very difficult for sshd * to support. * * Returns 0 if an unsupportable combination is found, 1 otherwise. */ static int aix_valid_authentications(const char *user) { char *auth1, *sys, *p; int valid = 1; if (getuserattr((char *)user, S_AUTHSYSTEM, &sys, SEC_CHAR) != 0) { logit("Can't retrieve attribute SYSTEM for %s: %.100s", user, strerror(errno)); return 0; } debug3("AIX SYSTEM attribute %s", sys); if (strcmp(sys, "NONE") != 0) return 1; /* not "NONE", so is OK */ if (getuserattr((char *)user, S_AUTH1, &auth1, SEC_LIST) != 0) { logit("Can't retrieve attribute auth1 for %s: %.100s", user, strerror(errno)); return 0; } p = auth1; /* A SEC_LIST is concatenated strings, ending with two NULs. */ while (p[0] != '\0' && p[1] != '\0') { debug3("AIX auth1 attribute list member %s", p); if (strcmp(p, "NONE") != 0 && strcmp(p, "SYSTEM")) { logit("Account %s has unsupported auth1 value '%s'", user, p); valid = 0; } p += strlen(p) + 1; } return (valid); } /* * Do authentication via AIX's authenticate routine. We loop until the * reenter parameter is 0, but normally authenticate is called only once. * * Note: this function returns 1 on success, whereas AIX's authenticate() * returns 0. */ int sys_auth_passwd(struct ssh *ssh, const char *password) { Authctxt *ctxt = ssh->authctxt; char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name; int r, authsuccess = 0, expired, reenter, result; do { result = authenticate((char *)name, (char *)password, &reenter, &authmsg); aix_remove_embedded_newlines(authmsg); debug3("AIX/authenticate result %d, authmsg %.100s", result, authmsg); } while (reenter); if (!aix_valid_authentications(name)) result = -1; if (result == 0) { authsuccess = 1; /* * Record successful login. We don't have a pty yet, so just * label the line as "ssh" */ aix_setauthdb(name); /* * Check if the user's password is expired. */ expired = passwdexpired(name, &msg); if (msg && *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); switch (expired) { case 0: /* password not expired */ break; case 1: /* expired, password change required */ ctxt->force_pwchange = 1; break; default: /* user can't change(2) or other error (-1) */ logit("Password can't be changed for user %s: %.100s", name, msg); free(msg); authsuccess = 0; } aix_restoreauthdb(); } free(authmsg); return authsuccess; } /* * Check if specified account is permitted to log in. * Returns 1 if login is allowed, 0 if not allowed. */ int sys_auth_allowed_user(struct passwd *pw, struct sshbuf *loginmsg) { char *msg = NULL; int r, result, permitted = 0; struct stat st; /* * Don't perform checks for root account (PermitRootLogin controls * logins via ssh) or if running as non-root user (since * loginrestrictions will always fail due to insufficient privilege). */ if (pw->pw_uid == 0 || geteuid() != 0) { debug3("%s: not checking", __func__); return 1; } result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg); if (result == 0) permitted = 1; /* * If restricted because /etc/nologin exists, the login will be denied * in session.c after the nologin message is sent, so allow for now * and do not append the returned message. */ if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) permitted = 1; 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); debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg); if (!permitted) logit("Login restricted for %s: %.100s", pw->pw_name, msg); free(msg); return permitted; } int sys_auth_record_login(const char *user, const char *host, const char *ttynm, struct sshbuf *loginmsg) { char *msg = NULL; int success = 0; aix_setauthdb(user); if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) { success = 1; if (msg != NULL) { debug("AIX/loginsuccess: msg %s", msg); if (lastlogin_msg == NULL) lastlogin_msg = msg; } } aix_restoreauthdb(); return (success); } char * sys_auth_get_lastlogin_msg(const char *user, uid_t uid) { char *msg = lastlogin_msg; lastlogin_msg = NULL; return msg; } # ifdef CUSTOM_FAILED_LOGIN /* * record_failed_login: generic "login failed" interface function */ void record_failed_login(struct ssh *ssh, const char *user, const char *hostname, const char *ttyname) { if (geteuid() != 0) return; aix_setauthdb(user); # ifdef AIX_LOGINFAILED_4ARG loginfailed((char *)user, (char *)hostname, (char *)ttyname, AUDIT_FAIL_AUTH); # else loginfailed((char *)user, (char *)hostname, (char *)ttyname); # endif aix_restoreauthdb(); } # endif /* CUSTOM_FAILED_LOGIN */ /* * If we have setauthdb, retrieve the password registry for the user's * account then feed it to setauthdb. This will mean that subsequent AIX auth * functions will only use the specified loadable module. If we don't have * setauthdb this is a no-op. */ void aix_setauthdb(const char *user) { # ifdef HAVE_SETAUTHDB char *registry; if (setuserdb(S_READ) == -1) { debug3("%s: Could not open userdb to read", __func__); return; } if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { if (setauthdb(registry, old_registry) == 0) debug3("AIX/setauthdb set registry '%s'", registry); else debug3("AIX/setauthdb set registry '%s' failed: %s", registry, strerror(errno)); } else debug3("%s: Could not read S_REGISTRY for user: %s", __func__, strerror(errno)); enduserdb(); # endif /* HAVE_SETAUTHDB */ } /* * Restore the user's registry settings from old_registry. * Note that if the first aix_setauthdb fails, setauthdb("") is still safe * (it restores the system default behaviour). If we don't have setauthdb, * this is a no-op. */ void aix_restoreauthdb(void) { # ifdef HAVE_SETAUTHDB if (setauthdb(old_registry, NULL) == 0) debug3("%s: restoring old registry '%s'", __func__, old_registry); else debug3("%s: failed to restore old registry %s", __func__, old_registry); # endif /* HAVE_SETAUTHDB */ } # endif /* WITH_AIXAUTHENTICATE */ # 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. */ char * 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); if (getuserattr(pw_name, S_AUTHDOMAIN, &authdomain, SEC_CHAR) != 0) debug("AIX getuserattr S_AUTHDOMAIN: %s", strerror(errno)); if (getuserattr(pw_name, S_AUTHNAME, &authname, SEC_CHAR) != 0) debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno)); if (authdomain != NULL) xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain); else if (authname != NULL) principal = xstrdup(authname); enduserdb(); return principal; } # endif /* USE_AIX_KRB_NAME */ # if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO) # undef getnameinfo /* * For some reason, AIX's getnameinfo will refuse to resolve the all-zeros * IPv6 address into its textual representation ("::"), so we wrap it * with a function that will. */ int sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { struct sockaddr_in6 *sa6; u_int32_t *a6; if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) && sa->sa_family == AF_INET6) { sa6 = (struct sockaddr_in6 *)sa; a6 = sa6->sin6_addr.u6_addr.u6_addr32; if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { strlcpy(host, "::", hostlen); snprintf(serv, servlen, "%d", sa6->sin6_port); return 0; } } return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); } # endif /* AIX_GETNAMEINFO_HACK */ # if defined(USE_GETGRSET) # include int getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt) { char *cp, *grplist, *grp; gid_t gid; int ret = 0, ngroups = 0, maxgroups; long long ll; maxgroups = *grpcnt; if ((cp = grplist = getgrset(user)) == NULL) return -1; /* handle zero-length case */ if (maxgroups <= 0) { *grpcnt = 0; return -1; } /* copy primary group */ groups[ngroups++] = pgid; /* copy each entry from getgrset into group list */ while ((grp = strsep(&grplist, ",")) != NULL) { ll = strtoll(grp, NULL, 10); if (ngroups >= maxgroups || ll < 0 || ll > UID_MAX) { ret = -1; goto out; } gid = (gid_t)ll; if (gid == pgid) continue; /* we have already added primary gid */ groups[ngroups++] = gid; } out: free(cp); *grpcnt = ngroups; return ret; } # endif /* USE_GETGRSET */ #endif /* _AIX */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-aix.h100644 001750 001750 0000000003614775415623 0020003xustar0030 atime=1744182234.661937197 openssh-10.0p1/openbsd-compat/port-aix.h010064400017500001750000000103621477541562300163700ustar00djmdjm/* * * Copyright (c) 2001 Gert Doering. All rights reserved. * Copyright (c) 2004,2005,2006 Darren Tucker. 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. */ #ifdef _AIX #ifdef HAVE_SYS_SOCKET_H # include #endif struct ssh; struct sshbuf; /* These should be in the system headers but are not. */ int usrinfo(int, char *, int); #if defined(HAVE_DECL_SETAUTHDB) && (HAVE_DECL_SETAUTHDB == 0) int setauthdb(const char *, char *); #endif /* these may or may not be in the headers depending on the version */ #if defined(HAVE_DECL_AUTHENTICATE) && (HAVE_DECL_AUTHENTICATE == 0) int authenticate(char *, char *, int *, char **); #endif #if defined(HAVE_DECL_LOGINFAILED) && (HAVE_DECL_LOGINFAILED == 0) int loginfailed(char *, char *, char *); #endif #if defined(HAVE_DECL_LOGINRESTRICTIONS) && (HAVE_DECL_LOGINRESTRICTIONS == 0) int loginrestrictions(char *, int, char *, char **); #endif #if defined(HAVE_DECL_LOGINSUCCESS) && (HAVE_DECL_LOGINSUCCESS == 0) int loginsuccess(char *, char *, char *, char **); #endif #if defined(HAVE_DECL_PASSWDEXPIRED) && (HAVE_DECL_PASSWDEXPIRED == 0) int passwdexpired(char *, char **); #endif /* Some versions define r_type in the above headers, which causes a conflict */ #ifdef r_type # undef r_type #endif /* AIX 4.2.x doesn't have nanosleep but does have nsleep which is equivalent */ #if !defined(HAVE_NANOSLEEP) && defined(HAVE_NSLEEP) # define nanosleep(a,b) nsleep(a,b) #endif /* For struct timespec on AIX 4.2.x */ #ifdef HAVE_SYS_TIMERS_H # include #endif /* for setpcred and friends */ #ifdef HAVE_USERSEC_H # include #endif /* * According to the setauthdb man page, AIX password registries must be 15 * chars or less plus terminating NUL. */ #ifdef HAVE_SETAUTHDB # define REGISTRY_SIZE 16 #endif 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 *, struct sshbuf *); # define CUSTOM_SYS_AUTH_RECORD_LOGIN 1 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(const char *); # endif #endif void aix_setauthdb(const char *); void aix_restoreauthdb(void); void aix_remove_embedded_newlines(char *); #if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_GETADDRINFO) # ifdef getnameinfo # undef getnameinfo # endif int sshaix_getnameinfo(const struct sockaddr *, size_t, char *, size_t, char *, size_t, int); # define getnameinfo(a,b,c,d,e,f,g) (sshaix_getnameinfo(a,b,c,d,e,f,g)) #endif /* * We use getgrset in preference to multiple getgrent calls for efficiency * plus it supports NIS and LDAP groups. */ #if !defined(HAVE_GETGROUPLIST) && defined(HAVE_GETGRSET) # define HAVE_GETGROUPLIST # define USE_GETGRSET int getgrouplist(const char *, gid_t, gid_t *, int *); #endif #endif /* _AIX */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-irix.c100644 001750 001750 0000000003614775415623 0020170xustar0030 atime=1744182234.661937197 openssh-10.0p1/openbsd-compat/port-irix.c010064400017500001750000000057271477541562300165660ustar00djmdjm/* * Copyright (c) 2000 Denis Parker. All rights reserved. * Copyright (c) 2000 Michael Stone. 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_IRIX_PROJECT) || \ defined(WITH_IRIX_JOBS) || \ defined(WITH_IRIX_ARRAY) #include #include #include #ifdef WITH_IRIX_PROJECT # include #endif /* WITH_IRIX_PROJECT */ #ifdef WITH_IRIX_JOBS # include #endif #ifdef WITH_IRIX_AUDIT # include #endif /* WITH_IRIX_AUDIT */ #include "log.h" void irix_setusercontext(struct passwd *pw) { #ifdef WITH_IRIX_PROJECT prid_t projid; #endif #ifdef WITH_IRIX_JOBS jid_t jid = 0; #elif defined(WITH_IRIX_ARRAY) 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)); #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)); #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)); #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)); } #endif /* WITH_IRIX_AUDIT */ } #endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-irix.h100644 001750 001750 0000000003614775415623 0020175xustar0030 atime=1744182234.661937197 openssh-10.0p1/openbsd-compat/port-irix.h010064400017500001750000000032271477541562300165640ustar00djmdjm/* * Copyright (c) 2000 Denis Parker. All rights reserved. * Copyright (c) 2000 Michael Stone. 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 _PORT_IRIX_H #define _PORT_IRIX_H #if defined(WITH_IRIX_PROJECT) || \ defined(WITH_IRIX_JOBS) || \ defined(WITH_IRIX_ARRAY) void irix_setusercontext(struct passwd *pw); #endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ #endif /* ! _PORT_IRIX_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-linux.c100644 001750 001750 0000000003614775415623 0020354xustar0030 atime=1744182234.662913784 openssh-10.0p1/openbsd-compat/port-linux.c010064400017500001750000000240501477541562300167400ustar00djmdjm/* * Copyright (c) 2005 Daniel Walsh * Copyright (c) 2006 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. */ /* * Linux-specific portability code - just SELinux support at present */ #include "includes.h" #if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) || \ defined(SYSTEMD_NOTIFY) #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "xmalloc.h" #include "port-linux.h" #include "misc.h" #ifdef WITH_SELINUX #include #include #include #ifndef SSH_SELINUX_UNCONFINED_TYPE # define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:" #endif /* Wrapper around is_selinux_enabled() to log its return value once only */ int ssh_selinux_enabled(void) { static int enabled = -1; if (enabled == -1) { enabled = (is_selinux_enabled() == 1); debug("SELinux support %s", enabled ? "enabled" : "disabled"); } return (enabled); } /* Return the default security context for the given username */ static char * ssh_selinux_getctxbyname(char *pwname) { char *sc = NULL, *sename = NULL, *lvl = NULL; int r; #ifdef HAVE_GETSEUSERBYNAME if (getseuserbyname(pwname, &sename, &lvl) != 0) return NULL; #else sename = pwname; lvl = NULL; #endif #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL r = get_default_context_with_level(sename, lvl, NULL, &sc); #else r = get_default_context(sename, NULL, &sc); #endif if (r != 0) { switch (security_getenforce()) { case -1: fatal("%s: ssh_selinux_getctxbyname: " "security_getenforce() failed", __func__); case 0: error("%s: Failed to get default SELinux security " "context for %s", __func__, pwname); sc = NULL; break; default: fatal("%s: Failed to get default SELinux security " "context for %s (in enforcing mode)", __func__, pwname); } } #ifdef HAVE_GETSEUSERBYNAME free(sename); free(lvl); #endif return sc; } /* Set the execution context to the default for the specified user */ void ssh_selinux_setup_exec_context(char *pwname) { char *user_ctx = NULL; if (!ssh_selinux_enabled()) return; debug3("%s: setting execution context", __func__); user_ctx = ssh_selinux_getctxbyname(pwname); if (setexeccon(user_ctx) != 0) { switch (security_getenforce()) { case -1: fatal("%s: security_getenforce() failed", __func__); case 0: error("%s: Failed to set SELinux execution " "context for %s", __func__, pwname); break; default: fatal("%s: Failed to set SELinux execution context " "for %s (in enforcing mode)", __func__, pwname); } } if (user_ctx != NULL) freecon(user_ctx); debug3("%s: done", __func__); } /* Set the TTY context for the specified user */ void ssh_selinux_setup_pty(char *pwname, const char *tty) { char *new_tty_ctx = NULL, *user_ctx = NULL, *old_tty_ctx = NULL; security_class_t chrclass; if (!ssh_selinux_enabled()) return; debug3("%s: setting TTY context on %s", __func__, tty); user_ctx = ssh_selinux_getctxbyname(pwname); /* XXX: should these calls fatal() upon failure in enforcing mode? */ if (getfilecon(tty, &old_tty_ctx) == -1) { 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, chrclass, &new_tty_ctx) != 0) { error("%s: security_compute_relabel: %s", __func__, strerror(errno)); goto out; } if (setfilecon(tty, new_tty_ctx) != 0) error("%s: setfilecon: %s", __func__, strerror(errno)); out: if (new_tty_ctx != NULL) freecon(new_tty_ctx); if (old_tty_ctx != NULL) freecon(old_tty_ctx); if (user_ctx != NULL) freecon(user_ctx); debug3("%s: done", __func__); } void ssh_selinux_change_context(const char *newname) { char *oldctx, *newctx, *cx, *cx2; LogLevel log_level = SYSLOG_LEVEL_INFO; if (!ssh_selinux_enabled()) return; if (getcon(&oldctx) < 0) { logit_f("getcon failed with %s", strerror(errno)); return; } if ((cx = strchr(oldctx, ':')) == NULL || (cx = strchr(cx + 1, ':')) == NULL || (cx - oldctx) >= INT_MAX) { logit_f("unparsable context %s", oldctx); return; } /* * Check whether we are attempting to switch away from an unconfined * security context. */ if (strncmp(cx, SSH_SELINUX_UNCONFINED_TYPE, sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0) log_level = SYSLOG_LEVEL_DEBUG3; cx2 = strchr(cx + 1, ':'); xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx, newname, cx2 == NULL ? "" : cx2); debug3_f("setting context from '%s' to '%s'", oldctx, newctx); if (setcon(newctx) < 0) do_log2_f(log_level, "setcon %s from %s failed with %s", newctx, oldctx, strerror(errno)); free(oldctx); free(newctx); } void ssh_selinux_setfscreatecon(const char *path) { char *context; struct selabel_handle *shandle = NULL; if (!ssh_selinux_enabled()) return; if (path == NULL) { setfscreatecon(NULL); return; } if ((shandle = selabel_open(SELABEL_CTX_FILE, NULL, 0)) == NULL) { debug_f("selabel_open failed"); return; } if (selabel_lookup(shandle, &context, path, 0700) == 0) setfscreatecon(context); selabel_close(shandle); } #endif /* WITH_SELINUX */ #ifdef LINUX_OOM_ADJUST /* * The magic "don't kill me" values, old and new, as documented in eg: * http://lxr.linux.no/#linux+v2.6.32/Documentation/filesystems/proc.txt * http://lxr.linux.no/#linux+v2.6.36/Documentation/filesystems/proc.txt */ static int oom_adj_save = INT_MIN; static char *oom_adj_path = NULL; struct { char *path; int value; } oom_adjust[] = { {"/proc/self/oom_score_adj", -1000}, /* kernels >= 2.6.36 */ {"/proc/self/oom_adj", -17}, /* kernels <= 2.6.35 */ {NULL, 0}, }; /* * Tell the kernel's out-of-memory killer to avoid sshd. * Returns the previous oom_adj value or zero. */ void oom_adjust_setup(void) { int i, value; FILE *fp; debug3("%s", __func__); for (i = 0; oom_adjust[i].path != NULL; i++) { oom_adj_path = oom_adjust[i].path; value = oom_adjust[i].value; if ((fp = fopen(oom_adj_path, "r+")) != NULL) { if (fscanf(fp, "%d", &oom_adj_save) != 1) verbose("error reading %s: %s", oom_adj_path, strerror(errno)); else { rewind(fp); if (fprintf(fp, "%d\n", value) <= 0) verbose("error writing %s: %s", oom_adj_path, strerror(errno)); else debug("Set %s from %d to %d", oom_adj_path, oom_adj_save, value); } fclose(fp); return; } } oom_adj_path = NULL; } /* Restore the saved OOM adjustment */ void oom_adjust_restore(void) { FILE *fp; debug3("%s", __func__); if (oom_adj_save == INT_MIN || oom_adj_path == NULL || (fp = fopen(oom_adj_path, "w")) == NULL) return; if (fprintf(fp, "%d\n", oom_adj_save) <= 0) verbose("error writing %s: %s", oom_adj_path, strerror(errno)); else debug("Set %s to %d", oom_adj_path, oom_adj_save); fclose(fp); return; } #endif /* LINUX_OOM_ADJUST */ #ifdef LINUX_MEMLOCK_ONFAULT #include void memlock_onfault_setup(void) { if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) < 0) verbose("unable to lock memory: %s", strerror(errno)); else debug("memory locked"); } #endif /* LINUX_MEMLOCK_ONFAULT */ #ifdef SYSTEMD_NOTIFY static void ssh_systemd_notify(const char *, ...) __attribute__((__format__ (printf, 1, 2))) __attribute__((__nonnull__ (1))); static void ssh_systemd_notify(const char *fmt, ...) { char *s = NULL; const char *path; struct stat sb; struct sockaddr_un addr; int fd = -1; va_list ap; if ((path = getenv("NOTIFY_SOCKET")) == NULL || strlen(path) == 0) return; va_start(ap, fmt); xvasprintf(&s, fmt, ap); va_end(ap); /* Only AF_UNIX is supported, with path or abstract sockets */ if (path[0] != '/' && path[0] != '@') { error_f("socket \"%s\" is not compatible with AF_UNIX", path); goto out; } if (path[0] == '/' && stat(path, &sb) != 0) { error_f("socket \"%s\" stat: %s", path, strerror(errno)); goto out; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; if (strlcpy(addr.sun_path, path, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { error_f("socket path \"%s\" too long", path); goto out; } /* Support for abstract socket */ if (addr.sun_path[0] == '@') addr.sun_path[0] = 0; if ((fd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1) { error_f("socket \"%s\": %s", path, strerror(errno)); goto out; } if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { error_f("socket \"%s\" connect: %s", path, strerror(errno)); goto out; } if (write(fd, s, strlen(s)) != (ssize_t)strlen(s)) { error_f("socket \"%s\" write: %s", path, strerror(errno)); goto out; } debug_f("socket \"%s\" notified %s", path, s); out: if (fd != -1) close(fd); free(s); } void ssh_systemd_notify_ready(void) { ssh_systemd_notify("READY=1"); } void ssh_systemd_notify_reload(void) { struct timespec now; monotime_ts(&now); if (now.tv_sec < 0 || now.tv_nsec < 0) { error_f("monotime returned negative value"); ssh_systemd_notify("RELOADING=1"); } else { ssh_systemd_notify("RELOADING=1\nMONOTONIC_USEC=%llu", ((uint64_t)now.tv_sec * 1000000ULL) + ((uint64_t)now.tv_nsec / 1000ULL)); } } #endif /* SYSTEMD_NOTIFY */ #endif /* WITH_SELINUX || LINUX_OOM_ADJUST || SYSTEMD_NOTIFY */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-linux.h100644 001750 001750 0000000003614775415623 0020361xustar0030 atime=1744182234.662913784 openssh-10.0p1/openbsd-compat/port-linux.h010064400017500001750000000025451477541562300167520ustar00djmdjm/* * Copyright (c) 2006 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. */ #ifndef _PORT_LINUX_H #define _PORT_LINUX_H #ifdef WITH_SELINUX int ssh_selinux_enabled(void); void ssh_selinux_setup_pty(char *, const char *); void ssh_selinux_setup_exec_context(char *); void ssh_selinux_change_context(const char *); void ssh_selinux_setfscreatecon(const char *); #endif #ifdef LINUX_OOM_ADJUST void oom_adjust_restore(void); void oom_adjust_setup(void); #endif #ifdef LINUX_MEMLOCK_ONFAULT void memlock_onfault_setup(void); #endif #ifdef SYSTEMD_NOTIFY void ssh_systemd_notify_ready(void); void ssh_systemd_notify_reload(void); #endif #endif /* ! _PORT_LINUX_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-net.c100644 001750 001750 0000000003614775415623 0020003xustar0030 atime=1744182234.662913784 openssh-10.0p1/openbsd-compat/port-net.c010064400017500001750000000207361477541562300163760ustar00djmdjm/* * Copyright (c) 2005 Reyk Floeter * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "log.h" #include "misc.h" #include "sshbuf.h" #include "channels.h" #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 #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. * * SSH_TUN_LINUX Use the (newer) Linux tun/tap device * SSH_TUN_FREEBSD Use the FreeBSD tun/tap device * SSH_TUN_COMPAT_AF Translate the OpenBSD address family * SSH_TUN_PREPEND_AF Prepend/remove the address family */ /* * System-specific tunnel open function */ #if defined(SSH_TUN_LINUX) #include #define TUN_CTRL_DEV "/dev/net/tun" int sys_tun_open(int tun, int mode, char **ifname) { struct ifreq ifr; int fd = -1; const char *name = NULL; 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)); if (mode == SSH_TUNMODE_ETHERNET) { ifr.ifr_flags = IFF_TAP; name = "tap%d"; } else { ifr.ifr_flags = IFF_TUN; name = "tun%d"; } ifr.ifr_flags |= IFF_NO_PI; if (tun != SSH_TUNID_ANY) { if (tun > SSH_TUNID_MAX) { debug("%s: invalid tunnel id %x: %s", __func__, tun, strerror(errno)); goto failed; } snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), name, tun); } if (ioctl(fd, TUNSETIFF, &ifr) == -1) { debug("%s: failed to configure tunnel (mode %d): %s", __func__, mode, strerror(errno)); goto failed; } if (tun == SSH_TUNID_ANY) debug("%s: tunnel mode %d fd %d", __func__, mode, fd); 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: close(fd); return (-1); } #endif /* SSH_TUN_LINUX */ #ifdef SSH_TUN_FREEBSD #include #include #ifdef HAVE_NET_IF_TUN_H #include #endif int sys_tun_open(int tun, int mode, char **ifname) { struct ifreq ifr; char name[100]; int fd = -1, sock; const char *tunbase = "tun"; #if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) int flag; #endif if (ifname != NULL) *ifname = NULL; if (mode == SSH_TUNMODE_ETHERNET) { #ifdef SSH_TUN_NO_L2 debug("%s: no layer 2 tunnelling support", __func__); return (-1); #else tunbase = "tap"; #endif } /* Open the tunnel device */ if (tun <= SSH_TUNID_MAX) { snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); fd = open(name, O_RDWR); } else if (tun == SSH_TUNID_ANY) { for (tun = 100; tun >= 0; tun--) { snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); if ((fd = open(name, O_RDWR)) >= 0) break; } } else { debug("%s: invalid tunnel %u\n", __func__, tun); return (-1); } if (fd < 0) { debug("%s: %s open failed: %s", __func__, name, strerror(errno)); return (-1); } /* Turn on tunnel headers */ #if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) flag = 1; if (mode != SSH_TUNMODE_ETHERNET && ioctl(fd, TUNSIFHEAD, &flag) == -1) { debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd, strerror(errno)); close(fd); } #endif 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), "%s%d", tunbase, tun); if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) goto failed; if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) goto failed; if ((ifr.ifr_flags & IFF_UP) == 0) { ifr.ifr_flags |= IFF_UP; if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) goto failed; } if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)) == NULL) goto failed; close(sock); 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); } #endif /* SSH_TUN_FREEBSD */ /* * System-specific channel filters */ #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 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; #endif #if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF) u_int32_t af; #endif /* XXX update channel input filter API to use unsigned length */ if (_len < 0) return -1; len = _len; #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) fatal("%s: buffer error: %s", __func__, ssh_err(r)); return (0); } u_char * sys_tun_outfilter(struct ssh *ssh, struct Channel *c, u_char **data, size_t *dlen) { u_char *buf; u_int32_t af; int r; /* XXX new API is incompatible with this signature. */ if ((r = sshbuf_get_string(c->output, data, dlen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (*dlen < sizeof(af)) return (NULL); buf = *data; #if defined(SSH_TUN_PREPEND_AF) /* skip address family */ *dlen -= sizeof(af); buf = *data + sizeof(af); #elif defined(SSH_TUN_COMPAT_AF) /* 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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-net.h100644 001750 001750 0000000003614775415623 0020010xustar0030 atime=1744182234.662913784 openssh-10.0p1/openbsd-compat/port-net.h010064400017500001750000000031161477541562300163740ustar00djmdjm/* * Copyright (c) 2005 Reyk Floeter * * 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 _PORT_TUN_H #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, char **); #endif #if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF) # define SSH_TUN_FILTER 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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-prngd.c100644 001750 001750 0000000003614775415623 0020327xustar0030 atime=1744182234.662913784 openssh-10.0p1/openbsd-compat/port-prngd.c010064400017500001750000000111011477541562300167040ustar00djmdjm/* * Copyright (c) 2001 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef HAVE_SYS_UN_H # include #endif #include #include #include #include #include #include #include #include /* for offsetof */ #include "atomicio.h" #include "misc.h" #include "log.h" #if defined(PRNGD_PORT) || defined(PRNGD_SOCKET) /* * EGD/PRNGD interface. * * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon * listening either on 'tcp_port', or via Unix domain socket at * * 'socket_path'. * Either a non-zero tcp_port or a non-null socket_path must be * supplied. * Returns 0 on success, -1 on error */ static int get_random_bytes_prngd(unsigned char *buf, int len, unsigned short tcp_port, char *socket_path) { int fd, addr_len, rval, errors; u_char msg[2]; struct sockaddr_storage addr; struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr; sshsig_t old_sigpipe; /* Sanity checks */ if (socket_path == NULL && tcp_port == 0) fatal("You must specify a port or a socket"); if (socket_path != NULL && strlen(socket_path) >= sizeof(addr_un->sun_path)) fatal("Random pool path is too long"); if (len <= 0 || len > 255) fatal("Too many bytes (%d) to read from PRNGD", len); memset(&addr, '\0', sizeof(addr)); if (tcp_port != 0) { addr_in->sin_family = AF_INET; addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr_in->sin_port = htons(tcp_port); addr_len = sizeof(*addr_in); } else { addr_un->sun_family = AF_UNIX; strlcpy(addr_un->sun_path, socket_path, sizeof(addr_un->sun_path)); addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path) + 1; } old_sigpipe = ssh_signal(SIGPIPE, SIG_IGN); errors = 0; rval = -1; reopen: fd = socket(addr.ss_family, SOCK_STREAM, 0); if (fd == -1) { error("Couldn't create socket: %s", strerror(errno)); goto done; } if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) { if (tcp_port != 0) { error("Couldn't connect to PRNGD port %d: %s", tcp_port, strerror(errno)); } else { error("Couldn't connect to PRNGD socket \"%s\": %s", addr_un->sun_path, strerror(errno)); } goto done; } /* Send blocking read request to PRNGD */ msg[0] = 0x02; msg[1] = len; if (atomicio(vwrite, fd, msg, sizeof(msg)) != sizeof(msg)) { if (errno == EPIPE && errors < 10) { close(fd); errors++; goto reopen; } error("Couldn't write to PRNGD socket: %s", strerror(errno)); goto done; } if (atomicio(read, fd, buf, len) != (size_t)len) { if (errno == EPIPE && errors < 10) { close(fd); errors++; goto reopen; } error("Couldn't read from PRNGD socket: %s", strerror(errno)); goto done; } rval = 0; done: ssh_signal(SIGPIPE, old_sigpipe); if (fd != -1) close(fd); return rval; } #endif /* PRNGD_PORT || PRNGD_SOCKET */ int seed_from_prngd(unsigned char *buf, size_t bytes) { #ifdef PRNGD_PORT debug("trying egd/prngd port %d", PRNGD_PORT); if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0) return 0; #endif #ifdef PRNGD_SOCKET debug("trying egd/prngd socket %s", PRNGD_SOCKET); if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0) return 0; #endif return -1; } openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-solaris.c100644 001750 001750 0000000003614775415623 0020671xustar0030 atime=1744182234.663891844 openssh-10.0p1/openbsd-compat/port-solaris.c010064400017500001750000000241501477541562300172560ustar00djmdjm/* * Copyright (c) 2006 Chad Mynhier. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "config.h" #include "includes.h" #include #include #include #ifdef HAVE_FCNTL_H # include #endif #include #include #include #include "log.h" #ifdef USE_SOLARIS_PROCESS_CONTRACTS #include #include #include #define CT_TEMPLATE CTFS_ROOT "/process/template" #define CT_LATEST CTFS_ROOT "/process/latest" static int tmpl_fd = -1; /* Lookup the latest process contract */ static ctid_t get_active_process_contract_id(void) { int stat_fd; ctid_t ctid = -1; ct_stathdl_t stathdl; if ((stat_fd = open64(CT_LATEST, O_RDONLY)) == -1) { error("%s: Error opening 'latest' process " "contract: %s", __func__, strerror(errno)); return -1; } if (ct_status_read(stat_fd, CTD_COMMON, &stathdl) != 0) { error("%s: Error reading process contract " "status: %s", __func__, strerror(errno)); goto out; } if ((ctid = ct_status_get_id(stathdl)) < 0) { error("%s: Error getting process contract id: %s", __func__, strerror(errno)); goto out; } ct_status_free(stathdl); out: close(stat_fd); return ctid; } void solaris_contract_pre_fork(void) { if ((tmpl_fd = open64(CT_TEMPLATE, O_RDWR)) == -1) { error("%s: open %s: %s", __func__, CT_TEMPLATE, strerror(errno)); return; } debug2("%s: setting up process contract template on fd %d", __func__, tmpl_fd); /* First we set the template parameters and event sets. */ if (ct_pr_tmpl_set_param(tmpl_fd, CT_PR_PGRPONLY) != 0) { error("%s: Error setting process contract parameter set " "(pgrponly): %s", __func__, strerror(errno)); goto fail; } if (ct_pr_tmpl_set_fatal(tmpl_fd, CT_PR_EV_HWERR) != 0) { error("%s: Error setting process contract template " "fatal events: %s", __func__, strerror(errno)); goto fail; } if (ct_tmpl_set_critical(tmpl_fd, 0) != 0) { error("%s: Error setting process contract template " "critical events: %s", __func__, strerror(errno)); goto fail; } if (ct_tmpl_set_informative(tmpl_fd, CT_PR_EV_HWERR) != 0) { error("%s: Error setting process contract template " "informative events: %s", __func__, strerror(errno)); goto fail; } /* Now make this the active template for this process. */ if (ct_tmpl_activate(tmpl_fd) != 0) { error("%s: Error activating process contract " "template: %s", __func__, strerror(errno)); goto fail; } return; fail: if (tmpl_fd != -1) { close(tmpl_fd); tmpl_fd = -1; } } void solaris_contract_post_fork_child() { debug2("%s: clearing process contract template on fd %d", __func__, tmpl_fd); /* Clear the active template. */ if (ct_tmpl_clear(tmpl_fd) != 0) error("%s: Error clearing active process contract " "template: %s", __func__, strerror(errno)); close(tmpl_fd); tmpl_fd = -1; } void solaris_contract_post_fork_parent(pid_t pid) { ctid_t ctid; char ctl_path[256]; int r, ctl_fd = -1, stat_fd = -1; debug2("%s: clearing template (fd %d)", __func__, tmpl_fd); if (tmpl_fd == -1) return; /* First clear the active template. */ if ((r = ct_tmpl_clear(tmpl_fd)) != 0) error("%s: Error clearing active process contract " "template: %s", __func__, strerror(errno)); close(tmpl_fd); tmpl_fd = -1; /* * If either the fork didn't succeed (pid < 0), or clearing * th active contract failed (r != 0), then we have nothing * more do. */ if (r != 0 || pid <= 0) return; /* Now lookup and abandon the contract we've created. */ ctid = get_active_process_contract_id(); debug2("%s: abandoning contract id %ld", __func__, ctid); snprintf(ctl_path, sizeof(ctl_path), CTFS_ROOT "/process/%ld/ctl", ctid); if ((ctl_fd = open64(ctl_path, O_WRONLY)) < 0) { error("%s: Error opening process contract " "ctl file: %s", __func__, strerror(errno)); goto fail; } if (ct_ctl_abandon(ctl_fd) < 0) { error("%s: Error abandoning process contract: %s", __func__, strerror(errno)); goto fail; } close(ctl_fd); return; fail: if (tmpl_fd != -1) { close(tmpl_fd); tmpl_fd = -1; } if (stat_fd != -1) close(stat_fd); if (ctl_fd != -1) close(ctl_fd); } #endif #ifdef USE_SOLARIS_PROJECTS #include #include /* * Get/set solaris default project. * If we fail, just run along gracefully. */ void solaris_set_default_project(struct passwd *pw) { struct project *defaultproject; struct project tempproject; char buf[1024]; /* get default project, if we fail just return gracefully */ if ((defaultproject = getdefaultproj(pw->pw_name, &tempproject, &buf, sizeof(buf))) != NULL) { /* set default project */ if (setproject(defaultproject->pj_name, pw->pw_name, TASK_NORMAL) != 0) debug("setproject(%s): %s", defaultproject->pj_name, strerror(errno)); } else { /* debug on getdefaultproj() error */ debug("getdefaultproj(%s): %s", pw->pw_name, strerror(errno)); } } #endif /* USE_SOLARIS_PROJECTS */ #ifdef USE_SOLARIS_PRIVS # ifdef HAVE_PRIV_H # include # endif priv_set_t * solaris_basic_privset(void) { priv_set_t *pset; #ifdef HAVE_PRIV_BASICSET if ((pset = priv_allocset()) == NULL) { error("priv_allocset: %s", strerror(errno)); return NULL; } priv_basicset(pset); #else if ((pset = priv_str_to_set("basic", ",", NULL)) == NULL) { error("priv_str_to_set: %s", strerror(errno)); return NULL; } #endif return pset; } void solaris_drop_privs_pinfo_net_fork_exec(void) { priv_set_t *pset = NULL, *npset = NULL; /* * Note: this variant avoids dropping DAC filesystem rights, in case * the process calling it is running as root and should have the * ability to read/write/chown any file on the system. * * We start with the basic set, then *add* the DAC rights to it while * taking away other parts of BASIC we don't need. Then we intersect * this with our existing PERMITTED set. In this way we keep any * DAC rights we had before, while otherwise reducing ourselves to * the minimum set of privileges we need to proceed. * * This also means we drop any other parts of "root" that we don't * need (e.g. the ability to kill any process, create new device nodes * etc etc). */ if ((pset = priv_allocset()) == NULL) fatal("priv_allocset: %s", strerror(errno)); if ((npset = solaris_basic_privset()) == NULL) fatal("solaris_basic_privset: %s", strerror(errno)); if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 || priv_addset(npset, PRIV_FILE_DAC_READ) != 0 || priv_addset(npset, PRIV_FILE_DAC_SEARCH) != 0 || priv_addset(npset, PRIV_FILE_DAC_WRITE) != 0 || priv_addset(npset, PRIV_FILE_OWNER) != 0) fatal("priv_addset: %s", strerror(errno)); if (priv_delset(npset, PRIV_PROC_EXEC) != 0 || #ifdef PRIV_NET_ACCESS priv_delset(npset, PRIV_NET_ACCESS) != 0 || #endif priv_delset(npset, PRIV_PROC_FORK) != 0 || priv_delset(npset, PRIV_PROC_INFO) != 0 || priv_delset(npset, PRIV_PROC_SESSION) != 0) fatal("priv_delset: %s", strerror(errno)); #ifdef PRIV_XPOLICY /* * It is possible that the user has an extended policy * in place; the LIMIT set restricts the extended policy * and so should not be restricted. * PRIV_XPOLICY is newly defined in Solaris 11 though the extended * policy was not implemented until Solaris 11.1. */ if (getpflags(PRIV_XPOLICY) == 1) { if (getppriv(PRIV_LIMIT, pset) != 0) fatal("getppriv: %s", strerror(errno)); priv_intersect(pset, npset); if (setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0) fatal("setppriv: %s", strerror(errno)); } else #endif { /* Cannot exec, so we can kill the limit set. */ priv_emptyset(pset); if (setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0) fatal("setppriv: %s", strerror(errno)); } if (getppriv(PRIV_PERMITTED, pset) != 0) fatal("getppriv: %s", strerror(errno)); priv_intersect(pset, npset); if (setppriv(PRIV_SET, PRIV_PERMITTED, npset) != 0 || setppriv(PRIV_SET, PRIV_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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-solaris.h100644 001750 001750 0000000003614775415623 0020676xustar0030 atime=1744182234.663891844 openssh-10.0p1/openbsd-compat/port-solaris.h010064400017500001750000000024221477541562300172610ustar00djmdjm/* * Copyright (c) 2006 Chad Mynhier. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _PORT_SOLARIS_H #include #include 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_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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-uw.c100644 001750 001750 0000000003614775415623 0017650xustar0030 atime=1744182234.663891844 openssh-10.0p1/openbsd-compat/port-uw.c010064400017500001750000000102451477541562300162350ustar00djmdjm/* * Copyright (c) 2005 The SCO Group. All rights reserved. * Copyright (c) 2005 Tim Rice. 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(HAVE_LIBIAF) && !defined(HAVE_SECUREWARE) #include #ifdef HAVE_CRYPT_H # include #endif #include #include #include #include #include #include "xmalloc.h" #include "packet.h" #include "auth-options.h" #include "log.h" #include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ #include "servconf.h" #include "hostfile.h" #include "auth.h" #include "ssh.h" #include "ssh_api.h" int nischeck(char *); int sys_auth_passwd(struct ssh *ssh, const char *password) { Authctxt *authctxt = ssh->authctxt; struct passwd *pw = authctxt->pw; char *salt; int result; /* 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. */ salt = (pw_password[0] && pw_password[1]) ? pw_password : "xx"; /* * Authentication is accepted if the encrypted passwords * are identical. */ #ifdef UNIXWARE_LONG_PASSWORDS if (!nischeck(pw->pw_name)) { result = ((strcmp(bigcrypt(password, salt), pw_password) == 0) || (strcmp(osr5bigcrypt(password, salt), pw_password) == 0)); } else #endif /* UNIXWARE_LONG_PASSWORDS */ result = (strcmp(xcrypt(password, salt), pw_password) == 0); #ifdef USE_LIBIAF if (authctxt->valid) free(pw_password); #endif return(result); } #ifdef UNIXWARE_LONG_PASSWORDS int nischeck(char *namep) { char password_file[] = "/etc/passwd"; FILE *fd; struct passwd *ent = NULL; if ((fd = fopen (password_file, "r")) == NULL) { /* * 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. */ return(0); } /* * fgetpwent() only reads from password file, so we know for certain * that the user is local. */ while (ent = fgetpwent(fd)) { if (strcmp (ent->pw_name, namep) == 0) { /* Local user */ fclose (fd); return(0); } } fclose (fd); return (1); } #endif /* UNIXWARE_LONG_PASSWORDS */ /* NOTE: ia_get_logpwd() allocates memory for arg 2 functions that call shadow_pw() will need to free */ #ifdef USE_LIBIAF char * get_iaf_password(struct passwd *pw) { char *pw_password = NULL; uinfo_t uinfo; if (!ia_openinfo(pw->pw_name,&uinfo)) { ia_get_logpwd(uinfo, &pw_password); if (pw_password == NULL) fatal("ia_get_logpwd: Unable to get the shadow passwd"); ia_closeinfo(uinfo); return pw_password; } else fatal("ia_openinfo: Unable to open the shadow passwd file"); } #endif /* USE_LIBIAF */ #endif /* HAVE_LIBIAF and not HAVE_SECUREWARE */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/port-uw.h100644 001750 001750 0000000003614775415623 0017655xustar0030 atime=1744182234.663891844 openssh-10.0p1/openbsd-compat/port-uw.h010064400017500001750000000025751477541562300162510ustar00djmdjm/* * Copyright (c) 2005 Tim Rice. 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 USE_LIBIAF char * get_iaf_password(struct passwd *pw); #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/pwcache.c100644 001750 001750 0000000003614775415623 0017645xustar0030 atime=1744182234.663891844 openssh-10.0p1/openbsd-compat/pwcache.c010064400017500001750000000063641477541562300162410ustar00djmdjm/* $OpenBSD: pwcache.c,v 1.9 2005/08/08 08:05:34 espie Exp $ */ /* * Copyright (c) 1989, 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. */ /* OPENBSD ORIGINAL: lib/libc/gen/pwcache.c */ #include "includes.h" #include #include #include #include #include #include #define NCACHE 64 /* power of 2 */ #define MASK (NCACHE - 1) /* bits to store with */ #ifndef HAVE_USER_FROM_UID char * user_from_uid(uid_t uid, int nouser) { static struct ncache { uid_t uid; char *name; } c_uid[NCACHE]; static int pwopen; static char nbuf[15]; /* 32 bits == 10 digits */ struct passwd *pw; struct ncache *cp; cp = c_uid + (uid & MASK); if (cp->uid != uid || cp->name == NULL) { if (pwopen == 0) { #ifdef HAVE_SETPASSENT setpassent(1); #endif pwopen = 1; } if ((pw = getpwuid(uid)) == NULL) { if (nouser) return (NULL); (void)snprintf(nbuf, sizeof(nbuf), "%lu", (u_long)uid); } cp->uid = uid; if (cp->name != NULL) free(cp->name); cp->name = strdup(pw ? pw->pw_name : nbuf); } return (cp->name); } #endif #ifndef HAVE_GROUP_FROM_GID char * group_from_gid(gid_t gid, int nogroup) { static struct ncache { gid_t gid; char *name; } c_gid[NCACHE]; static int gropen; static char nbuf[15]; /* 32 bits == 10 digits */ struct group *gr; struct ncache *cp; cp = c_gid + (gid & MASK); if (cp->gid != gid || cp->name == NULL) { if (gropen == 0) { #ifdef HAVE_SETGROUPENT setgroupent(1); #endif gropen = 1; } if ((gr = getgrgid(gid)) == NULL) { if (nogroup) return (NULL); (void)snprintf(nbuf, sizeof(nbuf), "%lu", (u_long)gid); } cp->gid = gid; if (cp->name != NULL) free(cp->name); cp->name = strdup(gr ? gr->gr_name : nbuf); } return (cp->name); } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/readpassphrase.c100644 001750 001750 0000000003614775415623 0021240xustar0030 atime=1744182234.663891844 openssh-10.0p1/openbsd-compat/readpassphrase.c010064400017500001750000000134561477541562300176340ustar00djmdjm/* $OpenBSD: readpassphrase.c,v 1.26 2016/10/18 12:47:18 millert Exp $ */ /* * Copyright (c) 2000-2002, 2007, 2010 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * 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 #include #include #include #include #include #include #include #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 */ #if !defined(_POSIX_VDISABLE) && defined(VDISABLE) # define _POSIX_VDISABLE VDISABLE #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; } /* * 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. */ 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); 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); /* Restore old terminal settings and signals. */ if (memcmp(&term, &oterm, sizeof(term)) != 0) { 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); (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); } DEF_WEAK(readpassphrase); #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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/readpassphrase.h100644 001750 001750 0000000003614775415623 0021245xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/readpassphrase.h010064400017500001750000000034031477541562300176300ustar00djmdjm/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */ /* * Copyright (c) 2000, 2002 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * 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: include/readpassphrase.h */ #ifndef _READPASSPHRASE_H_ #define _READPASSPHRASE_H_ #include "includes.h" #ifndef HAVE_READPASSPHRASE #define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ #define RPP_ECHO_ON 0x01 /* Leave echo on. */ #define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ #define RPP_FORCELOWER 0x04 /* Force input to lower case. */ #define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ #define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ #define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ char * readpassphrase(const char *, char *, size_t, int); #endif /* HAVE_READPASSPHRASE */ #endif /* !_READPASSPHRASE_H_ */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/reallocarray.c100644 001750 001750 0000000003614775415623 0020713xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/reallocarray.c010064400017500001750000000027641477541562300173070ustar00djmdjm/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */ /* * Copyright (c) 2008 Otto Moerbeek * * 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/reallocarray.c */ #include "includes.h" #ifndef HAVE_REALLOCARRAY #include #include #ifdef HAVE_STDINT_H #include #endif #include /* * 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 * reallocarray(void *optr, size_t nmemb, size_t size) { if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) { errno = ENOMEM; return NULL; } return realloc(optr, size * nmemb); } #endif /* HAVE_REALLOCARRAY */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/recallocarray.c100644 001750 001750 0000000003614775415623 0021056xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/recallocarray.c010064400017500001750000000046341477541562300174500ustar00djmdjm/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */ /* * Copyright (c) 2008, 2017 Otto Moerbeek * * 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 #include #ifdef HAVE_STDINT_H #include #endif #include #include /* * 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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/regress040755 001750 001750 0000000003614775415623 0017472xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/regress004075500017500001750000000000001477541562300160505ustar00djmdjmopenssh-10.0p1/openbsd-compat/regress/PaxHeaders.10889/Makefile.in100644 001750 001750 0000000003614775415623 0021606xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/regress/Makefile.in010064400017500001750000000016271477541562300201770ustar00djmdjmsysconfdir=@sysconfdir@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ VPATH=@srcdir@ CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ CPPFLAGS=-I. -I.. -I../.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../.. @CPPFLAGS@ @DEFS@ EXEEXT=@EXEEXT@ LIBCOMPAT=../libopenbsd-compat.a LIBSSH=../../libssh.a LIBS=@LIBS@ @CHANNELLIBS@ LDFLAGS=@LDFLAGS@ $(LIBCOMPAT) TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \ strtonumtest$(EXEEXT) opensslvertest$(EXEEXT) utimensattest$(EXEEXT) all: t-exec ${OTHERTESTS} .c: $(LIBCOMPAT) $(LIBSSH) $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBSSH) $(LIBS) t-exec: $(TESTPROGS) @echo running compat regress tests @for TEST in ""$?; do \ echo "run test $${TEST}" ... 1>&2; \ ./$${TEST}$(EXEEXT) || exit $$? ; \ done @echo finished compat regress tests clean: rm -f *.o *.a core $(TESTPROGS) valid.out distclean: clean rm -f Makefile *~ openssh-10.0p1/openbsd-compat/regress/PaxHeaders.10889/closefromtest.c100644 001750 001750 0000000003614775415623 0022576xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/regress/closefromtest.c010064400017500001750000000032151477541562300211620ustar00djmdjm/* * Copyright (c) 2006 Darren Tucker * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #define NUM_OPENS 10 void fail(char *msg) { fprintf(stderr, "closefrom: %s\n", msg); exit(1); } int main(void) { int i, max, fds[NUM_OPENS]; char buf[512]; for (i = 0; i < NUM_OPENS; i++) if ((fds[i] = open("/dev/null", O_RDONLY)) == -1) exit(0); /* can't test */ max = i - 1; /* should close last fd only */ closefrom(fds[max]); if (close(fds[max]) != -1) fail("failed to close highest fd"); /* make sure we can still use remaining descriptors */ for (i = 0; i < max; i++) if (read(fds[i], buf, sizeof(buf)) == -1) fail("closed descriptors it should not have"); /* should close all fds */ closefrom(fds[0]); for (i = 0; i < NUM_OPENS; i++) if (close(fds[i]) != -1) fail("failed to close from lowest fd"); return 0; } openssh-10.0p1/openbsd-compat/regress/PaxHeaders.10889/opensslvertest.c100644 001750 001750 0000000003614775415623 0023005xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/regress/opensslvertest.c010064400017500001750000000062301477541562300213710ustar00djmdjm/* * Copyright (c) 2014 Darren Tucker * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include int ssh_compatible_openssl(long, long); struct version_test { long headerver; long libver; int result; } version_tests[] = { /* built with 1.0.1b release headers */ { 0x1000101fL, 0x1000101fL, 1},/* exact match */ { 0x1000101fL, 0x1000102fL, 1}, /* newer library patch version: ok */ { 0x1000101fL, 0x1000100fL, 1}, /* older library patch version: ok */ { 0x1000101fL, 0x1000201fL, 1}, /* newer library fix version: ok */ { 0x1000101fL, 0x1000001fL, 0}, /* older library fix version: NO */ { 0x1000101fL, 0x1010101fL, 0}, /* newer library minor version: NO */ { 0x1000101fL, 0x0000101fL, 0}, /* older library major version: NO */ { 0x1000101fL, 0x2000101fL, 0}, /* newer library major version: NO */ /* built with 1.1.1b release headers */ { 0x1010101fL, 0x1010101fL, 1},/* exact match */ { 0x1010101fL, 0x1010102fL, 1}, /* newer library patch version: ok */ { 0x1010101fL, 0x1010100fL, 1}, /* older library patch version: ok */ { 0x1010101fL, 0x1010201fL, 1}, /* newer library fix version: ok */ { 0x1010101fL, 0x1010001fL, 0}, /* older library fix version: NO */ { 0x1010101fL, 0x1020001fL, 0}, /* newer library minor version: NO */ { 0x1010101fL, 0x0010101fL, 0}, /* older library major version: NO */ { 0x1010101fL, 0x2010101fL, 0}, /* newer library major version: NO */ /* built with 3.0.1 release headers */ { 0x3010101fL, 0x3010101fL, 1},/* exact match */ { 0x3010101fL, 0x3010102fL, 1}, /* newer library patch version: ok */ { 0x3010101fL, 0x3010100fL, 1}, /* older library patch version: ok */ { 0x3010101fL, 0x3010201fL, 1}, /* newer library fix version: ok */ { 0x3010101fL, 0x3010001fL, 1}, /* older library fix version: ok */ { 0x3010101fL, 0x3020001fL, 1}, /* newer library minor version: ok */ { 0x3010101fL, 0x1010101fL, 0}, /* older library major version: NO */ { 0x3010101fL, 0x4010101fL, 0}, /* newer library major version: NO */ }; void fail(long hver, long lver, int result) { fprintf(stderr, "opensslver: header %lx library %lx != %d \n", hver, lver, result); exit(1); } int main(void) { #ifdef WITH_OPENSSL unsigned int i; int res; long hver, lver; for (i = 0; i < sizeof(version_tests) / sizeof(version_tests[0]); i++) { hver = version_tests[i].headerver; lver = version_tests[i].libver; res = version_tests[i].result; if (ssh_compatible_openssl(hver, lver) != res) fail(hver, lver, res); } #endif exit(0); } openssh-10.0p1/openbsd-compat/regress/PaxHeaders.10889/snprintftest.c100644 001750 001750 0000000003614775415623 0022450xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/regress/snprintftest.c010064400017500001750000000037701477541562300210420ustar00djmdjm/* * Copyright (c) 2005 Darren Tucker * Copyright (c) 2005 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #define BUFSZ 2048 #include "includes.h" #include #include #include #include #include static int failed = 0; static void fail(const char *m) { fprintf(stderr, "snprintftest: %s\n", m); failed = 1; } 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(void) { char b[5]; char *src = NULL; int ret; memset(b, 'X', sizeof(b)); ret = snprintf(b, 5, "123456789"); if (ret != 9 || b[4] != '\0') fail("snprintf does not correctly terminate long strings"); /* check for read overrun on unterminated string */ if ((src = malloc(BUFSZ)) == NULL) { fail("malloc failed"); } else { memset(src, 'a', BUFSZ); snprintf(b, sizeof(b), "%.*s", 1, src); if (strcmp(b, "a") != 0) fail("failed with length limit '%%.s'"); } /* check that snprintf and vsnprintf return sane values */ if (snprintf(b, 1, "%s %d", "hello", 12345) != 11) fail("snprintf does not return required length"); if (x_snprintf(b, 1, "%s %d", "hello", 12345) != 11) fail("vsnprintf does not return required length"); free(src); return failed; } openssh-10.0p1/openbsd-compat/regress/PaxHeaders.10889/strduptest.c100644 001750 001750 0000000003614775415623 0022126xustar0030 atime=1744182234.664868812 openssh-10.0p1/openbsd-compat/regress/strduptest.c010064400017500001750000000021241477541562300205100ustar00djmdjm/* * Copyright (c) 2005 Darren Tucker * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include static int fail = 0; void test(const char *a) { char *b; b = strdup(a); if (b == 0) { fail = 1; return; } if (strcmp(a, b) != 0) fail = 1; free(b); } int main(void) { test(""); test("a"); test("\0"); test("abcdefghijklmnopqrstuvwxyz"); return fail; } openssh-10.0p1/openbsd-compat/regress/PaxHeaders.10889/strtonumtest.c100644 001750 001750 0000000003614775415623 0022500xustar0030 atime=1744182234.665845239 openssh-10.0p1/openbsd-compat/regress/strtonumtest.c010064400017500001750000000047211477541562300210670ustar00djmdjm/* $OpenBSD: strtonumtest.c,v 1.1 2004/08/03 20:38:36 otto Exp $ */ /* * Copyright (c) 2004 Otto Moerbeek * * 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: regress/lib/libc/strtonum/strtonumtest.c */ #include "includes.h" #include #include #include /* LLONG_MAX is known as LONGLONG_MAX on AIX */ #if defined(LONGLONG_MAX) && !defined(LLONG_MAX) # define LLONG_MAX LONGLONG_MAX # define LLONG_MIN LONGLONG_MIN #endif /* LLONG_MAX is known as LONG_LONG_MAX on HP-UX */ #if defined(LONG_LONG_MAX) && !defined(LLONG_MAX) # define LLONG_MAX LONG_LONG_MAX # define LLONG_MIN LONG_LONG_MIN #endif long long strtonum(const char *, long long, long long, const char **); int fail; void test(const char *p, long long lb, long long ub, int ok) { long long val; const char *q; val = strtonum(p, lb, ub, &q); if (ok && q != NULL) { fprintf(stderr, "%s [%lld-%lld] ", p, lb, ub); fprintf(stderr, "NUMBER NOT ACCEPTED %s\n", q); fail = 1; } else if (!ok && q == NULL) { fprintf(stderr, "%s [%lld-%lld] %lld ", p, lb, ub, val); fprintf(stderr, "NUMBER ACCEPTED\n"); fail = 1; } } int main(void) { test("1", 0, 10, 1); test("0", -2, 5, 1); test("0", 2, 5, 0); test("0", 2, LLONG_MAX, 0); test("-2", 0, LLONG_MAX, 0); test("0", -5, LLONG_MAX, 1); test("-3", -3, LLONG_MAX, 1); test("-9223372036854775808", LLONG_MIN, LLONG_MAX, 1); test("9223372036854775807", LLONG_MIN, LLONG_MAX, 1); test("-9223372036854775809", LLONG_MIN, LLONG_MAX, 0); test("9223372036854775808", LLONG_MIN, LLONG_MAX, 0); test("1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0); test("-1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0); test("-2", 10, -1, 0); test("-2", -10, -1, 1); test("-20", -10, -1, 0); test("20", -10, -1, 0); return (fail); } openssh-10.0p1/openbsd-compat/regress/PaxHeaders.10889/utimensattest.c100644 001750 001750 0000000003614775415623 0022616xustar0030 atime=1744182234.665845239 openssh-10.0p1/openbsd-compat/regress/utimensattest.c010064400017500001750000000062661477541562300212130ustar00djmdjm/* * 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 "includes.h" #include #include #include #include #include #include #include #include #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); } openssh-10.0p1/openbsd-compat/PaxHeaders.10889/rresvport.c100644 001750 001750 0000000003614775415623 0020301xustar0030 atime=1744182234.665845239 openssh-10.0p1/openbsd-compat/rresvport.c010064400017500001750000000057441477541562300166760ustar00djmdjm/* $OpenBSD: rresvport.c,v 1.9 2005/11/10 10:00:17 espie Exp $ */ /* * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved. * Copyright (c) 1983, 1993, 1994 * 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. */ /* OPENBSD ORIGINAL: lib/libc/net/rresvport.c */ #include "includes.h" #ifndef HAVE_RRESVPORT_AF #include #include #include #include #include #include #include #include #if 0 int rresvport(int *alport) { return rresvport_af(alport, AF_INET); } #endif int rresvport_af(int *alport, sa_family_t af) { struct sockaddr_storage ss; struct sockaddr *sa; u_int16_t *portp; int s; socklen_t salen; memset(&ss, '\0', sizeof ss); sa = (struct sockaddr *)&ss; switch (af) { case AF_INET: salen = sizeof(struct sockaddr_in); portp = &((struct sockaddr_in *)sa)->sin_port; break; case AF_INET6: salen = sizeof(struct sockaddr_in6); portp = &((struct sockaddr_in6 *)sa)->sin6_port; break; default: errno = EPFNOSUPPORT; return (-1); } sa->sa_family = af; s = socket(af, SOCK_STREAM, 0); if (s < 0) return (-1); *portp = htons(*alport); if (*alport < IPPORT_RESERVED - 1) { if (bind(s, sa, salen) >= 0) return (s); if (errno != EADDRINUSE) { (void)close(s); return (-1); } } *portp = 0; sa->sa_family = af; if (bindresvport_sa(s, sa) == -1) { (void)close(s); return (-1); } *alport = ntohs(*portp); return (s); } #endif /* HAVE_RRESVPORT_AF */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/setenv.c100644 001750 001750 0000000003614775415623 0017537xustar0030 atime=1744182234.665845239 openssh-10.0p1/openbsd-compat/setenv.c010064400017500001750000000134471477541562300161330ustar00djmdjm/* $OpenBSD: setenv.c,v 1.13 2010/08/23 22:31:50 millert Exp $ */ /* * Copyright (c) 1987 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. */ /* OPENBSD ORIGINAL: lib/libc/stdlib/setenv.c */ #include "includes.h" #if !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) #include #include #include extern char **environ; #ifndef HAVE_SETENV static char **lastenv; /* last value of environ */ #endif /* OpenSSH Portable: __findenv is from getenv.c rev 1.8, made static */ /* * __findenv -- * Returns pointer to value associated with name, if any, else NULL. * Starts searching within the environmental array at offset. * Sets offset to be the offset of the name/value combination in the * environmental array, for use by putenv(3), setenv(3) and unsetenv(3). * Explicitly removes '=' in argument name. * * This routine *should* be a static; don't use it. */ static char * __findenv(const char *name, int len, int *offset) { extern char **environ; int i; const char *np; char **p, *cp; if (name == NULL || environ == NULL) return (NULL); for (p = environ + *offset; (cp = *p) != NULL; ++p) { for (np = name, i = len; i && *cp; i--) if (*cp++ != *np++) break; if (i == 0 && *cp++ == '=') { *offset = p - environ; return (cp); } } return (NULL); } #if 0 /* nothing uses putenv */ /* * putenv -- * Add a name=value string directly to the environmental, replacing * any current value. */ int putenv(char *str) { char **P, *cp; size_t cnt; int offset = 0; for (cp = str; *cp && *cp != '='; ++cp) ; if (*cp != '=') { errno = EINVAL; return (-1); /* missing `=' in string */ } if (__findenv(str, (int)(cp - str), &offset) != NULL) { environ[offset++] = str; /* could be set multiple times */ while (__findenv(str, (int)(cp - str), &offset)) { for (P = &environ[offset];; ++P) if (!(*P = *(P + 1))) break; } return (0); } /* create new slot for string */ for (P = environ; *P != NULL; P++) ; cnt = P - environ; P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); if (!P) return (-1); if (lastenv != environ) memcpy(P, environ, cnt * sizeof(char *)); lastenv = environ = P; environ[cnt] = str; environ[cnt + 1] = NULL; return (0); } #endif #ifndef HAVE_SETENV /* * setenv -- * Set the value of the environmental variable "name" to be * "value". If rewrite is set, replace any current value. */ int setenv(const char *name, const char *value, int rewrite) { char *C, **P; const char *np; int l_value, offset = 0; for (np = name; *np && *np != '='; ++np) ; #ifdef notyet if (*np) { errno = EINVAL; return (-1); /* has `=' in name */ } #endif l_value = strlen(value); if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { int tmpoff = offset + 1; if (!rewrite) return (0); #if 0 /* XXX - existing entry may not be writable */ if (strlen(C) >= l_value) { /* old larger; copy over */ while ((*C++ = *value++)) ; return (0); } #endif /* could be set multiple times */ while (__findenv(name, (int)(np - name), &tmpoff)) { for (P = &environ[tmpoff];; ++P) if (!(*P = *(P + 1))) break; } } else { /* create new slot */ size_t cnt; for (P = environ; *P != NULL; P++) ; cnt = P - environ; P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); if (!P) return (-1); if (lastenv != environ) memcpy(P, environ, cnt * sizeof(char *)); lastenv = environ = P; offset = cnt; environ[cnt + 1] = NULL; } if (!(environ[offset] = /* name + `=' + value */ malloc((size_t)((int)(np - name) + l_value + 2)))) return (-1); for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) ; for (*C++ = '='; (*C++ = *value++); ) ; return (0); } #endif /* HAVE_SETENV */ #ifndef HAVE_UNSETENV /* * unsetenv(name) -- * Delete environmental variable "name". */ int unsetenv(const char *name) { char **P; const char *np; int offset = 0; if (!name || !*name) { errno = EINVAL; return (-1); } for (np = name; *np && *np != '='; ++np) ; if (*np) { errno = EINVAL; return (-1); /* has `=' in name */ } /* could be set multiple times */ while (__findenv(name, (int)(np - name), &offset)) { for (P = &environ[offset];; ++P) if (!(*P = *(P + 1))) break; } return (0); } #endif /* HAVE_UNSETENV */ #endif /* !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/setproctitle.c100644 001750 001750 0000000003614775415623 0020754xustar0030 atime=1744182234.665845239 openssh-10.0p1/openbsd-compat/setproctitle.c010064400017500001750000000111021477541562300173320ustar00djmdjm/* Based on conf.c from UCB sendmail 8.8.8 */ /* * Copyright 2003 Damien Miller * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 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. */ #include "includes.h" #ifndef HAVE_SETPROCTITLE #include #include #include #include #ifdef HAVE_SYS_PSTAT_H #include #endif #include #include #define SPT_NONE 0 /* don't use it at all */ #define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */ #define SPT_REUSEARGV 2 /* cover argv with title information */ #ifndef SPT_TYPE # define SPT_TYPE SPT_NONE #endif #ifndef SPT_PADCHAR # define SPT_PADCHAR '\0' #endif #if SPT_TYPE == SPT_REUSEARGV static char *argv_start = NULL; static size_t argv_env_len = 0; #endif #endif /* HAVE_SETPROCTITLE */ void compat_init_setproctitle(int argc, char *argv[]) { #if !defined(HAVE_SETPROCTITLE) && \ defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV extern char **environ; char *lastargv = NULL; char **envp = environ; int i; /* * 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 * programs. Beware. */ if (argc == 0 || argv[0] == NULL) return; /* Fail if we can't allocate room for the new environment */ for (i = 0; envp[i] != NULL; i++) ; if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) { environ = envp; /* put it back */ return; } /* * Find the last argv string or environment variable within * our process memory area. */ for (i = 0; i < argc; i++) { if (lastargv == NULL || lastargv + 1 == argv[i]) lastargv = argv[i] + strlen(argv[i]); } for (i = 0; envp[i] != NULL; i++) { if (lastargv + 1 == envp[i]) lastargv = envp[i] + strlen(envp[i]); } argv[1] = NULL; argv_start = argv[0]; argv_env_len = lastargv - argv[0] - 1; /* * Copy environment * XXX - will truncate env on strdup fail */ for (i = 0; envp[i] != NULL; i++) environ[i] = strdup(envp[i]); environ[i] = NULL; #endif /* SPT_REUSEARGV */ } #ifndef HAVE_SETPROCTITLE void setproctitle(const char *fmt, ...) { #if SPT_TYPE != SPT_NONE va_list ap; char buf[1024], ptitle[1024]; size_t len = 0; int r; extern char *__progname; #if SPT_TYPE == SPT_PSTAT union pstun pst; #endif #if SPT_TYPE == SPT_REUSEARGV if (argv_env_len <= 0) return; #endif strlcpy(buf, __progname, sizeof(buf)); r = -1; va_start(ap, fmt); if (fmt != NULL) { len = strlcat(buf, ": ", sizeof(buf)); if (len < sizeof(buf)) r = vsnprintf(buf + len, sizeof(buf) - len , fmt, ap); } va_end(ap); if (r == -1 || (size_t)r >= sizeof(buf) - len) return; strnvis(ptitle, buf, sizeof(ptitle), VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL); #if SPT_TYPE == SPT_PSTAT pst.pst_command = ptitle; pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0); #elif SPT_TYPE == SPT_REUSEARGV /* 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++) argv_start[len] = SPT_PADCHAR; #endif #endif /* SPT_NONE */ } #endif /* HAVE_SETPROCTITLE */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sha1.c100644 001750 001750 0000000003614775415623 0017067xustar0030 atime=1744182234.665845239 openssh-10.0p1/openbsd-compat/sha1.c010064400017500001750000000124621477541562300154570ustar00djmdjm/* $OpenBSD: sha1.c,v 1.27 2019/06/07 22:56:36 dtucker Exp $ */ /* * SHA-1 in C * By Steve Reid * 100% Public Domain * * Test Vectors (from FIPS PUB 180-1) * "abc" * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 * A million repetitions of "a" * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ #include "includes.h" #ifndef WITH_OPENSSL #include #include #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* * blk0() and blk() perform the initial expand. * I got the idea of expanding during the round function from SSLeay */ #if BYTE_ORDER == LITTLE_ENDIAN # define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ |(rol(block->l[i],8)&0x00FF00FF)) #else # define blk0(i) block->l[i] #endif #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ^block->l[(i+2)&15]^block->l[i&15],1)) /* * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); typedef union { u_int8_t c[64]; u_int32_t l[16]; } CHAR64LONG16; /* * Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1Transform(u_int32_t state[5], const u_int8_t buffer[SHA1_BLOCK_LENGTH]) { u_int32_t a, b, c, d, e; u_int8_t workspace[SHA1_BLOCK_LENGTH]; CHAR64LONG16 *block = (CHAR64LONG16 *)workspace; (void)memcpy(block, buffer, SHA1_BLOCK_LENGTH); /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; } DEF_WEAK(SHA1Transform); /* * SHA1Init - Initialize new context */ void SHA1Init(SHA1_CTX *context) { /* SHA1 initialization constants */ context->count = 0; context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; } DEF_WEAK(SHA1Init); /* * Run your data through this. */ void 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 += ((u_int64_t)len << 3); if ((j + len) > 63) { (void)memcpy(&context->buffer[j], data, (i = 64-j)); SHA1Transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64) SHA1Transform(context->state, (u_int8_t *)&data[i]); j = 0; } else { i = 0; } (void)memcpy(&context->buffer[j], &data[i], len - i); } DEF_WEAK(SHA1Update); /* * Add padding and return the message digest. */ void SHA1Pad(SHA1_CTX *context) { u_int8_t finalcount[8]; u_int i; for (i = 0; i < 8; i++) { finalcount[i] = (u_int8_t)((context->count >> ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ } SHA1Update(context, (u_int8_t *)"\200", 1); while ((context->count & 504) != 448) 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) { u_int i; SHA1Pad(context); for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { digest[i] = (u_int8_t) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } explicit_bzero(context, sizeof(*context)); } DEF_WEAK(SHA1Final); #endif /* !WITH_OPENSSL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sha1.h100644 001750 001750 0000000003614775415623 0017074xustar0030 atime=1744182234.666821856 openssh-10.0p1/openbsd-compat/sha1.h010064400017500001750000000043561477541562300154670ustar00djmdjm/* $OpenBSD: sha1.h,v 1.24 2012/12/05 23:19:57 deraadt Exp $ */ /* * SHA-1 in C * By Steve Reid * 100% Public Domain */ #ifndef _SHA1_H #define _SHA1_H #ifndef WITH_OPENSSL #define SHA1_BLOCK_LENGTH 64 #define SHA1_DIGEST_LENGTH 20 #define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) typedef struct { u_int32_t state[5]; u_int64_t count; u_int8_t buffer[SHA1_BLOCK_LENGTH]; } SHA1_CTX; void SHA1Init(SHA1_CTX *); void SHA1Pad(SHA1_CTX *); void SHA1Transform(u_int32_t [5], const u_int8_t [SHA1_BLOCK_LENGTH]) __attribute__((__bounded__(__minbytes__,1,5))) __attribute__((__bounded__(__minbytes__,2,SHA1_BLOCK_LENGTH))); void SHA1Update(SHA1_CTX *, const u_int8_t *, size_t) __attribute__((__bounded__(__string__,2,3))); void SHA1Final(u_int8_t [SHA1_DIGEST_LENGTH], SHA1_CTX *) __attribute__((__bounded__(__minbytes__,1,SHA1_DIGEST_LENGTH))); char *SHA1End(SHA1_CTX *, char *) __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); char *SHA1File(const char *, char *) __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); char *SHA1FileChunk(const char *, char *, off_t, off_t) __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); char *SHA1Data(const u_int8_t *, size_t, char *) __attribute__((__bounded__(__string__,1,2))) __attribute__((__bounded__(__minbytes__,3,SHA1_DIGEST_STRING_LENGTH))); #define HTONDIGEST(x) do { \ x[0] = htonl(x[0]); \ x[1] = htonl(x[1]); \ x[2] = htonl(x[2]); \ x[3] = htonl(x[3]); \ x[4] = htonl(x[4]); } while (0) #define NTOHDIGEST(x) do { \ x[0] = ntohl(x[0]); \ x[1] = ntohl(x[1]); \ x[2] = ntohl(x[2]); \ x[3] = ntohl(x[3]); \ x[4] = ntohl(x[4]); } while (0) #endif /* !WITH_OPENSSL */ #endif /* _SHA1_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sha2.c100644 001750 001750 0000000003614775415623 0017070xustar0030 atime=1744182234.666821856 openssh-10.0p1/openbsd-compat/sha2.c010064400017500001750000000673451477541562300154720ustar00djmdjm/* $OpenBSD: sha2.c,v 1.28 2019/07/23 12:35:22 dtucker Exp $ */ /* * FILE: sha2.c * AUTHOR: Aaron D. Gifford * * Copyright (c) 2000-2001, Aaron D. Gifford * 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 copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) 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. * * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ */ /* OPENBSD ORIGINAL: lib/libc/hash/sha2.c */ #include "includes.h" #if !defined(HAVE_SHA256UPDATE) || !defined(HAVE_SHA384UPDATE) || \ !defined(HAVE_SHA512UPDATE) /* no-op out, similar to DEF_WEAK but only needed here */ #define MAKE_CLONE(x, y) void __ssh_compat_make_clone_##x_##y(void) #include #include "openbsd-compat/sha2.h" /* * UNROLLED TRANSFORM LOOP NOTE: * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform * loop version for the hash transform rounds (defined using macros * later in this file). Either define on the command line, for example: * * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c * * or define below: * * #define SHA2_UNROLL_TRANSFORM * */ #ifndef SHA2_SMALL #if defined(__amd64__) || defined(__i386__) #define SHA2_UNROLL_TRANSFORM #endif #endif /*** 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 * equivalent. * * If your system does not define the above, then you can do so by * hand like this: * * #define LITTLE_ENDIAN 1234 * #define BIG_ENDIAN 4321 * * And for little-endian machines, add: * * #define BYTE_ORDER LITTLE_ENDIAN * * Or for big-endian machines: * * #define BYTE_ORDER BIG_ENDIAN * * The FreeBSD machine this was written on defines BYTE_ORDER * appropriately by including (which in turn includes * where the appropriate definitions are actually * made). */ #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN #endif /*** 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) /*** ENDIAN SPECIFIC COPY MACROS **************************************/ #define BE_8_TO_32(dst, cp) do { \ (dst) = (u_int32_t)(cp)[3] | ((u_int32_t)(cp)[2] << 8) | \ ((u_int32_t)(cp)[1] << 16) | ((u_int32_t)(cp)[0] << 24); \ } while(0) #define BE_8_TO_64(dst, cp) do { \ (dst) = (u_int64_t)(cp)[7] | ((u_int64_t)(cp)[6] << 8) | \ ((u_int64_t)(cp)[5] << 16) | ((u_int64_t)(cp)[4] << 24) | \ ((u_int64_t)(cp)[3] << 32) | ((u_int64_t)(cp)[2] << 40) | \ ((u_int64_t)(cp)[1] << 48) | ((u_int64_t)(cp)[0] << 56); \ } while (0) #define BE_64_TO_8(cp, src) do { \ (cp)[0] = (src) >> 56; \ (cp)[1] = (src) >> 48; \ (cp)[2] = (src) >> 40; \ (cp)[3] = (src) >> 32; \ (cp)[4] = (src) >> 24; \ (cp)[5] = (src) >> 16; \ (cp)[6] = (src) >> 8; \ (cp)[7] = (src); \ } while (0) #define BE_32_TO_8(cp, src) do { \ (cp)[0] = (src) >> 24; \ (cp)[1] = (src) >> 16; \ (cp)[2] = (src) >> 8; \ (cp)[3] = (src); \ } while (0) /* * Macro for incrementally adding the unsigned 64-bit integer n to the * unsigned 128-bit integer (represented using a two-element array of * 64-bit words): */ #define ADDINC128(w,n) do { \ (w)[0] += (u_int64_t)(n); \ if ((w)[0] < (n)) { \ (w)[1]++; \ } \ } while (0) /*** THE SIX LOGICAL FUNCTIONS ****************************************/ /* * 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-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-224, SHA-256, SHA-384, and SHA-512): */ #define R(b,x) ((x) >> (b)) /* 32-bit Rotate-right (used in SHA-224 and SHA-256): */ #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) /* 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-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))) #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) /* Four of six logical functions used in SHA-384 and SHA-512: */ #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ /* 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, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; /* Initial hash value H for SHA-256: */ static const u_int32_t sha256_initial_hash_value[8] = { 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL }; /* Hash constant words K for SHA-384 and SHA-512: */ static const u_int64_t K512[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 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 */ static const u_int64_t sha384_initial_hash_value[8] = { 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL }; #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 SHA256Init(SHA2_CTX *context) { memcpy(context->state.st32, sha256_initial_hash_value, sizeof(sha256_initial_hash_value)); memset(context->buffer, 0, sizeof(context->buffer)); context->bitcount[0] = 0; } DEF_WEAK(SHA256Init); #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-256 round macros: */ #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do { \ BE_8_TO_32(W256[j], data); \ data += 4; \ T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \ (d) += T1; \ (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) #define ROUND256(a,b,c,d,e,f,g,h) do { \ s0 = W256[(j+1)&0x0f]; \ s0 = sigma0_256(s0); \ s1 = W256[(j+14)&0x0f]; \ s1 = sigma1_256(s1); \ T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + \ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) void 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]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { /* Rounds 0 to 15 (unrolled): */ ROUND256_0_TO_15(a,b,c,d,e,f,g,h); ROUND256_0_TO_15(h,a,b,c,d,e,f,g); ROUND256_0_TO_15(g,h,a,b,c,d,e,f); ROUND256_0_TO_15(f,g,h,a,b,c,d,e); ROUND256_0_TO_15(e,f,g,h,a,b,c,d); ROUND256_0_TO_15(d,e,f,g,h,a,b,c); ROUND256_0_TO_15(c,d,e,f,g,h,a,b); ROUND256_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds up to 63: */ do { ROUND256(a,b,c,d,e,f,g,h); ROUND256(h,a,b,c,d,e,f,g); ROUND256(g,h,a,b,c,d,e,f); ROUND256(f,g,h,a,b,c,d,e); ROUND256(e,f,g,h,a,b,c,d); ROUND256(d,e,f,g,h,a,b,c); ROUND256(c,d,e,f,g,h,a,b); ROUND256(b,c,d,e,f,g,h,a); } while (j < 64); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void 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]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { BE_8_TO_32(W256[j], data); data += 4; /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W256[(j+1)&0x0f]; s0 = sigma0_256(s0); s1 = W256[(j+14)&0x0f]; s1 = sigma1_256(s1); /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 64); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ DEF_WEAK(SHA256Transform); void SHA256Update(SHA2_CTX *context, const u_int8_t *data, size_t len) { u_int64_t freespace, usedspace; /* Calling with no data is valid (we do nothing) */ if (len == 0) return; 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; if (len >= freespace) { /* Fill the buffer completely and process it */ memcpy(&context->buffer[usedspace], data, freespace); context->bitcount[0] += freespace << 3; len -= freespace; data += freespace; SHA256Transform(context->state.st32, context->buffer); } else { /* The buffer is not yet full */ memcpy(&context->buffer[usedspace], data, len); context->bitcount[0] += (u_int64_t)len << 3; /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA256_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ 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[0] += len << 3; } /* Clean up: */ usedspace = freespace = 0; } DEF_WEAK(SHA256Update); void SHA256Pad(SHA2_CTX *context) { unsigned int usedspace; usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH; if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA256_BLOCK_LENGTH) { memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA256Transform(context->state.st32, context->buffer); /* Prepare for last transform: */ memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); } } else { /* Set-up for the last transform: */ memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Store the length of input data (in bits) in big endian format: */ BE_64_TO_8(&context->buffer[SHA256_SHORT_BLOCK_LENGTH], context->bitcount[0]); /* Final transform: */ SHA256Transform(context->state.st32, context->buffer); /* Clean up: */ usedspace = 0; } DEF_WEAK(SHA256Pad); void SHA256Final(u_int8_t digest[SHA256_DIGEST_LENGTH], SHA2_CTX *context) { SHA256Pad(context); #if BYTE_ORDER == LITTLE_ENDIAN int 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.st32, SHA256_DIGEST_LENGTH); #endif explicit_bzero(context, sizeof(*context)); } DEF_WEAK(SHA256Final); /*** SHA-512: *********************************************************/ void SHA512Init(SHA2_CTX *context) { 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 /* Unrolled SHA-512 round macros: */ #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do { \ BE_8_TO_64(W512[j], data); \ data += 8; \ T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \ (d) += T1; \ (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) #define ROUND512(a,b,c,d,e,f,g,h) do { \ s0 = W512[(j+1)&0x0f]; \ s0 = sigma0_512(s0); \ s1 = W512[(j+14)&0x0f]; \ s1 = sigma1_512(s1); \ T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + \ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) void 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]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { /* Rounds 0 to 15 (unrolled): */ ROUND512_0_TO_15(a,b,c,d,e,f,g,h); ROUND512_0_TO_15(h,a,b,c,d,e,f,g); ROUND512_0_TO_15(g,h,a,b,c,d,e,f); ROUND512_0_TO_15(f,g,h,a,b,c,d,e); ROUND512_0_TO_15(e,f,g,h,a,b,c,d); ROUND512_0_TO_15(d,e,f,g,h,a,b,c); ROUND512_0_TO_15(c,d,e,f,g,h,a,b); ROUND512_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds up to 79: */ do { ROUND512(a,b,c,d,e,f,g,h); ROUND512(h,a,b,c,d,e,f,g); ROUND512(g,h,a,b,c,d,e,f); ROUND512(f,g,h,a,b,c,d,e); ROUND512(e,f,g,h,a,b,c,d); ROUND512(d,e,f,g,h,a,b,c); ROUND512(c,d,e,f,g,h,a,b); ROUND512(b,c,d,e,f,g,h,a); } while (j < 80); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void 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]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { BE_8_TO_64(W512[j], data); data += 8; /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W512[(j+1)&0x0f]; s0 = sigma0_512(s0); s1 = W512[(j+14)&0x0f]; s1 = sigma1_512(s1); /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 80); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ DEF_WEAK(SHA512Transform); void SHA512Update(SHA2_CTX *context, const u_int8_t *data, size_t len) { size_t freespace, usedspace; /* Calling with no data is valid (we do nothing) */ if (len == 0) return; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA512_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ memcpy(&context->buffer[usedspace], data, freespace); ADDINC128(context->bitcount, freespace << 3); len -= freespace; data += freespace; SHA512Transform(context->state.st64, context->buffer); } else { /* The buffer is not yet full */ memcpy(&context->buffer[usedspace], data, len); ADDINC128(context->bitcount, len << 3); /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA512_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA512Transform(context->state.st64, data); ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); len -= SHA512_BLOCK_LENGTH; data += SHA512_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ memcpy(context->buffer, data, len); ADDINC128(context->bitcount, len << 3); } /* Clean up: */ usedspace = freespace = 0; } DEF_WEAK(SHA512Update); void SHA512Pad(SHA2_CTX *context) { unsigned int usedspace; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA512_BLOCK_LENGTH) { memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA512Transform(context->state.st64, context->buffer); /* And set-up for the last transform: */ memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2); } } else { /* Prepare for final transform: */ memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Store the length of input data (in bits) in big endian format: */ BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH], context->bitcount[1]); BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH + 8], context->bitcount[0]); /* Final transform: */ SHA512Transform(context->state.st64, context->buffer); /* Clean up: */ usedspace = 0; } DEF_WEAK(SHA512Pad); void SHA512Final(u_int8_t digest[SHA512_DIGEST_LENGTH], SHA2_CTX *context) { SHA512Pad(context); #if BYTE_ORDER == LITTLE_ENDIAN int 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.st64, SHA512_DIGEST_LENGTH); #endif explicit_bzero(context, sizeof(*context)); } DEF_WEAK(SHA512Final); #if !defined(SHA2_SMALL) /*** SHA-384: *********************************************************/ void SHA384Init(SHA2_CTX *context) { 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); 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 SHA384Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH]) { SHA512Transform(state, data); } void SHA384Update(SHA2_CTX *context, const u_int8_t *data, size_t len) { SHA512Update(context, data, len); } void SHA384Pad(SHA2_CTX *context) { SHA512Pad(context); } void SHA384Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA2_CTX *context) { SHA384Pad(context); #if BYTE_ORDER == LITTLE_ENDIAN int 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.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 */ explicit_bzero(context, sizeof(*context)); } DEF_WEAK(SHA512_256Final); #endif /* !defined(SHA2_SMALL) */ #endif /* 0 */ #endif /* HAVE_SHA{256,384,512}UPDATE */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sha2.h100644 001750 001750 0000000003614775415623 0017075xustar0030 atime=1744182234.667797622 openssh-10.0p1/openbsd-compat/sha2.h010064400017500001750000000172311477541562300154640ustar00djmdjm/* $OpenBSD: sha2.h,v 1.10 2016/09/03 17:00:29 tedu Exp $ */ /* * FILE: sha2.h * AUTHOR: Aaron D. Gifford * * Copyright (c) 2000-2001, Aaron D. Gifford * 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 copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) 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. * * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ */ /* OPENBSD ORIGINAL: include/sha2.h */ #ifndef _SSHSHA2_H #define _SSHSHA2_H #include "includes.h" #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) #define SHA384_BLOCK_LENGTH 128 #define SHA384_DIGEST_LENGTH 48 #define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) #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-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]; } SHA2_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 */ #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 SHA256Pad(SHA2_CTX *); void SHA256Final(u_int8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *) __attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH))); char *SHA256End(SHA2_CTX *, char *) __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); char *SHA256File(const char *, char *) __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); char *SHA256FileChunk(const char *, char *, off_t, off_t) __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); 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 */ #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 SHA384Pad(SHA2_CTX *); void SHA384Final(u_int8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *) __attribute__((__bounded__(__minbytes__,1,SHA384_DIGEST_LENGTH))); char *SHA384End(SHA2_CTX *, char *) __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); char *SHA384File(const char *, char *) __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); char *SHA384FileChunk(const char *, char *, off_t, off_t) __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); 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 */ #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 SHA512Pad(SHA2_CTX *); void SHA512Final(u_int8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *) __attribute__((__bounded__(__minbytes__,1,SHA512_DIGEST_LENGTH))); char *SHA512End(SHA2_CTX *, char *) __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); char *SHA512File(const char *, char *) __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); char *SHA512FileChunk(const char *, char *, off_t, off_t) __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); 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 /* HAVE_SHA{256,384,512}UPDATE */ #endif /* _SSHSHA2_H */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sigact.c100644 001750 001750 0000000003614775415623 0017505xustar0030 atime=1744182234.667797622 openssh-10.0p1/openbsd-compat/sigact.c010064400017500001750000000075131477541562300160760ustar00djmdjm/* $OpenBSD: sigaction.c,v 1.4 2001/01/22 18:01:48 millert Exp $ */ /**************************************************************************** * Copyright (c) 1998,2000 Free Software Foundation, Inc. * * * * 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, distribute with modifications, 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 ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * * * Except as contained in this notice, the name(s) of the above copyright * * holders shall not be used in advertising or otherwise to promote the * * sale, use or other dealings in this Software without prior written * * authorization. * ****************************************************************************/ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * ****************************************************************************/ /* OPENBSD ORIGINAL: lib/libcurses/base/sigaction.c */ #include "includes.h" #include #include #include "sigact.h" /* This file provides sigaction() emulation using sigvec() */ /* Use only if this is non POSIX system */ #if !HAVE_SIGACTION && HAVE_SIGVEC int sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact) { return sigvec(sig, sigact ? &sigact->sv : NULL, osigact ? &osigact->sv : NULL); } int sigemptyset (sigset_t *mask) { if (!mask) { errno = EINVAL; return -1; } *mask = 0; return 0; } int sigprocmask (int mode, sigset_t *mask, sigset_t *omask) { sigset_t current = sigsetmask(0); if (!mask) { errno = EINVAL; return -1; } if (omask) *omask = current; if (mode == SIG_BLOCK) current |= *mask; else if (mode == SIG_UNBLOCK) current &= ~*mask; else if (mode == SIG_SETMASK) current = *mask; sigsetmask(current); return 0; } int sigsuspend (sigset_t *mask) { if (!mask) { errno = EINVAL; return -1; } return sigpause(*mask); } int sigdelset (sigset_t *mask, int sig) { if (!mask) { errno = EINVAL; return -1; } *mask &= ~sigmask(sig); return 0; } int sigaddset (sigset_t *mask, int sig) { if (!mask) { errno = EINVAL; return -1; } *mask |= sigmask(sig); return 0; } int sigismember (sigset_t *mask, int sig) { if (!mask) { errno = EINVAL; return -1; } return (*mask & sigmask(sig)) != 0; } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sigact.h100644 001750 001750 0000000003614775415623 0017512xustar0030 atime=1744182234.667797622 openssh-10.0p1/openbsd-compat/sigact.h010064400017500001750000000072501477541562300161010ustar00djmdjm/* $OpenBSD: SigAction.h,v 1.3 2001/01/22 18:01:32 millert Exp $ */ /**************************************************************************** * Copyright (c) 1998,2000 Free Software Foundation, Inc. * * * * 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, distribute with modifications, 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 ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * * * Except as contained in this notice, the name(s) of the above copyright * * holders shall not be used in advertising or otherwise to promote the * * sale, use or other dealings in this Software without prior written * * authorization. * ****************************************************************************/ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * ****************************************************************************/ /* * $From: SigAction.h,v 1.6 2000/12/10 02:36:10 tom Exp $ * * This file exists to handle non-POSIX systems which don't have , * and usually no sigaction() nor */ /* OPENBSD ORIGINAL: lib/libcurses/SigAction.h */ #ifndef _SIGACTION_H #define _SIGACTION_H #if !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) #undef SIG_BLOCK #define SIG_BLOCK 00 #undef SIG_UNBLOCK #define SIG_UNBLOCK 01 #undef SIG_SETMASK #define SIG_SETMASK 02 /* * is in the Linux 1.2.8 + gcc 2.7.0 configuration, * and is useful for testing this header file. */ #if HAVE_BSD_SIGNAL_H # include #endif struct sigaction { struct sigvec sv; }; typedef unsigned long sigset_t; #undef sa_mask #define sa_mask sv.sv_mask #undef sa_handler #define sa_handler sv.sv_handler #undef sa_flags #define sa_flags sv.sv_flags int sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact); int sigprocmask (int how, sigset_t *mask, sigset_t *omask); int sigemptyset (sigset_t *mask); int sigsuspend (sigset_t *mask); int sigdelset (sigset_t *mask, int sig); int sigaddset (sigset_t *mask, int sig); #endif /* !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) */ #endif /* !defined(_SIGACTION_H) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strcasestr.c100644 001750 001750 0000000003614775415623 0020430xustar0030 atime=1744182234.667797622 openssh-10.0p1/openbsd-compat/strcasestr.c010064400017500001750000000045531477541562300170220ustar00djmdjm/* $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 #include /* * 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 openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strlcat.c100644 001750 001750 0000000003614775415623 0017707xustar0030 atime=1744182234.667797622 openssh-10.0p1/openbsd-compat/strlcat.c010064400017500001750000000034161477541562300162760ustar00djmdjm/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */ #include "includes.h" #ifndef HAVE_STRLCAT #include #include /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ } #endif /* !HAVE_STRLCAT */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strlcpy.c100644 001750 001750 0000000003614775415623 0017733xustar0030 atime=1744182234.667797622 openssh-10.0p1/openbsd-compat/strlcpy.c010064400017500001750000000032241477541562300163170ustar00djmdjm/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ #include "includes.h" #ifndef HAVE_STRLCPY #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0) { while (--n != 0) { if ((*d++ = *s++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif /* !HAVE_STRLCPY */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strmode.c100644 001750 001750 0000000003614775415623 0017710xustar0030 atime=1744182234.667797622 openssh-10.0p1/openbsd-compat/strmode.c010064400017500001750000000066031477541562300163000ustar00djmdjm/* $OpenBSD: strmode.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */ /*- * Copyright (c) 1990 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. */ /* OPENBSD ORIGINAL: lib/libc/string/strmode.c */ #include "includes.h" #ifndef HAVE_STRMODE #include #include #include /* XXX mode should be mode_t */ void strmode(int mode, char *p) { /* print type */ switch (mode & S_IFMT) { case S_IFDIR: /* directory */ *p++ = 'd'; break; case S_IFCHR: /* character special */ *p++ = 'c'; break; case S_IFBLK: /* block special */ *p++ = 'b'; break; case S_IFREG: /* regular */ *p++ = '-'; break; case S_IFLNK: /* symbolic link */ *p++ = 'l'; break; #ifdef S_IFSOCK case S_IFSOCK: /* socket */ *p++ = 's'; break; #endif #ifdef S_IFIFO case S_IFIFO: /* fifo */ *p++ = 'p'; break; #endif default: /* unknown */ *p++ = '?'; break; } /* usr */ if (mode & S_IRUSR) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWUSR) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXUSR | S_ISUID)) { case 0: *p++ = '-'; break; case S_IXUSR: *p++ = 'x'; break; case S_ISUID: *p++ = 'S'; break; case S_IXUSR | S_ISUID: *p++ = 's'; break; } /* group */ if (mode & S_IRGRP) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWGRP) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXGRP | S_ISGID)) { case 0: *p++ = '-'; break; case S_IXGRP: *p++ = 'x'; break; case S_ISGID: *p++ = 'S'; break; case S_IXGRP | S_ISGID: *p++ = 's'; break; } /* other */ if (mode & S_IROTH) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWOTH) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXOTH | S_ISVTX)) { case 0: *p++ = '-'; break; case S_IXOTH: *p++ = 'x'; break; case S_ISVTX: *p++ = 'T'; break; case S_IXOTH | S_ISVTX: *p++ = 't'; break; } *p++ = ' '; /* will be a '+' if ACL's implemented */ *p = '\0'; } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strndup.c100644 001750 001750 0000000003614775415623 0017732xustar0030 atime=1744182234.668775021 openssh-10.0p1/openbsd-compat/strndup.c010064400017500001750000000024241477541562300163170ustar00djmdjm/* $OpenBSD: strndup.c,v 1.2 2015/08/31 02:53:57 guenther Exp $ */ /* * Copyright (c) 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #if !defined(HAVE_STRNDUP) || defined(BROKEN_STRNDUP) #include #include #include #include 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 */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strnlen.c100644 001750 001750 0000000003614775415623 0017720xustar0030 atime=1744182234.668775021 openssh-10.0p1/openbsd-compat/strnlen.c010064400017500001750000000022721477541562300163060ustar00djmdjm/* $OpenBSD: strnlen.c,v 1.3 2010/06/02 12:58:12 millert Exp $ */ /* * Copyright (c) 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* OPENBSD ORIGINAL: lib/libc/string/strnlen.c */ #include "includes.h" #if !defined(HAVE_STRNLEN) || defined(BROKEN_STRNLEN) #include #include size_t strnlen(const char *str, size_t maxlen) { const char *cp; for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--) ; return (size_t)(cp - str); } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strptime.c100644 001750 001750 0000000003614775415623 0020102xustar0030 atime=1744182234.668775021 openssh-10.0p1/openbsd-compat/strptime.c010064400017500001750000000224411477541562300164700ustar00djmdjm/* $OpenBSD: strptime.c,v 1.12 2008/06/26 05:42:05 ray Exp $ */ /* $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code was contributed to The NetBSD Foundation by Klaus Klein. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* OPENBSD ORIGINAL: lib/libc/time/strptime.c */ #include "includes.h" #ifndef HAVE_STRPTIME #define TM_YEAR_BASE 1900 /* from tzfile.h */ #include #include #include #include /* #define _ctloc(x) (_CurrentTimeLocale->x) */ /* * We do not implement alternate representations. However, we always * check whether a given modifier is allowed for a certain conversion. */ #define _ALT_E 0x01 #define _ALT_O 0x02 #define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } static int _conv_num(const unsigned char **, int *, int, int); static char *_strptime(const char *, const char *, struct tm *, int); char * strptime(const char *buf, const char *fmt, struct tm *tm) { return(_strptime(buf, fmt, tm, 1)); } static char * _strptime(const char *buf, const char *fmt, struct tm *tm, int initialize) { unsigned char c; const unsigned char *bp; size_t len; int alt_format, i; static int century, relyear; if (initialize) { century = TM_YEAR_BASE; relyear = -1; } bp = (unsigned char *)buf; while ((c = *fmt) != '\0') { /* Clear `alternate' modifier prior to new conversion. */ alt_format = 0; /* Eat up white-space. */ if (isspace(c)) { while (isspace(*bp)) bp++; fmt++; continue; } if ((c = *fmt++) != '%') goto literal; again: switch (c = *fmt++) { case '%': /* "%%" is converted to "%". */ literal: if (c != *bp++) return (NULL); break; /* * "Alternative" modifiers. Just set the appropriate flag * and start over again. */ case 'E': /* "%E?" alternative conversion modifier. */ _LEGAL_ALT(0); alt_format |= _ALT_E; goto again; case 'O': /* "%O?" alternative conversion modifier. */ _LEGAL_ALT(0); alt_format |= _ALT_O; goto again; /* * "Complex" conversion rules, implemented through recursion. */ #if 0 case 'c': /* Date and time, using the locale's format. */ _LEGAL_ALT(_ALT_E); if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0))) return (NULL); break; #endif case 'D': /* The date as "%m/%d/%y". */ _LEGAL_ALT(0); if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0))) return (NULL); break; case 'R': /* The time as "%H:%M". */ _LEGAL_ALT(0); if (!(bp = _strptime(bp, "%H:%M", tm, 0))) return (NULL); break; case 'r': /* The time as "%I:%M:%S %p". */ _LEGAL_ALT(0); if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0))) return (NULL); break; case 'T': /* The time as "%H:%M:%S". */ _LEGAL_ALT(0); if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0))) return (NULL); break; #if 0 case 'X': /* The time, using the locale's format. */ _LEGAL_ALT(_ALT_E); if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0))) return (NULL); break; case 'x': /* The date, using the locale's format. */ _LEGAL_ALT(_ALT_E); if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0))) return (NULL); break; #endif /* * "Elementary" conversion rules. */ #if 0 case 'A': /* The day of week, using the locale's form. */ case 'a': _LEGAL_ALT(0); for (i = 0; i < 7; i++) { /* Full name. */ len = strlen(_ctloc(day[i])); if (strncasecmp(_ctloc(day[i]), bp, len) == 0) break; /* Abbreviated name. */ len = strlen(_ctloc(abday[i])); if (strncasecmp(_ctloc(abday[i]), bp, len) == 0) break; } /* Nothing matched. */ if (i == 7) return (NULL); tm->tm_wday = i; bp += len; break; case 'B': /* The month, using the locale's form. */ case 'b': case 'h': _LEGAL_ALT(0); for (i = 0; i < 12; i++) { /* Full name. */ len = strlen(_ctloc(mon[i])); if (strncasecmp(_ctloc(mon[i]), bp, len) == 0) break; /* Abbreviated name. */ len = strlen(_ctloc(abmon[i])); if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0) break; } /* Nothing matched. */ if (i == 12) return (NULL); tm->tm_mon = i; bp += len; break; #endif case 'C': /* The century number. */ _LEGAL_ALT(_ALT_E); if (!(_conv_num(&bp, &i, 0, 99))) return (NULL); century = i * 100; break; case 'd': /* The day of month. */ case 'e': _LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_mday, 1, 31))) return (NULL); break; case 'k': /* The hour (24-hour clock representation). */ _LEGAL_ALT(0); /* FALLTHROUGH */ case 'H': _LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_hour, 0, 23))) return (NULL); break; case 'l': /* The hour (12-hour clock representation). */ _LEGAL_ALT(0); /* FALLTHROUGH */ case 'I': _LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_hour, 1, 12))) return (NULL); break; case 'j': /* The day of year. */ _LEGAL_ALT(0); if (!(_conv_num(&bp, &tm->tm_yday, 1, 366))) return (NULL); tm->tm_yday--; break; case 'M': /* The minute. */ _LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_min, 0, 59))) return (NULL); break; case 'm': /* The month. */ _LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_mon, 1, 12))) return (NULL); tm->tm_mon--; break; #if 0 case 'p': /* The locale's equivalent of AM/PM. */ _LEGAL_ALT(0); /* AM? */ len = strlen(_ctloc(am_pm[0])); if (strncasecmp(_ctloc(am_pm[0]), bp, len) == 0) { if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */ return (NULL); else if (tm->tm_hour == 12) tm->tm_hour = 0; bp += len; break; } /* PM? */ len = strlen(_ctloc(am_pm[1])); if (strncasecmp(_ctloc(am_pm[1]), bp, len) == 0) { if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */ return (NULL); else if (tm->tm_hour < 12) tm->tm_hour += 12; bp += len; break; } /* Nothing matched. */ return (NULL); #endif case 'S': /* The seconds. */ _LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_sec, 0, 61))) return (NULL); break; case 'U': /* The week of year, beginning on sunday. */ case 'W': /* The week of year, beginning on monday. */ _LEGAL_ALT(_ALT_O); /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ if (!(_conv_num(&bp, &i, 0, 53))) return (NULL); break; case 'w': /* The day of week, beginning on sunday. */ _LEGAL_ALT(_ALT_O); if (!(_conv_num(&bp, &tm->tm_wday, 0, 6))) return (NULL); break; case 'Y': /* The year. */ _LEGAL_ALT(_ALT_E); if (!(_conv_num(&bp, &i, 0, 9999))) return (NULL); relyear = -1; tm->tm_year = i - TM_YEAR_BASE; break; case 'y': /* The year within the century (2 digits). */ _LEGAL_ALT(_ALT_E | _ALT_O); if (!(_conv_num(&bp, &relyear, 0, 99))) return (NULL); break; /* * Miscellaneous conversions. */ case 'n': /* Any kind of white-space. */ case 't': _LEGAL_ALT(0); while (isspace(*bp)) bp++; break; default: /* Unknown/unsupported conversion. */ return (NULL); } } /* * We need to evaluate the two digit year spec (%y) * last as we can get a century spec (%C) at any time. */ if (relyear != -1) { if (century == TM_YEAR_BASE) { if (relyear <= 68) tm->tm_year = relyear + 2000 - TM_YEAR_BASE; else tm->tm_year = relyear + 1900 - TM_YEAR_BASE; } else { tm->tm_year = relyear + century - TM_YEAR_BASE; } } return ((char *)bp); } static int _conv_num(const unsigned char **buf, int *dest, int llim, int ulim) { int result = 0; int rulim = ulim; if (**buf < '0' || **buf > '9') return (0); /* we use rulim to break out of the loop when we run out of digits */ do { result *= 10; result += *(*buf)++ - '0'; rulim /= 10; } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); if (result < llim || result > ulim) return (0); *dest = result; return (1); } #endif /* HAVE_STRPTIME */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strsep.c100644 001750 001750 0000000003614775415623 0017553xustar0030 atime=1744182234.668775021 openssh-10.0p1/openbsd-compat/strsep.c010064400017500001750000000051351477541562300161420ustar00djmdjm/* $OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */ /*- * Copyright (c) 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: * 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/strsep.c */ #include "includes.h" #if !defined(HAVE_STRSEP) #include #include /* * Get next token from string *stringp, where tokens are possibly-empty * strings separated by characters from delim. * * Writes NULs into the string at *stringp to end tokens. * delim need not remain constant from call to call. * On return, *stringp points past the last NUL written (if there might * be further tokens), or is NULL (if there are definitely no more tokens). * * If *stringp is NULL, strsep returns NULL. */ char * strsep(char **stringp, const char *delim) { char *s; const char *spanp; int c, sc; char *tok; if ((s = *stringp) == NULL) return (NULL); for (tok = s;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *stringp = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } #endif /* !defined(HAVE_STRSEP) */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strtoll.c100644 001750 001750 0000000003614775415623 0017736xustar0030 atime=1744182234.668775021 openssh-10.0p1/openbsd-compat/strtoll.c010064400017500001750000000104461477541562300163260ustar00djmdjm/* $OpenBSD: strtoll.c,v 1.6 2005/11/10 10:00:17 espie Exp $ */ /*- * Copyright (c) 1992 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. */ /* OPENBSD ORIGINAL: lib/libc/stdlib/strtoll.c */ #include "includes.h" #ifndef HAVE_STRTOLL #include #include #include #include #include /* * Convert a string to a long long. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */ long long strtoll(const char *nptr, char **endptr, int base) { const char *s; long long acc, cutoff; int c; int neg, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ s = nptr; do { c = (unsigned char) *s++; } while (isspace(c)); if (c == '-') { neg = 1; c = *s++; } else { neg = 0; if (c == '+') c = *s++; } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for long longs is * [-9223372036854775808..9223372036854775807] and the input base * is 10, cutoff will be set to 922337203685477580 and cutlim to * either 7 (neg==0) or 8 (neg==1), meaning that if we have * accumulated a value > 922337203685477580, or equal but the * next digit is > 7 (or 8), the number is too big, and we will * return a range error. * * Set any if any `digits' consumed; make it negative to indicate * overflow. */ cutoff = neg ? LLONG_MIN : LLONG_MAX; cutlim = cutoff % base; cutoff /= base; if (neg) { if (cutlim > 0) { cutlim -= base; cutoff += 1; } cutlim = -cutlim; } for (acc = 0, any = 0;; c = (unsigned char) *s++) { if (isdigit(c)) c -= '0'; else if (isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0) continue; if (neg) { if (acc < cutoff || (acc == cutoff && c > cutlim)) { any = -1; acc = LLONG_MIN; errno = ERANGE; } else { any = 1; acc *= base; acc -= c; } } else { if (acc > cutoff || (acc == cutoff && c > cutlim)) { any = -1; acc = LLONG_MAX; errno = ERANGE; } else { any = 1; acc *= base; acc += c; } } } if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return (acc); } #endif /* HAVE_STRTOLL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strtonum.c100644 001750 001750 0000000003614775415623 0020126xustar0030 atime=1744182234.669751317 openssh-10.0p1/openbsd-compat/strtonum.c010064400017500001750000000035441477541562300165170ustar00djmdjm/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */ /* * Copyright (c) 2004 Ted Unangst and Todd Miller * 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. */ /* OPENBSD ORIGINAL: lib/libc/stdlib/strtonum.c */ #include "includes.h" #ifndef HAVE_STRTONUM #include #include #include #define INVALID 1 #define TOOSMALL 2 #define TOOLARGE 3 long long strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp) { long long ll = 0; char *ep; int error = 0; struct errval { const char *errstr; int err; } ev[4] = { { NULL, 0 }, { "invalid", EINVAL }, { "too small", ERANGE }, { "too large", ERANGE }, }; ev[0].err = errno; errno = 0; if (minval > maxval) error = INVALID; else { ll = strtoll(numstr, &ep, 10); if (numstr == ep || *ep != '\0') error = INVALID; else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) error = TOOSMALL; else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) error = TOOLARGE; } if (errstrp != NULL) *errstrp = ev[error].errstr; errno = ev[error].err; if (error) ll = 0; return (ll); } #endif /* HAVE_STRTONUM */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strtoul.c100644 001750 001750 0000000003614775415623 0017747xustar0030 atime=1744182234.669751317 openssh-10.0p1/openbsd-compat/strtoul.c010064400017500001750000000061071477541562300163360ustar00djmdjm/* $OpenBSD: strtoul.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */ /* * Copyright (c) 1990 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. */ /* OPENBSD ORIGINAL: lib/libc/stdlib/strtoul.c */ #include "includes.h" #ifndef HAVE_STRTOUL #include #include #include #include /* * Convert a string to an unsigned long integer. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */ unsigned long strtoul(const char *nptr, char **endptr, int base) { const char *s; unsigned long acc, cutoff; int c; int neg, any, cutlim; /* * See strtol for comments as to the logic used. */ s = nptr; do { c = (unsigned char) *s++; } while (isspace(c)); if (c == '-') { neg = 1; c = *s++; } else { neg = 0; if (c == '+') c = *s++; } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; cutoff = ULONG_MAX / (unsigned long)base; cutlim = ULONG_MAX % (unsigned long)base; for (acc = 0, any = 0;; c = (unsigned char) *s++) { if (isdigit(c)) c -= '0'; else if (isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0) continue; if (acc > cutoff || acc == cutoff && c > cutlim) { any = -1; acc = ULONG_MAX; errno = ERANGE; } else { any = 1; acc *= (unsigned long)base; acc += c; } } if (neg && any > 0) acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return (acc); } #endif /* !HAVE_STRTOUL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/strtoull.c100644 001750 001750 0000000003614775415623 0020123xustar0030 atime=1744182234.669751317 openssh-10.0p1/openbsd-compat/strtoull.c010064400017500001750000000062051477541562300165110ustar00djmdjm/* $OpenBSD: strtoull.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */ /*- * Copyright (c) 1992 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. */ /* OPENBSD ORIGINAL: lib/libc/stdlib/strtoull.c */ #include "includes.h" #ifndef HAVE_STRTOULL #include #include #include #include #include /* * Convert a string to an unsigned long long. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */ unsigned long long strtoull(const char *nptr, char **endptr, int base) { const char *s; unsigned long long acc, cutoff; int c; int neg, any, cutlim; /* * See strtoq for comments as to the logic used. */ s = nptr; do { c = (unsigned char) *s++; } while (isspace(c)); if (c == '-') { neg = 1; c = *s++; } else { neg = 0; if (c == '+') c = *s++; } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; cutoff = ULLONG_MAX / (unsigned long long)base; cutlim = ULLONG_MAX % (unsigned long long)base; for (acc = 0, any = 0;; c = (unsigned char) *s++) { if (isdigit(c)) c -= '0'; else if (isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0) continue; if (acc > cutoff || (acc == cutoff && c > cutlim)) { any = -1; acc = ULLONG_MAX; errno = ERANGE; } else { any = 1; acc *= (unsigned long long)base; acc += c; } } if (neg && any > 0) acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return (acc); } #endif /* !HAVE_STRTOULL */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sys-queue.h100644 001750 001750 0000000003614775415623 0020200xustar0030 atime=1744182234.669751317 openssh-10.0p1/openbsd-compat/sys-queue.h010064400017500001750000000477511477541562300166010ustar00djmdjm/* $OpenBSD: queue.h,v 1.45 2018/07/12 14:22:54 sashan Exp $ */ /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ /* * Copyright (c) 1991, 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. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ /* OPENBSD ORIGINAL: sys/sys/queue.h */ #ifndef _FAKE_QUEUE_H_ #define _FAKE_QUEUE_H_ /* * Require for OS/X and other platforms that have old/broken/incomplete * . */ #undef CIRCLEQ_EMPTY #undef CIRCLEQ_END #undef CIRCLEQ_ENTRY #undef CIRCLEQ_FIRST #undef CIRCLEQ_FOREACH #undef CIRCLEQ_FOREACH_REVERSE #undef CIRCLEQ_HEAD #undef CIRCLEQ_HEAD_INITIALIZER #undef CIRCLEQ_INIT #undef CIRCLEQ_INSERT_AFTER #undef CIRCLEQ_INSERT_BEFORE #undef CIRCLEQ_INSERT_HEAD #undef CIRCLEQ_INSERT_TAIL #undef CIRCLEQ_LAST #undef CIRCLEQ_NEXT #undef CIRCLEQ_PREV #undef CIRCLEQ_REMOVE #undef CIRCLEQ_REPLACE #undef LIST_EMPTY #undef LIST_END #undef LIST_ENTRY #undef LIST_FIRST #undef LIST_FOREACH #undef LIST_FOREACH_SAFE #undef LIST_HEAD #undef LIST_HEAD_INITIALIZER #undef LIST_INIT #undef LIST_INSERT_AFTER #undef LIST_INSERT_BEFORE #undef LIST_INSERT_HEAD #undef LIST_NEXT #undef LIST_REMOVE #undef LIST_REPLACE #undef SIMPLEQ_CONCAT #undef SIMPLEQ_EMPTY #undef SIMPLEQ_END #undef SIMPLEQ_ENTRY #undef SIMPLEQ_FIRST #undef SIMPLEQ_FOREACH #undef SIMPLEQ_FOREACH_SAFE #undef SIMPLEQ_HEAD #undef SIMPLEQ_HEAD_INITIALIZER #undef SIMPLEQ_INIT #undef SIMPLEQ_INSERT_AFTER #undef SIMPLEQ_INSERT_HEAD #undef SIMPLEQ_INSERT_TAIL #undef SIMPLEQ_NEXT #undef SIMPLEQ_REMOVE_AFTER #undef SIMPLEQ_REMOVE_HEAD #undef SLIST_EMPTY #undef SLIST_END #undef SLIST_ENTRY #undef SLIST_FIRST #undef SLIST_FOREACH #undef SLIST_FOREACH_PREVPTR #undef SLIST_FOREACH_SAFE #undef SLIST_HEAD #undef SLIST_HEAD_INITIALIZER #undef SLIST_INIT #undef SLIST_INSERT_AFTER #undef SLIST_INSERT_HEAD #undef SLIST_NEXT #undef SLIST_REMOVE #undef SLIST_REMOVE_AFTER #undef SLIST_REMOVE_HEAD #undef SLIST_REMOVE_NEXT #undef TAILQ_CONCAT #undef TAILQ_EMPTY #undef TAILQ_END #undef TAILQ_ENTRY #undef TAILQ_FIRST #undef TAILQ_FOREACH #undef TAILQ_FOREACH_REVERSE #undef TAILQ_FOREACH_REVERSE_SAFE #undef TAILQ_FOREACH_SAFE #undef TAILQ_HEAD #undef TAILQ_HEAD_INITIALIZER #undef TAILQ_INIT #undef TAILQ_INSERT_AFTER #undef TAILQ_INSERT_BEFORE #undef TAILQ_INSERT_HEAD #undef TAILQ_INSERT_TAIL #undef TAILQ_LAST #undef TAILQ_NEXT #undef TAILQ_PREV #undef TAILQ_REMOVE #undef TAILQ_REPLACE /* * This file defines five types of data structures: singly-linked lists, * lists, simple queues, tail queues and XOR simple queues. * * * A singly-linked list is headed by a single forward pointer. The elements * are singly linked for minimum space and pointer manipulation overhead at * the expense of O(n) removal for arbitrary elements. New elements can be * added to the list after an existing element or at the head of the list. * Elements being removed from the head of the list should use the explicit * macro for this purpose for optimum efficiency. A singly-linked list may * only be traversed in the forward direction. Singly-linked lists are ideal * for applications with large datasets and few or no removals or for * implementing a LIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A simple queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are singly * linked to save space, so elements can only be removed from the * head of the list. New elements can be added to the list before or after * an existing element, at the head of the list, or at the end of the * list. A simple queue may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * An XOR simple queue is used in the same way as a regular simple queue. * The difference is that the head structure also includes a "cookie" that * is XOR'd with the queue pointer (first, last or next) to generate the * real pointer value. * * For details on the use of these macros, see the queue(3) manual page. */ #if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) #define _Q_INVALID ((void *)-1) #define _Q_INVALIDATE(a) (a) = _Q_INVALID #else #define _Q_INVALIDATE(a) #endif /* * Singly-linked List definitions. */ #define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define SLIST_HEAD_INITIALIZER(head) \ { NULL } #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } /* * Singly-linked List access methods. */ #define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_END(head) NULL #define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define SLIST_FOREACH(var, head, field) \ for((var) = SLIST_FIRST(head); \ (var) != SLIST_END(head); \ (var) = SLIST_NEXT(var, field)) #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST(head); \ (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ (var) = (tvar)) /* * Singly-linked List functions. */ #define SLIST_INIT(head) { \ SLIST_FIRST(head) = SLIST_END(head); \ } #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (0) #define SLIST_REMOVE_AFTER(elm, field) do { \ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ } while (0) #define SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (0) #define SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->slh_first; \ \ while (curelm->field.sle_next != (elm)) \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ } \ _Q_INVALIDATE((elm)->field.sle_next); \ } while (0) /* * List definitions. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List access methods. */ #define LIST_FIRST(head) ((head)->lh_first) #define LIST_END(head) NULL #define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) #define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_FOREACH(var, head, field) \ for((var) = LIST_FIRST(head); \ (var)!= LIST_END(head); \ (var) = LIST_NEXT(var, field)) #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST(head); \ (var) && ((tvar) = LIST_NEXT(var, field), 1); \ (var) = (tvar)) /* * List functions. */ #define LIST_INIT(head) do { \ LIST_FIRST(head) = LIST_END(head); \ } while (0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (0) #define LIST_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (0) #define LIST_REMOVE(elm, field) do { \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ _Q_INVALIDATE((elm)->field.le_prev); \ _Q_INVALIDATE((elm)->field.le_next); \ } while (0) #define LIST_REPLACE(elm, elm2, field) do { \ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ (elm2)->field.le_next->field.le_prev = \ &(elm2)->field.le_next; \ (elm2)->field.le_prev = (elm)->field.le_prev; \ *(elm2)->field.le_prev = (elm2); \ _Q_INVALIDATE((elm)->field.le_prev); \ _Q_INVALIDATE((elm)->field.le_next); \ } while (0) /* * Simple queue definitions. */ #define SIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqh_first; /* first element */ \ struct type **sqh_last; /* addr of last next element */ \ } #define SIMPLEQ_HEAD_INITIALIZER(head) \ { NULL, &(head).sqh_first } #define SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ } /* * Simple queue access methods. */ #define SIMPLEQ_FIRST(head) ((head)->sqh_first) #define SIMPLEQ_END(head) NULL #define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) #define SIMPLEQ_FOREACH(var, head, field) \ for((var) = SIMPLEQ_FIRST(head); \ (var) != SIMPLEQ_END(head); \ (var) = SIMPLEQ_NEXT(var, field)) #define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SIMPLEQ_FIRST(head); \ (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ (var) = (tvar)) /* * Simple queue functions. */ #define SIMPLEQ_INIT(head) do { \ (head)->sqh_first = NULL; \ (head)->sqh_last = &(head)->sqh_first; \ } while (0) #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ (head)->sqh_first = (elm); \ } while (0) #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ *(head)->sqh_last = (elm); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (0) #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ (head)->sqh_last = &(elm)->field.sqe_next; \ (listelm)->field.sqe_next = (elm); \ } while (0) #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ (head)->sqh_last = &(head)->sqh_first; \ } while (0) #define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (0) #define SIMPLEQ_CONCAT(head1, head2) do { \ if (!SIMPLEQ_EMPTY((head2))) { \ *(head1)->sqh_last = (head2)->sqh_first; \ (head1)->sqh_last = (head2)->sqh_last; \ SIMPLEQ_INIT((head2)); \ } \ } while (0) /* * XOR Simple queue definitions. */ #define XSIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqx_first; /* first element */ \ struct type **sqx_last; /* addr of last next element */ \ unsigned long sqx_cookie; \ } #define XSIMPLEQ_ENTRY(type) \ struct { \ struct type *sqx_next; /* next element */ \ } /* * XOR Simple queue access methods. */ #define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ (unsigned long)(ptr))) #define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) #define XSIMPLEQ_END(head) NULL #define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) #define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) #define XSIMPLEQ_FOREACH(var, head, field) \ for ((var) = XSIMPLEQ_FIRST(head); \ (var) != XSIMPLEQ_END(head); \ (var) = XSIMPLEQ_NEXT(head, var, field)) #define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = XSIMPLEQ_FIRST(head); \ (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ (var) = (tvar)) /* * XOR Simple queue functions. */ #define XSIMPLEQ_INIT(head) do { \ arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ } while (0) #define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.sqx_next = (head)->sqx_first) == \ XSIMPLEQ_XOR(head, NULL)) \ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ } while (0) #define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ } while (0) #define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ XSIMPLEQ_XOR(head, NULL)) \ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ } while (0) #define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ } while (0) #define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ (elm)->field.sqx_next)->field.sqx_next) \ == XSIMPLEQ_XOR(head, NULL)) \ (head)->sqx_last = \ XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ } while (0) /* * Tail queue definitions. */ #define TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ } #define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } #define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ } /* * Tail queue access methods. */ #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_END(head) NULL #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) /* XXX */ #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) #define TAILQ_EMPTY(head) \ (TAILQ_FIRST(head) == TAILQ_END(head)) #define TAILQ_FOREACH(var, head, field) \ for((var) = TAILQ_FIRST(head); \ (var) != TAILQ_END(head); \ (var) = TAILQ_NEXT(var, field)) #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST(head); \ (var) != TAILQ_END(head) && \ ((tvar) = TAILQ_NEXT(var, field), 1); \ (var) = (tvar)) #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for((var) = TAILQ_LAST(head, headname); \ (var) != TAILQ_END(head); \ (var) = TAILQ_PREV(var, headname, field)) #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ for ((var) = TAILQ_LAST(head, headname); \ (var) != TAILQ_END(head) && \ ((tvar) = TAILQ_PREV(var, headname, field), 1); \ (var) = (tvar)) /* * Tail queue functions. */ #define TAILQ_INIT(head) do { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &(head)->tqh_first; \ } while (0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ (head)->tqh_first->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (head)->tqh_first = (elm); \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } while (0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } while (0) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (listelm)->field.tqe_next = (elm); \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } while (0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_next = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ } while (0) #define TAILQ_REMOVE(head, elm, field) do { \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ _Q_INVALIDATE((elm)->field.tqe_prev); \ _Q_INVALIDATE((elm)->field.tqe_next); \ } while (0) #define TAILQ_REPLACE(head, elm, elm2, field) do { \ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ (elm2)->field.tqe_next->field.tqe_prev = \ &(elm2)->field.tqe_next; \ else \ (head)->tqh_last = &(elm2)->field.tqe_next; \ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ *(elm2)->field.tqe_prev = (elm2); \ _Q_INVALIDATE((elm)->field.tqe_prev); \ _Q_INVALIDATE((elm)->field.tqe_next); \ } while (0) #define TAILQ_CONCAT(head1, head2, field) do { \ if (!TAILQ_EMPTY(head2)) { \ *(head1)->tqh_last = (head2)->tqh_first; \ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ (head1)->tqh_last = (head2)->tqh_last; \ TAILQ_INIT((head2)); \ } \ } while (0) #endif /* !_SYS_QUEUE_H_ */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/vis.c100644 001750 001750 0000000003614775415623 0017034xustar0030 atime=1744182234.670727945 openssh-10.0p1/openbsd-compat/vis.c010064400017500001750000000137431477541562300154270ustar00djmdjm/* $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. * * 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/gen/vis.c */ #include "includes.h" #if !defined(HAVE_STRNVIS) || defined(BROKEN_STRNVIS) #include #include #include #include #include #include #include "vis.h" #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') #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))) || \ ((flag & VIS_SP) == 0 && (c) == ' ') || \ ((flag & VIS_TAB) == 0 && (c) == '\t') || \ ((flag & VIS_NL) == 0 && (c) == '\n') || \ ((flag & VIS_SAFE) && ((c) == '\b' || \ (c) == '\007' || (c) == '\r' || \ isgraph((u_char)(c)))))) /* * vis - visually encode characters */ char * vis(char *dst, int c, int flag, int nextc) { if (isvisible(c, flag)) { if ((c == '"' && (flag & VIS_DQ) != 0) || (c == '\\' && (flag & VIS_NOSLASH) == 0)) *dst++ = '\\'; *dst++ = c; *dst = '\0'; return (dst); } if (flag & VIS_CSTYLE) { switch(c) { case '\n': *dst++ = '\\'; *dst++ = 'n'; goto done; case '\r': *dst++ = '\\'; *dst++ = 'r'; goto done; case '\b': *dst++ = '\\'; *dst++ = 'b'; goto done; case '\a': *dst++ = '\\'; *dst++ = 'a'; goto done; case '\v': *dst++ = '\\'; *dst++ = 'v'; goto done; case '\t': *dst++ = '\\'; *dst++ = 't'; goto done; case '\f': *dst++ = '\\'; *dst++ = 'f'; goto done; case ' ': *dst++ = '\\'; *dst++ = 's'; goto done; case '\0': *dst++ = '\\'; *dst++ = '0'; if (isoctal(nextc)) { *dst++ = '0'; *dst++ = '0'; } goto done; } } if (((c & 0177) == ' ') || (flag & VIS_OCTAL) || ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) { *dst++ = '\\'; *dst++ = ((u_char)c >> 6 & 07) + '0'; *dst++ = ((u_char)c >> 3 & 07) + '0'; *dst++ = ((u_char)c & 07) + '0'; goto done; } if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; if (c & 0200) { c &= 0177; *dst++ = 'M'; } if (iscntrl((u_char)c)) { *dst++ = '^'; if (c == 0177) *dst++ = '?'; else *dst++ = c + '@'; } else { *dst++ = '-'; *dst++ = c; } done: *dst = '\0'; return (dst); } DEF_WEAK(vis); /* * strvis, strnvis, strvisx - visually encode characters from src into dst * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NULL, * is returned. * * Strnvis will write no more than siz-1 bytes (and will NULL terminate). * The number of bytes needed to fully encode the string is returned. * * Strvisx encodes exactly len bytes from src into dst. * This is useful for encoding a block of data. */ int strvis(char *dst, const char *src, int flag) { char c; char *start; for (start = dst; (c = *src);) dst = vis(dst, c, flag, *++src); *dst = '\0'; return (dst - start); } DEF_WEAK(strvis); int strnvis(char *dst, const char *src, size_t siz, int flag) { char *start, *end; char tbuf[5]; int c, i; i = 0; for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) { if (isvisible(c, flag)) { if ((c == '"' && (flag & VIS_DQ) != 0) || (c == '\\' && (flag & VIS_NOSLASH) == 0)) { /* need space for the extra '\\' */ if (dst + 1 >= end) { i = 2; break; } *dst++ = '\\'; } i = 1; *dst++ = c; src++; } else { i = vis(tbuf, c, flag, *++src) - tbuf; if (dst + i <= end) { memcpy(dst, tbuf, i); dst += i; } else { src--; break; } } } if (siz > 0) *dst = '\0'; if (dst + i > end) { /* adjust return value for truncation */ while ((c = *src)) dst += vis(tbuf, c, flag, *++src) - tbuf; } return (dst - start); } 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; char *start; for (start = dst; len > 1; len--) { c = *src; dst = vis(dst, c, flag, *++src); } if (len) dst = vis(dst, *src, flag, '\0'); *dst = '\0'; return (dst - start); } #endif openssh-10.0p1/openbsd-compat/PaxHeaders.10889/sys-tree.h100644 001750 001750 0000000003614775415623 0020013xustar0030 atime=1744182234.670727945 openssh-10.0p1/openbsd-compat/sys-tree.h010064400017500001750000000612651477541562300164100ustar00djmdjm/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */ /* * Copyright 2002 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* OPENBSD ORIGINAL: sys/sys/tree.h */ #include "config.h" #ifdef NO_ATTRIBUTE_ON_RETURN_TYPE # define __attribute__(x) #endif #ifndef _SYS_TREE_H_ #define _SYS_TREE_H_ /* * This file defines data structures for different types of trees: * splay trees and red-black trees. * * A splay tree is a self-organizing data structure. Every operation * on the tree causes a splay to happen. The splay moves the requested * node to the root of the tree and partly rebalances it. * * This has the benefit that request locality causes faster lookups as * the requested nodes move to the top of the tree. On the other hand, * every lookup causes memory writes. * * The Balance Theorem bounds the total access time for m operations * and n inserts on an initially empty tree as O((m + n)lg n). The * amortized cost for a sequence of m accesses to a splay tree is O(lg n); * * A red-black tree is a binary search tree with the node color as an * extra attribute. It fulfills a set of conditions: * - every search path from the root to a leaf consists of the * same number of black nodes, * - each red node (except for the root) has a black parent, * - each leaf node is black. * * Every operation on a red-black tree is bounded as O(lg n). * The maximum height of a red-black tree is 2lg (n+1). */ #define SPLAY_HEAD(name, type) \ struct name { \ struct type *sph_root; /* root of the tree */ \ } #define SPLAY_INITIALIZER(root) \ { NULL } #define SPLAY_INIT(root) do { \ (root)->sph_root = NULL; \ } while (0) #define SPLAY_ENTRY(type) \ struct { \ struct type *spe_left; /* left element */ \ struct type *spe_right; /* right element */ \ } #define SPLAY_LEFT(elm, field) (elm)->field.spe_left #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right #define SPLAY_ROOT(head) (head)->sph_root #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ #define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ (head)->sph_root = tmp; \ } while (0) #define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ SPLAY_LEFT(tmp, field) = (head)->sph_root; \ (head)->sph_root = tmp; \ } while (0) #define SPLAY_LINKLEFT(head, tmp, field) do { \ SPLAY_LEFT(tmp, field) = (head)->sph_root; \ tmp = (head)->sph_root; \ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ } while (0) #define SPLAY_LINKRIGHT(head, tmp, field) do { \ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ tmp = (head)->sph_root; \ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ } while (0) #define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ } while (0) /* Generates prototypes and inline functions */ #define SPLAY_PROTOTYPE(name, type, field, cmp) \ void name##_SPLAY(struct name *, struct type *); \ void name##_SPLAY_MINMAX(struct name *, int); \ struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ \ /* Finds the node with the same key as elm */ \ static __inline struct type * \ name##_SPLAY_FIND(struct name *head, struct type *elm) \ { \ if (SPLAY_EMPTY(head)) \ return(NULL); \ name##_SPLAY(head, elm); \ if ((cmp)(elm, (head)->sph_root) == 0) \ return (head->sph_root); \ return (NULL); \ } \ \ static __inline struct type * \ name##_SPLAY_NEXT(struct name *head, struct type *elm) \ { \ name##_SPLAY(head, elm); \ if (SPLAY_RIGHT(elm, field) != NULL) { \ elm = SPLAY_RIGHT(elm, field); \ while (SPLAY_LEFT(elm, field) != NULL) { \ elm = SPLAY_LEFT(elm, field); \ } \ } else \ elm = NULL; \ return (elm); \ } \ \ static __inline struct type * \ name##_SPLAY_MIN_MAX(struct name *head, int val) \ { \ name##_SPLAY_MINMAX(head, val); \ return (SPLAY_ROOT(head)); \ } /* Main splay operation. * Moves node close to the key of elm to top */ #define SPLAY_GENERATE(name, type, field, cmp) \ struct type * \ name##_SPLAY_INSERT(struct name *head, struct type *elm) \ { \ if (SPLAY_EMPTY(head)) { \ SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ } else { \ int __comp; \ name##_SPLAY(head, elm); \ __comp = (cmp)(elm, (head)->sph_root); \ if(__comp < 0) { \ SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ SPLAY_RIGHT(elm, field) = (head)->sph_root; \ SPLAY_LEFT((head)->sph_root, field) = NULL; \ } else if (__comp > 0) { \ SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ SPLAY_LEFT(elm, field) = (head)->sph_root; \ SPLAY_RIGHT((head)->sph_root, field) = NULL; \ } else \ return ((head)->sph_root); \ } \ (head)->sph_root = (elm); \ return (NULL); \ } \ \ struct type * \ name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ { \ struct type *__tmp; \ if (SPLAY_EMPTY(head)) \ return (NULL); \ name##_SPLAY(head, elm); \ if ((cmp)(elm, (head)->sph_root) == 0) { \ if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ } else { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ name##_SPLAY(head, elm); \ SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ } \ return (elm); \ } \ return (NULL); \ } \ \ void \ name##_SPLAY(struct name *head, struct type *elm) \ { \ struct type __node, *__left, *__right, *__tmp; \ int __comp; \ \ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ __left = __right = &__node; \ \ while ((__comp = (cmp)(elm, (head)->sph_root))) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if ((cmp)(elm, __tmp) < 0){ \ SPLAY_ROTATE_RIGHT(head, __tmp, field); \ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKLEFT(head, __right, field); \ } else if (__comp > 0) { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if ((cmp)(elm, __tmp) > 0){ \ SPLAY_ROTATE_LEFT(head, __tmp, field); \ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKRIGHT(head, __left, field); \ } \ } \ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ } \ \ /* Splay with either the minimum or the maximum element \ * Used to find minimum or maximum element in tree. \ */ \ void name##_SPLAY_MINMAX(struct name *head, int __comp) \ { \ struct type __node, *__left, *__right, *__tmp; \ \ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ __left = __right = &__node; \ \ while (1) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if (__comp < 0){ \ SPLAY_ROTATE_RIGHT(head, __tmp, field); \ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKLEFT(head, __right, field); \ } else if (__comp > 0) { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if (__comp > 0) { \ SPLAY_ROTATE_LEFT(head, __tmp, field); \ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKRIGHT(head, __left, field); \ } \ } \ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ } #define SPLAY_NEGINF -1 #define SPLAY_INF 1 #define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) #define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) #define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) #define SPLAY_FOREACH(x, name, head) \ for ((x) = SPLAY_MIN(name, head); \ (x) != NULL; \ (x) = SPLAY_NEXT(name, head, x)) /* Macros that define a red-black tree */ #define RB_HEAD(name, type) \ struct name { \ struct type *rbh_root; /* root of the tree */ \ } #define RB_INITIALIZER(root) \ { NULL } #define RB_INIT(root) do { \ (root)->rbh_root = NULL; \ } while (0) #define RB_BLACK 0 #define RB_RED 1 #define RB_ENTRY(type) \ struct { \ struct type *rbe_left; /* left element */ \ struct type *rbe_right; /* right element */ \ struct type *rbe_parent; /* parent element */ \ int rbe_color; /* node color */ \ } #define RB_LEFT(elm, field) (elm)->field.rbe_left #define RB_RIGHT(elm, field) (elm)->field.rbe_right #define RB_PARENT(elm, field) (elm)->field.rbe_parent #define RB_COLOR(elm, field) (elm)->field.rbe_color #define RB_ROOT(head) (head)->rbh_root #define RB_EMPTY(head) (RB_ROOT(head) == NULL) #define RB_SET(elm, parent, field) do { \ RB_PARENT(elm, field) = parent; \ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ RB_COLOR(elm, field) = RB_RED; \ } while (0) #define RB_SET_BLACKRED(black, red, field) do { \ RB_COLOR(black, field) = RB_BLACK; \ RB_COLOR(red, field) = RB_RED; \ } while (0) #ifndef RB_AUGMENT #define RB_AUGMENT(x) do {} while (0) #endif #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ (tmp) = RB_RIGHT(elm, field); \ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ } else \ (head)->rbh_root = (tmp); \ RB_LEFT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ if ((RB_PARENT(tmp, field))) \ RB_AUGMENT(RB_PARENT(tmp, field)); \ } while (0) #define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ (tmp) = RB_LEFT(elm, field); \ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ } else \ (head)->rbh_root = (tmp); \ RB_RIGHT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ if ((RB_PARENT(tmp, field))) \ RB_AUGMENT(RB_PARENT(tmp, field)); \ } while (0) /* Generates prototypes and inline functions */ #define RB_PROTOTYPE(name, type, field, cmp) \ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) #define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) #define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ attr struct type *name##_RB_INSERT(struct name *, struct type *); \ attr struct type *name##_RB_FIND(struct name *, struct type *); \ attr struct type *name##_RB_NFIND(struct name *, struct type *); \ attr struct type *name##_RB_NEXT(struct type *); \ attr struct type *name##_RB_PREV(struct type *); \ attr struct type *name##_RB_MINMAX(struct name *, int); \ \ /* Main rb operation. * Moves node close to the key of elm to top */ #define RB_GENERATE(name, type, field, cmp) \ RB_GENERATE_INTERNAL(name, type, field, cmp,) #define RB_GENERATE_STATIC(name, type, field, cmp) \ RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) #define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ attr void \ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ { \ struct type *parent, *gparent, *tmp; \ while ((parent = RB_PARENT(elm, field)) && \ RB_COLOR(parent, field) == RB_RED) { \ gparent = RB_PARENT(parent, field); \ if (parent == RB_LEFT(gparent, field)) { \ tmp = RB_RIGHT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_RIGHT(parent, field) == elm) { \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_RIGHT(head, gparent, tmp, field); \ } else { \ tmp = RB_LEFT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_LEFT(parent, field) == elm) { \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_LEFT(head, gparent, tmp, field); \ } \ } \ RB_COLOR(head->rbh_root, field) = RB_BLACK; \ } \ \ attr void \ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ { \ struct type *tmp; \ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ elm != RB_ROOT(head)) { \ if (RB_LEFT(parent, field) == elm) { \ tmp = RB_RIGHT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = RB_RIGHT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ if (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ struct type *oleft; \ if ((oleft = RB_LEFT(tmp, field)))\ RB_COLOR(oleft, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_RIGHT(head, tmp, oleft, field);\ tmp = RB_RIGHT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_RIGHT(tmp, field)) \ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_LEFT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } else { \ tmp = RB_LEFT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = RB_LEFT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ if (RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ struct type *oright; \ if ((oright = RB_RIGHT(tmp, field)))\ RB_COLOR(oright, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_LEFT(head, tmp, oright, field);\ tmp = RB_LEFT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_LEFT(tmp, field)) \ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_RIGHT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } \ } \ if (elm) \ RB_COLOR(elm, field) = RB_BLACK; \ } \ \ attr struct type * \ name##_RB_REMOVE(struct name *head, struct type *elm) \ { \ struct type *child, *parent, *old = elm; \ int color; \ if (RB_LEFT(elm, field) == NULL) \ child = RB_RIGHT(elm, field); \ else if (RB_RIGHT(elm, field) == NULL) \ child = RB_LEFT(elm, field); \ else { \ struct type *left; \ elm = RB_RIGHT(elm, field); \ while ((left = RB_LEFT(elm, field))) \ elm = left; \ child = RB_RIGHT(elm, field); \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ if (RB_PARENT(elm, field) == old) \ parent = elm; \ (elm)->field = (old)->field; \ if (RB_PARENT(old, field)) { \ if (RB_LEFT(RB_PARENT(old, field), field) == old)\ RB_LEFT(RB_PARENT(old, field), field) = elm;\ else \ RB_RIGHT(RB_PARENT(old, field), field) = elm;\ RB_AUGMENT(RB_PARENT(old, field)); \ } else \ RB_ROOT(head) = elm; \ RB_PARENT(RB_LEFT(old, field), field) = elm; \ if (RB_RIGHT(old, field)) \ RB_PARENT(RB_RIGHT(old, field), field) = elm; \ if (parent) { \ left = parent; \ do { \ RB_AUGMENT(left); \ } while ((left = RB_PARENT(left, field))); \ } \ goto color; \ } \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ color: \ if (color == RB_BLACK) \ name##_RB_REMOVE_COLOR(head, parent, child); \ return (old); \ } \ \ /* Inserts a node into the RB tree */ \ attr struct type * \ name##_RB_INSERT(struct name *head, struct type *elm) \ { \ struct type *tmp; \ struct type *parent = NULL; \ int comp = 0; \ tmp = RB_ROOT(head); \ while (tmp) { \ parent = tmp; \ comp = (cmp)(elm, parent); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ RB_SET(elm, parent, field); \ if (parent != NULL) { \ if (comp < 0) \ RB_LEFT(parent, field) = elm; \ else \ RB_RIGHT(parent, field) = elm; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = elm; \ name##_RB_INSERT_COLOR(head, elm); \ return (NULL); \ } \ \ /* Finds the node with the same key as elm */ \ attr struct type * \ name##_RB_FIND(struct name *head, struct type *elm) \ { \ struct type *tmp = RB_ROOT(head); \ int comp; \ while (tmp) { \ comp = cmp(elm, tmp); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ return (NULL); \ } \ \ /* Finds the first node greater than or equal to the search key */ \ attr struct type * \ name##_RB_NFIND(struct name *head, struct type *elm) \ { \ struct type *tmp = RB_ROOT(head); \ struct type *res = NULL; \ int comp; \ while (tmp) { \ comp = cmp(elm, tmp); \ if (comp < 0) { \ res = tmp; \ tmp = RB_LEFT(tmp, field); \ } \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ return (res); \ } \ \ /* ARGSUSED */ \ attr struct type * \ name##_RB_NEXT(struct type *elm) \ { \ if (RB_RIGHT(elm, field)) { \ elm = RB_RIGHT(elm, field); \ while (RB_LEFT(elm, field)) \ elm = RB_LEFT(elm, field); \ } else { \ if (RB_PARENT(elm, field) && \ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ elm = RB_PARENT(elm, field); \ else { \ while (RB_PARENT(elm, field) && \ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ elm = RB_PARENT(elm, field); \ elm = RB_PARENT(elm, field); \ } \ } \ return (elm); \ } \ \ /* ARGSUSED */ \ attr struct type * \ name##_RB_PREV(struct type *elm) \ { \ if (RB_LEFT(elm, field)) { \ elm = RB_LEFT(elm, field); \ while (RB_RIGHT(elm, field)) \ elm = RB_RIGHT(elm, field); \ } else { \ if (RB_PARENT(elm, field) && \ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ elm = RB_PARENT(elm, field); \ else { \ while (RB_PARENT(elm, field) && \ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ elm = RB_PARENT(elm, field); \ elm = RB_PARENT(elm, field); \ } \ } \ return (elm); \ } \ \ attr struct type * \ name##_RB_MINMAX(struct name *head, int val) \ { \ struct type *tmp = RB_ROOT(head); \ struct type *parent = NULL; \ while (tmp) { \ parent = tmp; \ if (val < 0) \ tmp = RB_LEFT(tmp, field); \ else \ tmp = RB_RIGHT(tmp, field); \ } \ return (parent); \ } #define RB_NEGINF -1 #define RB_INF 1 #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) #define RB_FIND(name, x, y) name##_RB_FIND(x, y) #define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) #define RB_NEXT(name, x, y) name##_RB_NEXT(y) #define RB_PREV(name, x, y) name##_RB_PREV(y) #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) #define RB_FOREACH(x, name, head) \ for ((x) = RB_MIN(name, head); \ (x) != NULL; \ (x) = name##_RB_NEXT(x)) #define RB_FOREACH_SAFE(x, name, head, y) \ for ((x) = RB_MIN(name, head); \ ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \ (x) = (y)) #define RB_FOREACH_REVERSE(x, name, head) \ for ((x) = RB_MAX(name, head); \ (x) != NULL; \ (x) = name##_RB_PREV(x)) #define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ for ((x) = RB_MAX(name, head); \ ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \ (x) = (y)) #endif /* _SYS_TREE_H_ */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/timingsafe_bcmp.c100644 001750 001750 0000000003614775415623 0021362xustar0030 atime=1744182234.670727945 openssh-10.0p1/openbsd-compat/timingsafe_bcmp.c010064400017500001750000000022551477541562300177510ustar00djmdjm/* $OpenBSD: timingsafe_bcmp.c,v 1.1 2010/09/24 13:33:00 matthew Exp $ */ /* * Copyright (c) 2010 Damien Miller. 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. */ /* OPENBSD ORIGINAL: lib/libc/string/timingsafe_bcmp.c */ #include "includes.h" #ifndef HAVE_TIMINGSAFE_BCMP int timingsafe_bcmp(const void *b1, const void *b2, size_t n) { const unsigned char *p1 = b1, *p2 = b2; int ret = 0; for (; n > 0; n--) ret |= *p1++ ^ *p2++; return (ret != 0); } #endif /* TIMINGSAFE_BCMP */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/vis.h100644 001750 001750 0000000003514775415623 0017040xustar0029 atime=1744182234.67170374 openssh-10.0p1/openbsd-compat/vis.h010064400017500001750000000071131477541562300154260ustar00djmdjm/* $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 $ */ /*- * Copyright (c) 1990 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. * * @(#)vis.h 5.9 (Berkeley) 4/3/91 */ /* OPENBSD ORIGINAL: include/vis.h */ #include "includes.h" #if !defined(HAVE_STRNVIS) || defined(BROKEN_STRNVIS) #ifndef _VIS_H_ #define _VIS_H_ #include #include /* * to select alternate encoding format */ #define VIS_OCTAL 0x01 /* use octal \ddd format */ #define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */ /* * to alter set of characters encoded (default is to encode all * non-graphic except space, tab, and newline). */ #define VIS_SP 0x04 /* also encode space */ #define VIS_TAB 0x08 /* also encode tab */ #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 */ #define VIS_NOSLASH 0x40 /* inhibit printing '\' */ #define VIS_GLOB 0x100 /* encode glob(3) magics and '#' */ /* * unvis return codes */ #define UNVIS_VALID 1 /* character valid */ #define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ #define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ #define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ #define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ /* * unvis flags */ #define UNVIS_END 1 /* no more characters */ 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) __attribute__ ((__bounded__(__string__,1,3))); int strunvis(char *, const char *); int unvis(char *, char, int *, int); ssize_t strnunvis(char *, const char *, size_t) __attribute__ ((__bounded__(__string__,1,3))); #endif /* !_VIS_H_ */ #endif /* !HAVE_STRNVIS || BROKEN_STRNVIS */ openssh-10.0p1/openbsd-compat/PaxHeaders.10889/xcrypt.c100644 001750 001750 0000000003514775415623 0017563xustar0029 atime=1744182234.67170374 openssh-10.0p1/openbsd-compat/xcrypt.c010064400017500001750000000101321477541562300161440ustar00djmdjm/* * Copyright (c) 2003 Ben Lindstrom. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include # if defined(HAVE_CRYPT_H) && !defined(HAVE_SECUREWARE) # include # endif # ifdef __hpux # include # include # endif # ifdef HAVE_SECUREWARE # include # include # include # endif # if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) # include # endif # if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) # include # include # include # endif # if defined(WITH_OPENSSL) && !defined(HAVE_CRYPT) && defined(HAVE_DES_CRYPT) # include # define crypt DES_crypt # endif #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) /* * 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, MINIMUM(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(); #if defined(__hpux) && !defined(HAVE_SECUREWARE) if (iscomsec()) crypted = bigcrypt(password, salt); else crypted = crypt(password, salt); # elif defined(HAVE_SECUREWARE) crypted = bigcrypt(password, salt); # else crypted = crypt(password, salt); #endif return crypted; } /* * Handle shadowed password systems in a cleaner way for portable * version. */ char * shadow_pw(struct passwd *pw) { char *pw_password = pw->pw_passwd; # if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) struct spwd *spw = getspnam(pw->pw_name); if (spw != NULL) pw_password = spw->sp_pwdp; # endif #ifdef USE_LIBIAF return(get_iaf_password(pw)); #endif # if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) struct passwd_adjunct *spw; if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL) pw_password = spw->pwa_passwd; # elif defined(HAVE_SECUREWARE) struct pr_passwd *spw = getprpwnam(pw->pw_name); if (spw != NULL) pw_password = spw->ufld.fd_encrypt; # endif return pw_password; } openssh-10.0p1/PaxHeaders.10889/openssh.xml.in100644 001750 001750 0000000003514775415623 0015761xustar0029 atime=1744182234.67170374 openssh-10.0p1/openssh.xml.in010064400017500001750000000054271477541562300143550ustar00djmdjm openssh-10.0p1/PaxHeaders.10889/opensshd.init.in100755 001750 001750 0000000003514775415623 0016273xustar0029 atime=1744182234.67170374 openssh-10.0p1/opensshd.init.in010075500017500001750000000023601477541562300146600ustar00djmdjm#!@STARTUP_SCRIPT_SHELL@ # Donated code that was put under PD license. # # Stripped PRNGd out of it for the time being. umask 022 CAT=@CAT@ KILL=@KILL@ prefix=@prefix@ sysconfdir=@sysconfdir@ piddir=@piddir@ SSHD=$prefix/sbin/sshd 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 stop_service() { if [ -r $PIDFILE -a ! -z ${PIDFILE} ]; then PID=`${CAT} ${PIDFILE}` fi if [ ${PID:=0} -gt 1 -a ! "X$PID" = "X " ]; then ${KILL} ${PID} else echo "Unable to read PID file" fi } start_service() { # XXX We really should check if the service is already going, but # XXX we will opt out at this time. - Bal # Check to see if we have keys that need to be made ${SSH_KEYGEN} -A # Start SSHD echo "starting $SSHD... \c" ; $SSHD sshd_rc=$? if [ $sshd_rc -ne 0 ]; then echo "$0: Error ${sshd_rc} starting ${SSHD}... bailing." exit $sshd_rc fi echo done. } case $1 in 'start') start_service ;; 'stop') stop_service ;; 'restart') stop_service start_service ;; *) echo "$0: usage: $0 {start|stop|restart}" ;; esac openssh-10.0p1/PaxHeaders.10889/packet.c100644 001750 001750 0000000003614775415623 0014567xustar0030 atime=1744182234.679516659 openssh-10.0p1/packet.c010064400017500001750000002267221477541562300131650ustar00djmdjm/* $OpenBSD: packet.c,v 1.318 2025/02/18 08:02:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * This file contains code implementing the packet protocol and communication * with the other side. This same code is used both on client and server side. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * SSH2 packet format added by Markus Friedl. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include "openbsd-compat/sys-queue.h" #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_POLL_H #include #endif #include #include /* * Explicitly include OpenSSL before zlib as some versions of OpenSSL have * "free_func" in their headers, which zlib typedefs. */ #ifdef WITH_OPENSSL # include # include # ifdef OPENSSL_HAS_ECC # include # endif #endif #ifdef WITH_ZLIB #include #endif #include "xmalloc.h" #include "compat.h" #include "ssh2.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "digest.h" #include "mac.h" #include "log.h" #include "canohost.h" #include "misc.h" #include "channels.h" #include "ssh.h" #include "packet.h" #include "ssherr.h" #include "sshbuf.h" #ifdef PACKET_DEBUG #define DBG(x) x #else #define DBG(x) #endif #define PACKET_MAX_SIZE (256 * 1024) struct packet_state { u_int32_t seqnr; u_int32_t packets; u_int64_t blocks; u_int64_t bytes; }; struct packet { TAILQ_ENTRY(packet) next; u_char type; struct sshbuf *payload; }; struct session_state { /* * This variable contains the file descriptors used for * communicating with the other side. connection_in is used for * reading; connection_out for writing. These can be the same * descriptor, in which case it is assumed to be a socket. */ int connection_in; int connection_out; /* Protocol flags for the remote side. */ u_int remote_protocol_flags; /* Encryption context for receiving data. Only used for decryption. */ struct sshcipher_ctx *receive_context; /* Encryption context for sending data. Only used for encryption. */ struct sshcipher_ctx *send_context; /* Buffer for raw input data from the socket. */ struct sshbuf *input; /* Buffer for raw output data going to the socket. */ struct sshbuf *output; /* Buffer for the partial outgoing packet being constructed. */ struct sshbuf *outgoing_packet; /* Buffer for the incoming packet currently being processed. */ struct sshbuf *incoming_packet; /* 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; /* default maximum packet size */ u_int max_packet_size; /* Flag indicating whether this module has been initialized. */ int initialized; /* Set to true if the connection is interactive. */ int interactive_mode; /* Set to true if we are the server side. */ int server_side; /* Set to true if we are authenticated. */ int after_authentication; int keep_alive_timeouts; /* The maximum time that we will wait to send or receive a packet */ int packet_timeout_ms; /* Session key information for Encryption and MAC */ struct newkeys *newkeys[MODE_MAX]; struct packet_state p_read, p_send; /* Volume-based rekeying */ 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 */ /* 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() */ u_int packlen; /* Used in packet_send2 */ int rekeying; /* Used in ssh_packet_send_mux() */ int mux; /* Used in packet_set_interactive */ int set_interactive_called; /* Used in packet_set_maxsize */ int set_maxsize_called; /* One-off warning about weak ciphers */ int cipher_warning_done; /* Hook for fuzzing inbound packets */ ssh_packet_hook_fn *hook_in; void *hook_in_ctx; TAILQ_HEAD(, packet) outgoing; }; struct ssh * ssh_alloc_session_state(void) { struct ssh *ssh = NULL; struct session_state *state = NULL; 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 || (state->incoming_packet = sshbuf_new()) == NULL) goto fail; TAILQ_INIT(&state->outgoing); TAILQ_INIT(&ssh->private_keys); TAILQ_INIT(&ssh->public_keys); state->connection_in = -1; state->connection_out = -1; state->max_packet_size = 32768; state->packet_timeout_ms = -1; state->p_send.packets = state->p_read.packets = 0; state->initialized = 1; /* * ssh_packet_send2() needs to queue packets until * we've done the initial key exchange. */ state->rekeying = 1; ssh->state = state; return ssh; fail: if (ssh) { kex_free(ssh->kex); free(ssh); } if (state) { sshbuf_free(state->input); sshbuf_free(state->output); sshbuf_free(state->incoming_packet); sshbuf_free(state->outgoing_packet); free(state); } 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 != NULL && ssh->kex->done == 0); } /* * Sets the descriptors used for communication. */ struct ssh * ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) { struct session_state *state; const struct sshcipher *none = cipher_by_name("none"); int r; if (none == NULL) { error_f("cannot load cipher 'none'"); return NULL; } if (ssh == NULL) ssh = ssh_alloc_session_state(); if (ssh == NULL) { error_f("could not allocate state"); return NULL; } state = ssh->state; state->connection_in = fd_in; state->connection_out = fd_out; if ((r = cipher_init(&state->send_context, none, (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 || (r = cipher_init(&state->receive_context, none, (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) { error_fr(r, "cipher_init failed"); free(ssh); /* XXX need ssh_free_session_state? */ return NULL; } state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; /* * Cache the IP address of the remote connection for use in error * messages that might be generated after the connection has closed. */ (void)ssh_remote_ipaddr(ssh); return ssh; } void ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count) { struct session_state *state = ssh->state; if (timeout <= 0 || count <= 0) { state->packet_timeout_ms = -1; return; } if ((INT_MAX / 1000) / count < timeout) state->packet_timeout_ms = INT_MAX; else state->packet_timeout_ms = timeout * count * 1000; } void ssh_packet_set_mux(struct ssh *ssh) { ssh->state->mux = 1; ssh->state->rekeying = 0; kex_free(ssh->kex); ssh->kex = NULL; } 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) { struct session_state *state = ssh->state; int r; 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) < 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), dlen, NULL, 0); } 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, size_t mac_already, u_int discard) { struct session_state *state = ssh->state; int r; if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) { if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0) return r; return SSH_ERR_MAC_INVALID; } /* * 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; 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; } /* Returns 1 if remote host is connected via socket, 0 if not. */ int ssh_packet_connection_is_on_socket(struct ssh *ssh) { 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) == -1) return 0; tolen = sizeof(to); memset(&to, 0, sizeof(to)); if (getpeername(state->connection_out, (struct sockaddr *)&to, &tolen) == -1) return 0; if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) return 0; if (from.ss_family != AF_INET && from.ss_family != AF_INET6) return 0; return 1; } void ssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes) { if (ibytes) *ibytes = ssh->state->p_read.bytes; if (obytes) *obytes = ssh->state->p_send.bytes; } int ssh_packet_connection_af(struct ssh *ssh) { return get_sock_af(ssh->state->connection_out); } /* Sets the connection into non-blocking mode. */ void ssh_packet_set_nonblocking(struct ssh *ssh) { /* Set the socket into non-blocking mode. */ set_nonblock(ssh->state->connection_in); if (ssh->state->connection_out != ssh->state->connection_in) set_nonblock(ssh->state->connection_out); } /* Returns the socket used for reading. */ int ssh_packet_get_connection_in(struct ssh *ssh) { return ssh->state->connection_in; } /* Returns the descriptor used for writing. */ int ssh_packet_get_connection_out(struct ssh *ssh) { return ssh->state->connection_out; } /* * Returns the IP-address of the remote host as a string. The returned * string must not be freed. */ const char * ssh_remote_ipaddr(struct ssh *ssh) { int sock; /* Check whether we have cached the ipaddr. */ 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 remote DNS hostname as a string. The returned string must not * be freed. NB. this will usually trigger a DNS query. Return value is on * heap and no caching is performed. * This function does additional checks on the hostname to mitigate some * attacks based on conflation of hostnames and addresses and will * fall back to returning an address on error. */ char * ssh_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_f("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); } /* 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. */ static void ssh_packet_close_internal(struct ssh *ssh, int do_close) { struct session_state *state = ssh->state; u_int mode; if (!state->initialized) return; state->initialized = 0; 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]); /* 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; debug("compress outgoing: " "raw data %llu, compressed %llu, factor %.2f", (unsigned long long)stream->total_in, (unsigned long long)stream->total_out, stream->total_in == 0 ? 0.0 : (double) stream->total_out / stream->total_in); if (state->compression_out_failures == 0) deflateEnd(stream); } if (state->compression_in_started) { z_streamp stream = &state->compression_in_stream; debug("compress incoming: " "raw data %llu, compressed %llu, factor %.2f", (unsigned long long)stream->total_out, (unsigned long long)stream->total_in, stream->total_out == 0 ? 0.0 : (double) stream->total_in / stream->total_out); if (state->compression_in_failures == 0) inflateEnd(stream); } } #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; kex_free(ssh->kex); ssh->kex = 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. */ void ssh_packet_set_protocol_flags(struct ssh *ssh, u_int protocol_flags) { ssh->state->remote_protocol_flags = protocol_flags; } /* Returns the remote protocol flags set earlier by the above function. */ u_int ssh_packet_get_protocol_flags(struct ssh *ssh) { return ssh->state->remote_protocol_flags; } /* * Starts packet compression from the next packet on in both directions. * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */ static int ssh_packet_init_compression(struct ssh *ssh) { if (!ssh->state->compression_buffer && ((ssh->state->compression_buffer = sshbuf_new()) == NULL)) return SSH_ERR_ALLOC_FAIL; return 0; } #ifdef WITH_ZLIB static int start_compression_out(struct ssh *ssh, int level) { if (level < 1 || level > 9) return SSH_ERR_INVALID_ARGUMENT; debug("Enabling compression at level %d.", level); if (ssh->state->compression_out_started == 1) deflateEnd(&ssh->state->compression_out_stream); switch (deflateInit(&ssh->state->compression_out_stream, level)) { case Z_OK: ssh->state->compression_out_started = 1; break; case Z_MEM_ERROR: return SSH_ERR_ALLOC_FAIL; default: return SSH_ERR_INTERNAL_ERROR; } return 0; } static int start_compression_in(struct ssh *ssh) { if (ssh->state->compression_in_started == 1) inflateEnd(&ssh->state->compression_in_stream); switch (inflateInit(&ssh->state->compression_in_stream)) { case Z_OK: ssh->state->compression_in_started = 1; break; case Z_MEM_ERROR: return SSH_ERR_ALLOC_FAIL; default: return SSH_ERR_INTERNAL_ERROR; } return 0; } /* XXX remove need for separate compression buffer */ static int compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { u_char buf[4096]; int r, status; if (ssh->state->compression_out_started != 1) return SSH_ERR_INTERNAL_ERROR; /* This case is not handled below. */ if (sshbuf_len(in) == 0) return 0; /* Input is the contents of the input buffer. */ if ((ssh->state->compression_out_stream.next_in = sshbuf_mutable_ptr(in)) == NULL) return SSH_ERR_INTERNAL_ERROR; ssh->state->compression_out_stream.avail_in = sshbuf_len(in); /* Loop compressing until deflate() returns with avail_out != 0. */ do { /* Set up fixed-size output buffer. */ ssh->state->compression_out_stream.next_out = buf; ssh->state->compression_out_stream.avail_out = sizeof(buf); /* Compress as much data into the buffer as possible. */ status = deflate(&ssh->state->compression_out_stream, Z_PARTIAL_FLUSH); switch (status) { case Z_MEM_ERROR: return SSH_ERR_ALLOC_FAIL; case Z_OK: /* Append compressed data to output_buffer. */ if ((r = sshbuf_put(out, buf, sizeof(buf) - ssh->state->compression_out_stream.avail_out)) != 0) return r; break; case Z_STREAM_ERROR: default: ssh->state->compression_out_failures++; return SSH_ERR_INVALID_FORMAT; } } while (ssh->state->compression_out_stream.avail_out == 0); return 0; } static int uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { u_char buf[4096]; int r, status; if (ssh->state->compression_in_started != 1) return SSH_ERR_INTERNAL_ERROR; if ((ssh->state->compression_in_stream.next_in = sshbuf_mutable_ptr(in)) == NULL) return SSH_ERR_INTERNAL_ERROR; ssh->state->compression_in_stream.avail_in = sshbuf_len(in); for (;;) { /* Set up fixed-size output buffer. */ ssh->state->compression_in_stream.next_out = buf; ssh->state->compression_in_stream.avail_out = sizeof(buf); status = inflate(&ssh->state->compression_in_stream, Z_SYNC_FLUSH); switch (status) { case Z_OK: if ((r = sshbuf_put(out, buf, sizeof(buf) - ssh->state->compression_in_stream.avail_out)) != 0) return r; break; case Z_BUF_ERROR: /* * Comments in zlib.h say that we should keep calling * inflate() until we get an error. This appears to * be the error that we get. */ return 0; case Z_DATA_ERROR: return SSH_ERR_INVALID_FORMAT; case Z_MEM_ERROR: return SSH_ERR_ALLOC_FAIL; case Z_STREAM_ERROR: default: ssh->state->compression_in_failures++; return SSH_ERR_INTERNAL_ERROR; } } /* NOTREACHED */ } #else /* WITH_ZLIB */ static int start_compression_out(struct ssh *ssh, int level) { return SSH_ERR_INTERNAL_ERROR; } static int start_compression_in(struct ssh *ssh) { return SSH_ERR_INTERNAL_ERROR; } static int compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { return SSH_ERR_INTERNAL_ERROR; } static int uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { return SSH_ERR_INTERNAL_ERROR; } #endif /* WITH_ZLIB */ void ssh_clear_newkeys(struct ssh *ssh, int mode) { if (ssh->kex && ssh->kex->newkeys[mode]) { kex_free_newkeys(ssh->kex->newkeys[mode]); ssh->kex->newkeys[mode] = NULL; } } int ssh_set_newkeys(struct ssh *ssh, int mode) { struct session_state *state = ssh->state; struct sshenc *enc; struct sshmac *mac; struct sshcomp *comp; 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_f("mode %d", mode); if (mode == MODE_OUT) { ccp = &state->send_context; crypt_type = CIPHER_ENCRYPT; ps = &state->p_send; max_blocks = &state->max_blocks_out; } else { ccp = &state->receive_context; crypt_type = CIPHER_DECRYPT; ps = &state->p_read; max_blocks = &state->max_blocks_in; } if (state->newkeys[mode] != NULL) { debug_f("rekeying %s, input %llu bytes %llu blocks, " "output %llu bytes %llu blocks", dir, (unsigned long long)state->p_read.bytes, (unsigned long long)state->p_read.blocks, (unsigned long long)state->p_send.bytes, (unsigned long long)state->p_send.blocks); kex_free_newkeys(state->newkeys[mode]); state->newkeys[mode] = NULL; } /* 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; ssh->kex->newkeys[mode] = NULL; enc = &state->newkeys[mode]->enc; mac = &state->newkeys[mode]->mac; comp = &state->newkeys[mode]->comp; if (cipher_authlen(enc->cipher) == 0) { if ((r = mac_init(mac)) != 0) return r; } mac->enabled = 1; DBG(debug_f("cipher_init: %s", 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(*ccp)) != NULL) { error("Warning: %s", wmsg); state->cipher_warning_done = 1; } /* Deleting the keys does not gain extra security */ /* explicit_bzero(enc->iv, enc->block_size); explicit_bzero(enc->key, enc->key_len); explicit_bzero(mac->key, mac->key_len); */ if (((comp->type == COMP_DELAYED && state->after_authentication)) && comp->enabled == 0) { if ((r = ssh_packet_init_compression(ssh)) < 0) return r; if (mode == MODE_OUT) { if ((r = start_compression_out(ssh, 6)) != 0) return r; } else { if ((r = start_compression_in(ssh)) != 0) return r; } comp->enabled = 1; } /* * The 2^(blocksize*2) limit is too expensive for 3DES, * 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 = 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)); } int ssh_packet_check_rekey(struct ssh *ssh) { if (!ssh_packet_need_rekeying(ssh, 0)) return 0; debug3_f("rekex triggered"); return kex_start_rekex(ssh); } /* * Delayed compression for SSH2 is enabled after authentication: * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. */ static int ssh_packet_enable_delayed_compress(struct ssh *ssh) { struct session_state *state = ssh->state; struct sshcomp *comp = NULL; int r, mode; /* * Remember that we are past the authentication step, so rekeying * with COMP_DELAYED will turn on compression immediately. */ state->after_authentication = 1; for (mode = 0; mode < MODE_MAX; mode++) { /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ if (state->newkeys[mode] == NULL) continue; comp = &state->newkeys[mode]->comp; if (comp && !comp->enabled && comp->type == COMP_DELAYED) { if ((r = ssh_packet_init_compression(ssh)) != 0) return r; if (mode == MODE_OUT) { if ((r = start_compression_out(ssh, 6)) != 0) return r; } else { if ((r = start_compression_in(ssh)) != 0) return r; } comp->enabled = 1; } } return 0; } /* Used to mute debug logging for noisy packet types */ int ssh_packet_log_type(u_char type) { switch (type) { case SSH2_MSG_PING: case SSH2_MSG_PONG: 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) */ int ssh_packet_send2_wrapped(struct ssh *ssh) { struct session_state *state = ssh->state; u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; u_char tmp, padlen, pad = 0; u_int authlen = 0, aadlen = 0; u_int len; struct sshenc *enc = NULL; struct sshmac *mac = NULL; struct sshcomp *comp = NULL; int r, block_size; if (state->newkeys[MODE_OUT] != NULL) { enc = &state->newkeys[MODE_OUT]->enc; mac = &state->newkeys[MODE_OUT]->mac; comp = &state->newkeys[MODE_OUT]->comp; /* disable mac for authenticated encryption */ if ((authlen = cipher_authlen(enc->cipher)) != 0) mac = NULL; } block_size = enc ? enc->block_size : 8; 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); #endif if (comp && comp->enabled) { len = sshbuf_len(state->outgoing_packet); /* skip header, compress only payload */ if ((r = sshbuf_consume(state->outgoing_packet, 5)) != 0) goto out; sshbuf_reset(state->compression_buffer); if ((r = compress_buffer(ssh, state->outgoing_packet, state->compression_buffer)) != 0) goto out; sshbuf_reset(state->outgoing_packet); if ((r = sshbuf_put(state->outgoing_packet, "\0\0\0\0\0", 5)) != 0 || (r = sshbuf_putb(state->outgoing_packet, state->compression_buffer)) != 0) goto out; DBG(debug("compression: raw %d compressed %zd", len, sshbuf_len(state->outgoing_packet))); } /* sizeof (packet_len + pad_len + payload) */ len = sshbuf_len(state->outgoing_packet); /* * calc size of padding, alloc space, get random data, * minimum padding is 4 bytes */ len -= aadlen; /* packet length is not encrypted for EtM modes */ padlen = block_size - (len % block_size); if (padlen < 4) padlen += block_size; if (state->extra_pad) { tmp = state->extra_pad; 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_f("adding %d (len %d padlen %d extra_pad %d)", pad, len, padlen, state->extra_pad)); tmp = padlen; padlen += pad; /* Check whether padlen calculation overflowed */ 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 && !cipher_ctx_is_plaintext(state->send_context)) { /* random padding */ arc4random_buf(cp, padlen); } else { /* clear padding */ explicit_bzero(cp, padlen); } /* sizeof (packet_len + pad_len + payload + padding) */ len = sshbuf_len(state->outgoing_packet); cp = sshbuf_mutable_ptr(state->outgoing_packet); if (cp == NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } /* packet_length includes payload, padding and padding length field */ POKE_U32(cp, len - 4); cp[4] = padlen; DBG(debug("send: len %d (includes padlen %d, aadlen %d)", len, padlen, aadlen)); /* compute MAC over seqnr and packet(length fields, payload, padding) */ if (mac && mac->enabled && !mac->etm) { if ((r = mac_compute(mac, state->p_send.seqnr, sshbuf_ptr(state->outgoing_packet), len, macbuf, sizeof(macbuf))) != 0) goto out; DBG(debug("done calc MAC out #%d", state->p_send.seqnr)); } /* encrypt packet and append to output buffer. */ 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, sshbuf_ptr(state->outgoing_packet), len - aadlen, aadlen, authlen)) != 0) goto out; /* append unencrypted MAC */ if (mac && mac->enabled) { if (mac->etm) { /* EtM: compute mac over aadlen + cipher text */ if ((r = mac_compute(mac, state->p_send.seqnr, cp, len, macbuf, sizeof(macbuf))) != 0) goto out; DBG(debug("done calc MAC(EtM) out #%d", state->p_send.seqnr)); } if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0) goto out; } #ifdef PACKET_DEBUG fprintf(stderr, "encrypted: "); sshbuf_dump(state->output, stderr); #endif /* increment sequence number for outgoing packets */ if (++state->p_send.seqnr == 0) { if ((ssh->kex->flags & KEX_INITIAL) != 0) { ssh_packet_disconnect(ssh, "outgoing sequence number " "wrapped during initial key exchange"); } logit("outgoing seqnr wraps around"); } if (++state->p_send.packets == 0) if (!(ssh->compat & SSH_BUG_NOREKEY)) return SSH_ERR_NEED_REKEY; state->p_send.blocks += len / block_size; state->p_send.bytes += len; sshbuf_reset(state->outgoing_packet); if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { debug_f("resetting send seqnr %u", state->p_send.seqnr); state->p_send.seqnr = 0; } if (type == SSH2_MSG_NEWKEYS) r = ssh_set_newkeys(ssh, MODE_OUT); else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side) r = ssh_packet_enable_delayed_compress(ssh); else r = 0; out: 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, 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. * Queue everything else. */ if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) { if (need_rekey) debug3_f("rekex triggered"); 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 */ if (type == SSH2_MSG_KEXINIT) state->rekeying = 1; if ((r = ssh_packet_send2_wrapped(ssh)) != 0) return r; /* after a NEWKEYS message we can send the complete queue */ if (type == SSH2_MSG_NEWKEYS) { state->rekeying = 0; 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_f("queued packet triggered rekex"); 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; } } return 0; } /* * Waits until a packet has been received, and returns its type. Note that * no other data is processed until this returns, so this function should not * be used during the interactive session. */ 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 = 0; struct pollfd pfd; char buf[8192]; struct timeval start; struct timespec timespec, *timespecp = NULL; DBG(debug("packet_read()")); /* * Since we are blocking, ensure that all written packets have * been sent. */ if ((r = ssh_packet_write_wait(ssh)) != 0) goto out; /* Stay in the loop until we have received a complete packet. */ for (;;) { /* Try to read a packet from the buffer. */ if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0) break; /* If we got a packet, return it. */ if (*typep != SSH_MSG_NONE) break; /* * Otherwise, wait for some data to arrive, add it to the * buffer, and try again. */ pfd.fd = state->connection_in; pfd.events = POLLIN; if (state->packet_timeout_ms > 0) { ms_remain = state->packet_timeout_ms; timespecp = ×pec; } /* Wait for some data to arrive. */ for (;;) { if (state->packet_timeout_ms > 0) { ms_to_timespec(×pec, ms_remain); monotime_tv(&start); } if ((r = ppoll(&pfd, 1, timespecp, NULL)) >= 0) break; if (errno != EAGAIN && errno != EINTR && 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) { r = 0; break; } } if (r == 0) { r = SSH_ERR_CONN_TIMEOUT; goto out; } /* Read data from the socket. */ 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) goto out; } out: return r; } int ssh_packet_read(struct ssh *ssh) { u_char type; int r; if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) fatal_fr(r, "read"); return type; } static int ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) { struct session_state *state = ssh->state; const u_char *cp; size_t need; int r; if (ssh->kex) return SSH_ERR_INTERNAL_ERROR; *typep = SSH_MSG_NONE; 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_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_f("type %u", *typep); /* sshbuf_dump(state->incoming_packet, stderr); */ /* reset for next packet */ state->packlen = 0; return r; } int 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; 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) return 0; if (state->newkeys[MODE_IN] != NULL) { enc = &state->newkeys[MODE_IN]->enc; mac = &state->newkeys[MODE_IN]->mac; comp = &state->newkeys[MODE_IN]->comp; /* disable mac for authenticated encryption */ if ((authlen = cipher_authlen(enc->cipher)) != 0) mac = NULL; } maclen = mac && mac->enabled ? mac->mac_len : 0; block_size = enc ? enc->block_size : 8; aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; if (aadlen && state->packlen == 0) { if (cipher_get_length(state->receive_context, &state->packlen, state->p_read.seqnr, sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0) return 0; if (state->packlen < 1 + 4 || state->packlen > PACKET_MAX_SIZE) { #ifdef PACKET_DEBUG sshbuf_dump(state->input, stderr); #endif 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) { /* * check if input size is less than the cipher block size, * decrypt first block and extract length of incoming packet */ if (sshbuf_len(state->input) < block_size) return 0; sshbuf_reset(state->incoming_packet); if ((r = sshbuf_reserve(state->incoming_packet, block_size, &cp)) != 0) goto out; if ((r = cipher_crypt(state->receive_context, state->p_send.seqnr, cp, sshbuf_ptr(state->input), block_size, 0, 0)) != 0) goto out; state->packlen = PEEK_U32(sshbuf_ptr(state->incoming_packet)); if (state->packlen < 1 + 4 || state->packlen > PACKET_MAX_SIZE) { #ifdef PACKET_DEBUG fprintf(stderr, "input: \n"); sshbuf_dump(state->input, stderr); fprintf(stderr, "incoming_packet: \n"); sshbuf_dump(state->incoming_packet, stderr); #endif logit("Bad packet length %u.", state->packlen); return ssh_packet_start_discard(ssh, enc, mac, 0, PACKET_MAX_SIZE); } if ((r = sshbuf_consume(state->input, block_size)) != 0) goto out; } DBG(debug("input: packet len %u", state->packlen+4)); if (aadlen) { /* only the payload is encrypted */ need = state->packlen; } else { /* * the payload size and the payload are encrypted, but we * have a partial packet of block_size bytes */ need = 4 + state->packlen - block_size; } DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d," " aadlen %d", block_size, need, maclen, authlen, aadlen)); 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, 0, PACKET_MAX_SIZE - block_size); } /* * check if the entire packet has been received and * decrypt into incoming_packet: * 'aadlen' bytes are unencrypted, but authenticated. * 'need' bytes are encrypted, followed by either * 'authlen' bytes of authentication tag or * 'maclen' bytes of message authentication code. */ if (sshbuf_len(state->input) < aadlen + need + authlen + maclen) return 0; /* packet is incomplete */ #ifdef PACKET_DEBUG fprintf(stderr, "read_poll enc/full: "); sshbuf_dump(state->input, stderr); #endif /* EtM: check mac over encrypted input */ if (mac && mac->enabled && mac->etm) { if ((r = mac_check(mac, state->p_read.seqnr, sshbuf_ptr(state->input), aadlen + need, 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, sshbuf_ptr(state->input), need, aadlen, authlen)) != 0) goto out; if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) goto out; if (mac && mac->enabled) { /* 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; logit("Corrupted MAC on input."); if (need + block_size > PACKET_MAX_SIZE) return SSH_ERR_INTERNAL_ERROR; return ssh_packet_start_discard(ssh, enc, mac, 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; } if (seqnr_p != NULL) *seqnr_p = state->p_read.seqnr; if (++state->p_read.seqnr == 0) { if ((ssh->kex->flags & KEX_INITIAL) != 0) { ssh_packet_disconnect(ssh, "incoming sequence number " "wrapped during initial key exchange"); } logit("incoming seqnr wraps around"); } if (++state->p_read.packets == 0) if (!(ssh->compat & SSH_BUG_NOREKEY)) return SSH_ERR_NEED_REKEY; state->p_read.blocks += (state->packlen + 4) / block_size; state->p_read.bytes += state->packlen + 4; /* get padlen */ padlen = sshbuf_ptr(state->incoming_packet)[4]; DBG(debug("input: padlen %d", padlen)); if (padlen < 4) { if ((r = sshpkt_disconnect(ssh, "Corrupted padlen %d on input.", padlen)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) return r; return SSH_ERR_CONN_CORRUPT; } /* skip packet size + padlen, discard padding */ if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 || ((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0)) goto out; DBG(debug("input: len before de-compress %zd", sshbuf_len(state->incoming_packet))); if (comp && comp->enabled) { 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; DBG(debug("input: len after de-compress %zd", sshbuf_len(state->incoming_packet))); } /* * get packet type, implies consume. * return length of payload (without type field) */ 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) { if ((r = sshpkt_disconnect(ssh, "Invalid ssh2 packet type: %d", *typep)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) return r; return SSH_ERR_PROTOCOL_ERROR; } 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; #ifdef PACKET_DEBUG fprintf(stderr, "read/plain[%d]:\r\n", *typep); sshbuf_dump(state->incoming_packet, stderr); #endif /* reset for next packet */ state->packlen = 0; if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { debug_f("resetting read seqnr %u", state->p_read.seqnr); state->p_read.seqnr = 0; } if ((r = ssh_packet_check_rekey(ssh)) != 0) return r; out: return r; } int ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) { struct session_state *state = ssh->state; u_int reason, seqnr; int r; u_char *msg; const u_char *d; size_t len; for (;;) { msg = NULL; r = ssh_packet_read_poll2(ssh, typep, seqnr_p); if (r != 0) return r; if (*typep == 0) { /* no message ready */ return 0; } state->keep_alive_timeouts = 0; DBG(debug("received packet type %d", *typep)); /* Always process disconnect messages */ if (*typep == 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; } /* * Do not implicitly handle any messages here during initial * KEX when in strict mode. They will be need to be allowed * explicitly by the KEX dispatch table or they will generate * protocol errors. */ if (ssh->kex != NULL && (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) return 0; /* Implicitly handle transport-level messages */ 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 r; } debug("Remote: %.900s", msg); free(msg); break; case SSH2_MSG_UNIMPLEMENTED: if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) return r; debug("Received SSH2_MSG_UNIMPLEMENTED for %u", seqnr); break; case SSH2_MSG_PING: if ((r = sshpkt_get_string_direct(ssh, &d, &len)) != 0) return r; DBG(debug("Received SSH2_MSG_PING len %zu", len)); if (!ssh->state->after_authentication) { DBG(debug("Won't reply to PING in preauth")); break; } if (ssh_packet_is_rekeying(ssh)) { DBG(debug("Won't reply to PING during KEX")); break; } if ((r = sshpkt_start(ssh, SSH2_MSG_PONG)) != 0 || (r = sshpkt_put_string(ssh, d, len)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; break; case SSH2_MSG_PONG: if ((r = sshpkt_get_string_direct(ssh, NULL, &len)) != 0) return r; DBG(debug("Received SSH2_MSG_PONG len %zu", len)); break; default: return 0; } } } /* * Buffers the supplied input data. This is intended to be used together * with packet_read_poll(). */ int ssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len) { struct session_state *state = ssh->state; int r; if (state->packet_discard) { state->keep_alive_timeouts = 0; /* ?? */ if (len >= state->packet_discard) { if ((r = ssh_packet_stop_discard(ssh)) != 0) return r; } state->packet_discard -= len; return 0; } if ((r = sshbuf_put(state->input, buf, len)) != 0) return r; return 0; } /* Reads and buffers data from the specified fd */ int ssh_packet_process_read(struct ssh *ssh, int fd) { struct session_state *state = ssh->state; int r; size_t rlen; if ((r = sshbuf_read(fd, state->input, PACKET_MAX_SIZE, &rlen)) != 0) return r; if (state->packet_discard) { if ((r = sshbuf_consume_end(state->input, rlen)) != 0) return r; state->keep_alive_timeouts = 0; /* ?? */ if (rlen >= state->packet_discard) { if ((r = ssh_packet_stop_discard(ssh)) != 0) return r; } state->packet_discard -= rlen; return 0; } return 0; } int ssh_packet_remaining(struct ssh *ssh) { return sshbuf_len(ssh->state->incoming_packet); } /* * Sends a diagnostic message from the server to the client. This message * can be sent at any time (but not while constructing another message). The * message is printed immediately, but only if the client is being executed * in verbose mode. These messages are primarily intended to ease debugging * authentication problems. The length of the formatted message must not * exceed 1024 bytes. This will automatically call ssh_packet_write_wait. */ void ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) { char buf[1024]; va_list args; int r; if ((ssh->compat & SSH_BUG_DEBUG)) return; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); 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_fr(r, "send DEBUG"); } 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. */ 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: ssh_packet_clear_keys(ssh); logdie("Connection closed by %s", remote_id); case SSH_ERR_CONN_TIMEOUT: 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->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: if (vasprintf(&tag, fmt, ap) == -1) { ssh_packet_clear_keys(ssh); logdie_f("could not allocate failure message"); } ssh_packet_clear_keys(ssh); errno = oerrno; logdie_r(r, "%s%sConnection %s %s", tag != NULL ? tag : "", tag != NULL ? ": " : "", ssh->state->server_side ? "from" : "to", remote_id); } } 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_f("should have exited"); } /* * Logs the error plus constructs and sends a disconnect packet, closes the * connection, and exits. This function never returns. The error message * should not contain a newline. The length of the formatted message must * not exceed 1024 bytes. */ void ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...) { char buf[1024], remote_id[512]; va_list args; static int disconnecting = 0; int r; if (disconnecting) /* Guard against recursive invocations. */ fatal("packet_disconnect called recursively."); disconnecting = 1; /* * 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 %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, r, "%s", __func__); if ((r = ssh_packet_write_wait(ssh)) != 0) sshpkt_fatal(ssh, r, "%s", __func__); /* Close the connection. */ ssh_packet_close(ssh); cleanup_exit(255); } /* * Checks if there is any buffered output, and tries to write some of * the output. */ int ssh_packet_write_poll(struct ssh *ssh) { struct session_state *state = ssh->state; int len = sshbuf_len(state->output); int r; if (len > 0) { 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) return SSH_ERR_CONN_CLOSED; if ((r = sshbuf_consume(state->output, len)) != 0) return r; } return 0; } /* * Calls packet_write_poll repeatedly until all pending output data has been * written. */ int ssh_packet_write_wait(struct ssh *ssh) { int ret, r, ms_remain = 0; struct timeval start; struct timespec timespec, *timespecp = NULL; struct session_state *state = ssh->state; struct pollfd pfd; if ((r = ssh_packet_write_poll(ssh)) != 0) return r; while (ssh_packet_have_data_to_write(ssh)) { pfd.fd = state->connection_out; pfd.events = POLLOUT; if (state->packet_timeout_ms > 0) { ms_remain = state->packet_timeout_ms; timespecp = ×pec; } for (;;) { if (state->packet_timeout_ms > 0) { ms_to_timespec(×pec, ms_remain); monotime_tv(&start); } if ((ret = ppoll(&pfd, 1, timespecp, NULL)) >= 0) break; if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) break; if (state->packet_timeout_ms <= 0) continue; ms_subtract_diff(&start, &ms_remain); if (ms_remain <= 0) { ret = 0; break; } } if (ret == 0) return SSH_ERR_CONN_TIMEOUT; if ((r = ssh_packet_write_poll(ssh)) != 0) return r; } return 0; } /* Returns true if there is buffered data to write to the connection. */ int ssh_packet_have_data_to_write(struct ssh *ssh) { return sshbuf_len(ssh->state->output) != 0; } /* Returns true if there is not too much data to write to the connection. */ int ssh_packet_not_very_much_data_to_write(struct ssh *ssh) { if (ssh->state->interactive_mode) return sshbuf_len(ssh->state->output) < 16384; else return sshbuf_len(ssh->state->output) < 128 * 1024; } /* * returns true when there are at most a few keystrokes of data to write * and the connection is in interactive mode. */ int ssh_packet_interactive_data_to_write(struct ssh *ssh) { return ssh->state->interactive_mode && sshbuf_len(ssh->state->output) < 256; } void ssh_packet_set_tos(struct ssh *ssh, int tos) { if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX) return; set_sock_tos(ssh->state->connection_in, tos); } /* Informs that the current session is interactive. Sets IP flags for that. */ void ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk) { struct session_state *state = ssh->state; if (state->set_interactive_called) return; state->set_interactive_called = 1; /* Record that we are in interactive mode. */ state->interactive_mode = interactive; /* Only set socket options if using a socket. */ if (!ssh_packet_connection_is_on_socket(ssh)) return; set_nodelay(state->connection_in); ssh_packet_set_tos(ssh, interactive ? qos_interactive : qos_bulk); } /* Returns true if the current connection is interactive. */ int ssh_packet_is_interactive(struct ssh *ssh) { return ssh->state->interactive_mode; } int ssh_packet_set_maxsize(struct ssh *ssh, u_int s) { struct session_state *state = ssh->state; if (state->set_maxsize_called) { logit_f("called twice: old %d new %d", state->max_packet_size, s); return -1; } if (s < 4 * 1024 || s > 1024 * 1024) { logit_f("bad size %d", s); return -1; } state->set_maxsize_called = 1; debug_f("setting to %d", s); state->max_packet_size = s; return s; } int ssh_packet_inc_alive_timeouts(struct ssh *ssh) { return ++ssh->state->keep_alive_timeouts; } void ssh_packet_set_alive_timeouts(struct ssh *ssh, int ka) { ssh->state->keep_alive_timeouts = ka; } u_int ssh_packet_get_maxsize(struct ssh *ssh) { return ssh->state->max_packet_size; } void ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t 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; } time_t ssh_packet_get_rekey_timeout(struct ssh *ssh) { time_t seconds; seconds = ssh->state->rekey_time + ssh->state->rekey_interval - monotime(); return (seconds <= 0 ? 1 : seconds); } void ssh_packet_set_server(struct ssh *ssh) { ssh->state->server_side = 1; ssh->kex->server = 1; /* XXX unify? */ } void ssh_packet_set_authenticated(struct ssh *ssh) { ssh->state->after_authentication = 1; } void * ssh_packet_get_input(struct ssh *ssh) { return (void *)ssh->state->input; } void * ssh_packet_get_output(struct ssh *ssh) { return (void *)ssh->state->output; } /* Reset after_authentication and reset compression in post-auth privsep */ static int ssh_packet_set_postauth(struct ssh *ssh) { int r; debug_f("called"); /* This was set in net child, but is not visible in user child */ ssh->state->after_authentication = 1; ssh->state->rekeying = 0; if ((r = ssh_packet_enable_delayed_compress(ssh)) != 0) return r; return 0; } /* Packet state (de-)serialization for privsep */ /* turn kex into a blob for packet state serialization */ static int kex_to_blob(struct sshbuf *m, struct kex *kex) { int r; if ((r = sshbuf_put_u32(m, kex->we_need)) != 0 || (r = sshbuf_put_cstring(m, kex->hostkey_alg)) != 0 || (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 || (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 || (r = sshbuf_put_stringb(m, kex->my)) != 0 || (r = sshbuf_put_stringb(m, kex->peer)) != 0 || (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || (r = sshbuf_put_stringb(m, kex->server_version)) != 0 || (r = sshbuf_put_stringb(m, kex->session_id)) != 0 || (r = sshbuf_put_u32(m, kex->flags)) != 0) return r; return 0; } /* turn key exchange results into a blob for packet state serialization */ static int newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) { struct sshbuf *b; struct sshcipher_ctx *cc; struct sshcomp *comp; struct sshenc *enc; struct sshmac *mac; struct newkeys *newkey; int r; if ((newkey = ssh->state->newkeys[mode]) == NULL) return SSH_ERR_INTERNAL_ERROR; enc = &newkey->enc; mac = &newkey->mac; comp = &newkey->comp; 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; if ((r = sshbuf_put_cstring(b, enc->name)) != 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 || (r = sshbuf_put_string(b, enc->iv, enc->iv_len)) != 0) goto out; if (cipher_authlen(enc->cipher) == 0) { if ((r = sshbuf_put_cstring(b, mac->name)) != 0 || (r = sshbuf_put_u32(b, mac->enabled)) != 0 || (r = sshbuf_put_string(b, mac->key, mac->key_len)) != 0) goto out; } if ((r = sshbuf_put_u32(b, comp->type)) != 0 || (r = sshbuf_put_cstring(b, comp->name)) != 0) goto out; r = sshbuf_put_stringb(m, b); out: sshbuf_free(b); return r; } /* serialize packet state into a blob */ int ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) { struct session_state *state = ssh->state; int r; 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; return 0; } /* restore key exchange results from blob for packet state de-serialization */ static int newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) { struct sshbuf *b = NULL; struct sshcomp *comp; struct sshenc *enc; struct sshmac *mac; struct newkeys *newkey = NULL; size_t keylen, ivlen, maclen; int r; if ((newkey = calloc(1, sizeof(*newkey))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_froms(m, &b)) != 0) goto out; #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif enc = &newkey->enc; mac = &newkey->mac; comp = &newkey->comp; if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 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; if ((r = mac_setup(mac, mac->name)) != 0) goto out; if ((r = sshbuf_get_u32(b, (u_int *)&mac->enabled)) != 0 || (r = sshbuf_get_string(b, &mac->key, &maclen)) != 0) goto out; if (maclen > mac->key_len) { r = SSH_ERR_INVALID_FORMAT; goto out; } mac->key_len = maclen; } if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) goto out; if (sshbuf_len(b) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } enc->key_len = keylen; enc->iv_len = ivlen; ssh->kex->newkeys[mode] = newkey; newkey = NULL; r = 0; out: free(newkey); sshbuf_free(b); return r; } /* restore kex from blob for packet state de-serialization */ static int kex_from_blob(struct sshbuf *m, struct kex **kexp) { struct kex *kex; int r; if ((kex = kex_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_u32(m, &kex->we_need)) != 0 || (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 || (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 || (r = sshbuf_get_stringb(m, kex->my)) != 0 || (r = sshbuf_get_stringb(m, kex->peer)) != 0 || (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || (r = sshbuf_get_stringb(m, kex->server_version)) != 0 || (r = sshbuf_get_stringb(m, kex->session_id)) != 0 || (r = sshbuf_get_u32(m, &kex->flags)) != 0) goto out; kex->server = 1; kex->done = 1; r = 0; out: if (r != 0 || kexp == NULL) { kex_free(kex); if (kexp != NULL) *kexp = NULL; } else { kex_free(*kexp); *kexp = kex; } return r; } /* * Restore packet state from content of blob 'm' (de-serialization). * Note that 'm' will be partially consumed on parsing or any other errors. */ int ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) { struct session_state *state = ssh->state; const u_char *input, *output; size_t ilen, olen; int r; 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 child 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 = ssh_packet_set_postauth(ssh)) != 0) return r; sshbuf_reset(state->input); sshbuf_reset(state->output); if ((r = sshbuf_get_string_direct(m, &input, &ilen)) != 0 || (r = sshbuf_get_string_direct(m, &output, &olen)) != 0 || (r = sshbuf_put(state->input, input, ilen)) != 0 || (r = sshbuf_put(state->output, output, olen)) != 0) return r; if (sshbuf_len(m)) return SSH_ERR_INVALID_FORMAT; debug3_f("done"); return 0; } /* NEW API */ /* put data to the outgoing packet */ int sshpkt_put(struct ssh *ssh, const void *v, size_t len) { return sshbuf_put(ssh->state->outgoing_packet, v, len); } int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b) { return sshbuf_putb(ssh->state->outgoing_packet, b); } int sshpkt_put_u8(struct ssh *ssh, u_char val) { return sshbuf_put_u8(ssh->state->outgoing_packet, val); } int sshpkt_put_u32(struct ssh *ssh, u_int32_t val) { return sshbuf_put_u32(ssh->state->outgoing_packet, val); } int sshpkt_put_u64(struct ssh *ssh, u_int64_t val) { return sshbuf_put_u64(ssh->state->outgoing_packet, val); } int sshpkt_put_string(struct ssh *ssh, const void *v, size_t len) { return sshbuf_put_string(ssh->state->outgoing_packet, v, len); } int sshpkt_put_cstring(struct ssh *ssh, const void *v) { return sshbuf_put_cstring(ssh->state->outgoing_packet, v); } int sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v) { return sshbuf_put_stringb(ssh->state->outgoing_packet, v); } #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC int sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g) { return sshbuf_put_ec(ssh->state->outgoing_packet, v, g); } int sshpkt_put_ec_pkey(struct ssh *ssh, EVP_PKEY *pkey) { return sshbuf_put_ec_pkey(ssh->state->outgoing_packet, pkey); } #endif /* OPENSSL_HAS_ECC */ int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v) { return sshbuf_put_bignum2(ssh->state->outgoing_packet, v); } #endif /* WITH_OPENSSL */ /* fetch data from the incoming packet */ int sshpkt_get(struct ssh *ssh, void *valp, size_t len) { return sshbuf_get(ssh->state->incoming_packet, valp, len); } int sshpkt_get_u8(struct ssh *ssh, u_char *valp) { return sshbuf_get_u8(ssh->state->incoming_packet, valp); } int sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp) { return sshbuf_get_u32(ssh->state->incoming_packet, valp); } int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp) { return sshbuf_get_u64(ssh->state->incoming_packet, valp); } int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp) { return sshbuf_get_string(ssh->state->incoming_packet, valp, lenp); } int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) { return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp); } int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) { return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp); } int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) { return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); } int sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp) { return sshbuf_froms(ssh->state->incoming_packet, valp); } #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g) { return sshbuf_get_ec(ssh->state->incoming_packet, v, g); } #endif /* OPENSSL_HAS_ECC */ int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp) { return sshbuf_get_bignum2(ssh->state->incoming_packet, valp); } #endif /* WITH_OPENSSL */ int sshpkt_get_end(struct ssh *ssh) { if (sshbuf_len(ssh->state->incoming_packet) > 0) return SSH_ERR_UNEXPECTED_TRAILING_DATA; return 0; } const u_char * sshpkt_ptr(struct ssh *ssh, size_t *lenp) { if (lenp != NULL) *lenp = sshbuf_len(ssh->state->incoming_packet); return sshbuf_ptr(ssh->state->incoming_packet); } /* start a new packet */ int sshpkt_start(struct ssh *ssh, u_char type) { u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */ DBG(debug("packet_start[%d]", 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, 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_f("type %u", 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 */ int sshpkt_send(struct ssh *ssh) { if (ssh->state && ssh->state->mux) return ssh_packet_send_mux(ssh); return ssh_packet_send2(ssh); } int sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) { char buf[1024]; va_list args; int r; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); debug2_f("sending SSH2_MSG_DISCONNECT: %s", buf); 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; } /* roundup current message to pad bytes */ int sshpkt_add_padding(struct ssh *ssh, u_char pad) { ssh->state->extra_pad = pad; return 0; } openssh-10.0p1/PaxHeaders.10889/packet.h100644 001750 001750 0000000003614775415623 0014574xustar0030 atime=1744182234.680494057 openssh-10.0p1/packet.h010064400017500001750000000171431477541562300131650ustar00djmdjm/* $OpenBSD: packet.h,v 1.99 2024/08/15 00:51:51 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Interface for the packet protocol functions. * * 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 PACKET_H #define PACKET_H #include #ifdef WITH_OPENSSL # include # include # ifdef OPENSSL_HAS_ECC # include # else /* OPENSSL_HAS_ECC */ # define EC_KEY void # define EC_GROUP void # define EC_POINT void # endif /* OPENSSL_HAS_ECC */ #else /* WITH_OPENSSL */ # define BIGNUM void # define EC_KEY void # define EC_GROUP void # define EC_POINT void # define EVP_PKEY void #endif /* WITH_OPENSSL */ #include #include "openbsd-compat/sys-queue.h" struct kex; struct sshkey; struct sshbuf; struct session_state; /* private session data */ #include "dispatch.h" /* typedef, DISPATCH_MAX */ struct key_entry { TAILQ_ENTRY(key_entry) next; struct sshkey *key; }; struct ssh { /* Session state */ struct session_state *state; /* Key exchange */ struct kex *kex; /* 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]; /* number of packets to ignore in the dispatcher */ int dispatch_skip_packets; /* datafellows */ int compat; /* Lists for private and public keys */ 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); int ssh_packet_stop_discard(struct ssh *); int ssh_packet_connection_af(struct ssh *); void ssh_packet_set_nonblocking(struct ssh *); int ssh_packet_get_connection_in(struct ssh *); int ssh_packet_get_connection_out(struct ssh *); void ssh_packet_close(struct ssh *); 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 *); int ssh_packet_check_rekey(struct ssh *); void ssh_packet_set_protocol_flags(struct ssh *, u_int); u_int ssh_packet_get_protocol_flags(struct ssh *); void ssh_packet_set_tos(struct ssh *, int); void ssh_packet_set_interactive(struct ssh *, int, int, int); int ssh_packet_is_interactive(struct ssh *); void ssh_packet_set_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_send2_wrapped(struct ssh *); int ssh_packet_send2(struct ssh *); int ssh_packet_read(struct ssh *); 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_process_read(struct ssh *, int); int ssh_packet_read_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p); int ssh_packet_read_poll_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p); void ssh_packet_disconnect(struct ssh *, const char *fmt, ...) __attribute__((format(printf, 2, 3))) __attribute__((noreturn)); void ssh_packet_send_debug(struct ssh *, const char *fmt, ...) __attribute__((format(printf, 2, 3))); int ssh_set_newkeys(struct ssh *, int mode); void ssh_packet_get_bytes(struct ssh *, u_int64_t *, u_int64_t *); int ssh_packet_write_poll(struct ssh *); int ssh_packet_write_wait(struct ssh *); int ssh_packet_have_data_to_write(struct ssh *); int ssh_packet_not_very_much_data_to_write(struct ssh *); int ssh_packet_interactive_data_to_write(struct ssh *); int ssh_packet_connection_is_on_socket(struct ssh *); int ssh_packet_remaining(struct ssh *); 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 *); int ssh_packet_set_maxsize(struct ssh *, u_int); u_int ssh_packet_get_maxsize(struct ssh *); 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 *); char *ssh_remote_hostname(struct ssh *); void ssh_packet_set_rekey_limits(struct ssh *, u_int64_t, u_int32_t); time_t ssh_packet_get_rekey_timeout(struct ssh *); void *ssh_packet_get_input(struct ssh *); void *ssh_packet_get_output(struct ssh *); /* new API */ int sshpkt_start(struct ssh *ssh, u_char type); 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, 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); int sshpkt_put_u8(struct ssh *ssh, u_char val); int sshpkt_put_u32(struct ssh *ssh, u_int32_t val); int sshpkt_put_u64(struct ssh *ssh, u_int64_t val); 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_ec_pkey(struct ssh *ssh, EVP_PKEY *pkey); int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v); int sshpkt_get(struct ssh *ssh, void *valp, size_t len); int sshpkt_get_u8(struct ssh *ssh, u_char *valp); 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_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); #if !defined(WITH_OPENSSL) # undef BIGNUM # undef EC_KEY # undef EC_GROUP # undef EC_POINT # undef EVP_PKEY #elif !defined(OPENSSL_HAS_ECC) # undef EC_KEY # undef EC_GROUP # undef EC_POINT #endif #endif /* PACKET_H */ openssh-10.0p1/PaxHeaders.10889/pathnames.h100644 001750 001750 0000000003614775415623 0015305xustar0030 atime=1744182234.680494057 openssh-10.0p1/pathnames.h010064400017500001750000000142741477541562300137000ustar00djmdjm/* $OpenBSD: pathnames.h,v 1.32 2024/05/17 00:30:24 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #define ETCDIR "/etc" #ifndef SSHDIR #define SSHDIR ETCDIR "/ssh" #endif #ifndef _PATH_SSH_PIDDIR #define _PATH_SSH_PIDDIR "/var/run" #endif /* * System-wide file containing host keys of known hosts. This file should be * world-readable. */ #define _PATH_SSH_SYSTEM_HOSTFILE SSHDIR "/ssh_known_hosts" /* backward compat for protocol 2 */ #define _PATH_SSH_SYSTEM_HOSTFILE2 SSHDIR "/ssh_known_hosts2" /* * Of these, ssh_host_key must be readable only by root, whereas ssh_config * should be world-readable. */ #define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config" #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" #define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" #define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key" #define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key" #define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key" #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" #define _PATH_DH_MODULI SSHDIR "/moduli" #ifndef _PATH_SSH_PROGRAM #define _PATH_SSH_PROGRAM "/usr/bin/ssh" #endif /* Binary paths for the sshd components */ #ifndef _PATH_SSHD_SESSION #define _PATH_SSHD_SESSION "/usr/libexec/sshd-session" #endif #ifndef _PATH_SSHD_AUTH #define _PATH_SSHD_AUTH "/usr/libexec/sshd-auth" #endif /* * The process id of the daemon listening for connections is saved here to * make it easier to kill the correct daemon when necessary. */ #define _PATH_SSH_DAEMON_PID_FILE _PATH_SSH_PIDDIR "/sshd.pid" /* * The directory in user's home directory in which the files reside. The * directory should be world-readable (though not all files are). */ #define _PATH_SSH_USER_DIR ".ssh" /* * Per-user file containing host keys of known hosts. This file need not be * readable by anyone except the user him/herself, though this does not * contain anything particularly secret. */ #define _PATH_SSH_USER_HOSTFILE "~/" _PATH_SSH_USER_DIR "/known_hosts" /* backward compat for protocol 2 */ #define _PATH_SSH_USER_HOSTFILE2 "~/" _PATH_SSH_USER_DIR "/known_hosts2" /* * Name of the default file containing client-side authentication key. This * file should only be readable by the user him/herself. */ #define _PATH_SSH_CLIENT_ID_DSA _PATH_SSH_USER_DIR "/id_dsa" #define _PATH_SSH_CLIENT_ID_ECDSA _PATH_SSH_USER_DIR "/id_ecdsa" #define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa" #define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519" #define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" #define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk" #define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk" /* * Configuration file in user's home directory. This file need not be * readable by anyone but the user him/herself, but does not contain anything * particularly secret. If the user's home directory resides on an NFS * volume where root is mapped to nobody, this may need to be world-readable. */ #define _PATH_SSH_USER_CONFFILE _PATH_SSH_USER_DIR "/config" /* * File containing a list of those rsa keys that permit logging in as this * user. This file need not be readable by anyone but the user him/herself, * but does not contain anything particularly secret. If the user's home * directory resides on an NFS volume where root is mapped to nobody, this * may need to be world-readable. (This file is read by the daemon which is * running as root.) */ #define _PATH_SSH_USER_PERMITTED_KEYS _PATH_SSH_USER_DIR "/authorized_keys" /* backward compat for protocol v2 */ #define _PATH_SSH_USER_PERMITTED_KEYS2 _PATH_SSH_USER_DIR "/authorized_keys2" /* * Per-user and system-wide ssh "rc" files. These files are executed with * /bin/sh before starting the shell or command if they exist. They will be * passed "proto cookie" as arguments if X11 forwarding with spoofing is in * use. xauth will be run if neither of these exists. */ #define _PATH_SSH_USER_RC _PATH_SSH_USER_DIR "/rc" #define _PATH_SSH_SYSTEM_RC SSHDIR "/sshrc" /* * Ssh-only version of /etc/hosts.equiv. Additionally, the daemon may use * ~/.rhosts and /etc/hosts.equiv if rhosts authentication is enabled. */ #define _PATH_SSH_HOSTS_EQUIV SSHDIR "/shosts.equiv" #define _PATH_RHOSTS_EQUIV "/etc/hosts.equiv" /* * Default location of askpass */ #ifndef _PATH_SSH_ASKPASS_DEFAULT #define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass" #endif /* Location of ssh-keysign for hostbased authentication */ #ifndef _PATH_SSH_KEY_SIGN #define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign" #endif /* Location of ssh-pkcs11-helper to support keys in tokens */ #ifndef _PATH_SSH_PKCS11_HELPER #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" #endif /* UNIX domain socket for X11 server; displaynum will replace %u */ #ifndef _PATH_UNIX_X #define _PATH_UNIX_X "/tmp/.X11-unix/X%u" #endif /* for scp */ #ifndef _PATH_CP #define _PATH_CP "cp" #endif /* for sftp */ #ifndef _PATH_SFTP_SERVER #define _PATH_SFTP_SERVER "/usr/libexec/sftp-server" #endif /* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */ #ifndef _PATH_PRIVSEP_CHROOT_DIR #define _PATH_PRIVSEP_CHROOT_DIR "/var/empty" #endif /* for passwd change */ #ifndef _PATH_PASSWD_PROG #define _PATH_PASSWD_PROG "/usr/bin/passwd" #endif #ifndef _PATH_LS #define _PATH_LS "ls" #endif /* Askpass program define */ #ifndef ASKPASS_PROGRAM #define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass" #endif /* ASKPASS_PROGRAM */ openssh-10.0p1/PaxHeaders.10889/pkcs11.h100644 001750 001750 0000000003614775415623 0014427xustar0030 atime=1744182234.680494057 openssh-10.0p1/pkcs11.h010064400017500001750000001225761477541562300130270ustar00djmdjm/* $OpenBSD: pkcs11.h,v 1.3 2013/11/26 19:15:09 deraadt Exp $ */ /* pkcs11.h Copyright 2006, 2007 g10 Code GmbH Copyright 2006 Andreas Jellinghaus This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without modifications, as long as this notice is preserved. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, to the extent permitted by law; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* Please submit changes back to the Scute project at http://www.scute.org/ (or send them to marcus@g10code.com), so that they can be picked up by other projects from there as well. */ /* This file is a modified implementation of the PKCS #11 standard by RSA Security Inc. It is mostly a drop-in replacement, with the following change: This header file does not require any macro definitions by the user (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros for you (if useful, some are missing, let me know if you need more). There is an additional API available that does comply better to the GNU coding standard. It can be switched on by defining CRYPTOKI_GNU before including this header file. For this, the following changes are made to the specification: All structure types are changed to a "struct ck_foo" where CK_FOO is the type name in PKCS #11. All non-structure types are changed to ck_foo_t where CK_FOO is the lowercase version of the type name in PKCS #11. The basic types (CK_ULONG et al.) are removed without substitute. All members of structures are modified in the following way: Type indication prefixes are removed, and underscore characters are inserted before words. Then the result is lowercased. Note that function names are still in the original case, as they need for ABI compatibility. CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use . If CRYPTOKI_COMPAT is defined before including this header file, then none of the API changes above take place, and the API is the one defined by the PKCS #11 standard. */ #ifndef PKCS11_H #define PKCS11_H 1 #if defined(__cplusplus) extern "C" { #endif /* The version of cryptoki we implement. The revision is changed with each modification of this file. If you do not use the "official" version of this file, please consider deleting the revision macro (you may use a macro with a different name to keep track of your versions). */ #define CRYPTOKI_VERSION_MAJOR 2 #define CRYPTOKI_VERSION_MINOR 20 #define CRYPTOKI_VERSION_REVISION 6 /* Compatibility interface is default, unless CRYPTOKI_GNU is given. */ #ifndef CRYPTOKI_GNU #ifndef CRYPTOKI_COMPAT #define CRYPTOKI_COMPAT 1 #endif #endif /* System dependencies. */ #if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) /* There is a matching pop below. */ #pragma pack(push, cryptoki, 1) #ifdef CRYPTOKI_EXPORTS #define CK_SPEC __declspec(dllexport) #else #define CK_SPEC __declspec(dllimport) #endif #else #define CK_SPEC #endif #ifdef CRYPTOKI_COMPAT /* If we are in compatibility mode, switch all exposed names to the PKCS #11 variant. There are corresponding #undefs below. */ #define ck_flags_t CK_FLAGS #define ck_version _CK_VERSION #define ck_info _CK_INFO #define cryptoki_version cryptokiVersion #define manufacturer_id manufacturerID #define library_description libraryDescription #define library_version libraryVersion #define ck_notification_t CK_NOTIFICATION #define ck_slot_id_t CK_SLOT_ID #define ck_slot_info _CK_SLOT_INFO #define slot_description slotDescription #define hardware_version hardwareVersion #define firmware_version firmwareVersion #define ck_token_info _CK_TOKEN_INFO #define serial_number serialNumber #define max_session_count ulMaxSessionCount #define session_count ulSessionCount #define max_rw_session_count ulMaxRwSessionCount #define rw_session_count ulRwSessionCount #define max_pin_len ulMaxPinLen #define min_pin_len ulMinPinLen #define total_public_memory ulTotalPublicMemory #define free_public_memory ulFreePublicMemory #define total_private_memory ulTotalPrivateMemory #define free_private_memory ulFreePrivateMemory #define utc_time utcTime #define ck_session_handle_t CK_SESSION_HANDLE #define ck_user_type_t CK_USER_TYPE #define ck_state_t CK_STATE #define ck_session_info _CK_SESSION_INFO #define slot_id slotID #define device_error ulDeviceError #define ck_object_handle_t CK_OBJECT_HANDLE #define ck_object_class_t CK_OBJECT_CLASS #define ck_hw_feature_type_t CK_HW_FEATURE_TYPE #define ck_key_type_t CK_KEY_TYPE #define ck_certificate_type_t CK_CERTIFICATE_TYPE #define ck_attribute_type_t CK_ATTRIBUTE_TYPE #define ck_attribute _CK_ATTRIBUTE #define value pValue #define value_len ulValueLen #define ck_date _CK_DATE #define ck_mechanism_type_t CK_MECHANISM_TYPE #define ck_mechanism _CK_MECHANISM #define parameter pParameter #define parameter_len ulParameterLen #define ck_mechanism_info _CK_MECHANISM_INFO #define min_key_size ulMinKeySize #define max_key_size ulMaxKeySize #define ck_rv_t CK_RV #define ck_notify_t CK_NOTIFY #define ck_function_list _CK_FUNCTION_LIST #define ck_createmutex_t CK_CREATEMUTEX #define ck_destroymutex_t CK_DESTROYMUTEX #define ck_lockmutex_t CK_LOCKMUTEX #define ck_unlockmutex_t CK_UNLOCKMUTEX #define ck_c_initialize_args _CK_C_INITIALIZE_ARGS #define create_mutex CreateMutex #define destroy_mutex DestroyMutex #define lock_mutex LockMutex #define unlock_mutex UnlockMutex #define reserved pReserved #endif /* CRYPTOKI_COMPAT */ typedef unsigned long ck_flags_t; struct ck_version { unsigned char major; unsigned char minor; }; struct ck_info { struct ck_version cryptoki_version; unsigned char manufacturer_id[32]; ck_flags_t flags; unsigned char library_description[32]; struct ck_version library_version; }; typedef unsigned long ck_notification_t; #define CKN_SURRENDER (0) typedef unsigned long ck_slot_id_t; struct ck_slot_info { unsigned char slot_description[64]; unsigned char manufacturer_id[32]; ck_flags_t flags; struct ck_version hardware_version; struct ck_version firmware_version; }; #define CKF_TOKEN_PRESENT (1 << 0) #define CKF_REMOVABLE_DEVICE (1 << 1) #define CKF_HW_SLOT (1 << 2) #define CKF_ARRAY_ATTRIBUTE (1 << 30) struct ck_token_info { unsigned char label[32]; unsigned char manufacturer_id[32]; unsigned char model[16]; unsigned char serial_number[16]; ck_flags_t flags; unsigned long max_session_count; unsigned long session_count; unsigned long max_rw_session_count; unsigned long rw_session_count; unsigned long max_pin_len; unsigned long min_pin_len; unsigned long total_public_memory; unsigned long free_public_memory; unsigned long total_private_memory; unsigned long free_private_memory; struct ck_version hardware_version; struct ck_version firmware_version; unsigned char utc_time[16]; }; #define CKF_RNG (1 << 0) #define CKF_WRITE_PROTECTED (1 << 1) #define CKF_LOGIN_REQUIRED (1 << 2) #define CKF_USER_PIN_INITIALIZED (1 << 3) #define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5) #define CKF_CLOCK_ON_TOKEN (1 << 6) #define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8) #define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9) #define CKF_TOKEN_INITIALIZED (1 << 10) #define CKF_SECONDARY_AUTHENTICATION (1 << 11) #define CKF_USER_PIN_COUNT_LOW (1 << 16) #define CKF_USER_PIN_FINAL_TRY (1 << 17) #define CKF_USER_PIN_LOCKED (1 << 18) #define CKF_USER_PIN_TO_BE_CHANGED (1 << 19) #define CKF_SO_PIN_COUNT_LOW (1 << 20) #define CKF_SO_PIN_FINAL_TRY (1 << 21) #define CKF_SO_PIN_LOCKED (1 << 22) #define CKF_SO_PIN_TO_BE_CHANGED (1 << 23) #define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1) #define CK_EFFECTIVELY_INFINITE (0) typedef unsigned long ck_session_handle_t; #define CK_INVALID_HANDLE (0) typedef unsigned long ck_user_type_t; #define CKU_SO (0) #define CKU_USER (1) #define CKU_CONTEXT_SPECIFIC (2) typedef unsigned long ck_state_t; #define CKS_RO_PUBLIC_SESSION (0) #define CKS_RO_USER_FUNCTIONS (1) #define CKS_RW_PUBLIC_SESSION (2) #define CKS_RW_USER_FUNCTIONS (3) #define CKS_RW_SO_FUNCTIONS (4) struct ck_session_info { ck_slot_id_t slot_id; ck_state_t state; ck_flags_t flags; unsigned long device_error; }; #define CKF_RW_SESSION (1 << 1) #define CKF_SERIAL_SESSION (1 << 2) typedef unsigned long ck_object_handle_t; typedef unsigned long ck_object_class_t; #define CKO_DATA (0) #define CKO_CERTIFICATE (1) #define CKO_PUBLIC_KEY (2) #define CKO_PRIVATE_KEY (3) #define CKO_SECRET_KEY (4) #define CKO_HW_FEATURE (5) #define CKO_DOMAIN_PARAMETERS (6) #define CKO_MECHANISM (7) #define CKO_VENDOR_DEFINED (1U << 31) typedef unsigned long ck_hw_feature_type_t; #define CKH_MONOTONIC_COUNTER (1) #define CKH_CLOCK (2) #define CKH_USER_INTERFACE (3) #define CKH_VENDOR_DEFINED (1U << 31) typedef unsigned long ck_key_type_t; #define CKK_RSA (0) #define CKK_DSA (1) #define CKK_DH (2) #define CKK_ECDSA (3) #define CKK_EC (3) #define CKK_X9_42_DH (4) #define CKK_KEA (5) #define CKK_GENERIC_SECRET (0x10) #define CKK_RC2 (0x11) #define CKK_RC4 (0x12) #define CKK_DES (0x13) #define CKK_DES2 (0x14) #define CKK_DES3 (0x15) #define CKK_CAST (0x16) #define CKK_CAST3 (0x17) #define CKK_CAST128 (0x18) #define CKK_RC5 (0x19) #define CKK_IDEA (0x1a) #define CKK_SKIPJACK (0x1b) #define CKK_BATON (0x1c) #define CKK_JUNIPER (0x1d) #define CKK_CDMF (0x1e) #define CKK_AES (0x1f) #define CKK_BLOWFISH (0x20) #define CKK_TWOFISH (0x21) #define CKK_VENDOR_DEFINED (1U << 31) typedef unsigned long ck_certificate_type_t; #define CKC_X_509 (0) #define CKC_X_509_ATTR_CERT (1) #define CKC_WTLS (2) #define CKC_VENDOR_DEFINED (1U << 31) typedef unsigned long ck_attribute_type_t; #define CKA_CLASS (0) #define CKA_TOKEN (1) #define CKA_PRIVATE (2) #define CKA_LABEL (3) #define CKA_APPLICATION (0x10) #define CKA_VALUE (0x11) #define CKA_OBJECT_ID (0x12) #define CKA_CERTIFICATE_TYPE (0x80) #define CKA_ISSUER (0x81) #define CKA_SERIAL_NUMBER (0x82) #define CKA_AC_ISSUER (0x83) #define CKA_OWNER (0x84) #define CKA_ATTR_TYPES (0x85) #define CKA_TRUSTED (0x86) #define CKA_CERTIFICATE_CATEGORY (0x87) #define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88) #define CKA_URL (0x89) #define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a) #define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b) #define CKA_CHECK_VALUE (0x90) #define CKA_KEY_TYPE (0x100) #define CKA_SUBJECT (0x101) #define CKA_ID (0x102) #define CKA_SENSITIVE (0x103) #define CKA_ENCRYPT (0x104) #define CKA_DECRYPT (0x105) #define CKA_WRAP (0x106) #define CKA_UNWRAP (0x107) #define CKA_SIGN (0x108) #define CKA_SIGN_RECOVER (0x109) #define CKA_VERIFY (0x10a) #define CKA_VERIFY_RECOVER (0x10b) #define CKA_DERIVE (0x10c) #define CKA_START_DATE (0x110) #define CKA_END_DATE (0x111) #define CKA_MODULUS (0x120) #define CKA_MODULUS_BITS (0x121) #define CKA_PUBLIC_EXPONENT (0x122) #define CKA_PRIVATE_EXPONENT (0x123) #define CKA_PRIME_1 (0x124) #define CKA_PRIME_2 (0x125) #define CKA_EXPONENT_1 (0x126) #define CKA_EXPONENT_2 (0x127) #define CKA_COEFFICIENT (0x128) #define CKA_PRIME (0x130) #define CKA_SUBPRIME (0x131) #define CKA_BASE (0x132) #define CKA_PRIME_BITS (0x133) #define CKA_SUB_PRIME_BITS (0x134) #define CKA_VALUE_BITS (0x160) #define CKA_VALUE_LEN (0x161) #define CKA_EXTRACTABLE (0x162) #define CKA_LOCAL (0x163) #define CKA_NEVER_EXTRACTABLE (0x164) #define CKA_ALWAYS_SENSITIVE (0x165) #define CKA_KEY_GEN_MECHANISM (0x166) #define CKA_MODIFIABLE (0x170) #define CKA_ECDSA_PARAMS (0x180) #define CKA_EC_PARAMS (0x180) #define CKA_EC_POINT (0x181) #define CKA_SECONDARY_AUTH (0x200) #define CKA_AUTH_PIN_FLAGS (0x201) #define CKA_ALWAYS_AUTHENTICATE (0x202) #define CKA_WRAP_WITH_TRUSTED (0x210) #define CKA_HW_FEATURE_TYPE (0x300) #define CKA_RESET_ON_INIT (0x301) #define CKA_HAS_RESET (0x302) #define CKA_PIXEL_X (0x400) #define CKA_PIXEL_Y (0x401) #define CKA_RESOLUTION (0x402) #define CKA_CHAR_ROWS (0x403) #define CKA_CHAR_COLUMNS (0x404) #define CKA_COLOR (0x405) #define CKA_BITS_PER_PIXEL (0x406) #define CKA_CHAR_SETS (0x480) #define CKA_ENCODING_METHODS (0x481) #define CKA_MIME_TYPES (0x482) #define CKA_MECHANISM_TYPE (0x500) #define CKA_REQUIRED_CMS_ATTRIBUTES (0x501) #define CKA_DEFAULT_CMS_ATTRIBUTES (0x502) #define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503) #define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211) #define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212) #define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) #define CKA_VENDOR_DEFINED (1U << 31) struct ck_attribute { ck_attribute_type_t type; void *value; unsigned long value_len; }; struct ck_date { unsigned char year[4]; unsigned char month[2]; unsigned char day[2]; }; typedef unsigned long ck_mechanism_type_t; #define CKM_RSA_PKCS_KEY_PAIR_GEN (0) #define CKM_RSA_PKCS (1) #define CKM_RSA_9796 (2) #define CKM_RSA_X_509 (3) #define CKM_MD2_RSA_PKCS (4) #define CKM_MD5_RSA_PKCS (5) #define CKM_SHA1_RSA_PKCS (6) #define CKM_RIPEMD128_RSA_PKCS (7) #define CKM_RIPEMD160_RSA_PKCS (8) #define CKM_RSA_PKCS_OAEP (9) #define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa) #define CKM_RSA_X9_31 (0xb) #define CKM_SHA1_RSA_X9_31 (0xc) #define CKM_RSA_PKCS_PSS (0xd) #define CKM_SHA1_RSA_PKCS_PSS (0xe) #define CKM_DSA_KEY_PAIR_GEN (0x10) #define CKM_DSA (0x11) #define CKM_DSA_SHA1 (0x12) #define CKM_DH_PKCS_KEY_PAIR_GEN (0x20) #define CKM_DH_PKCS_DERIVE (0x21) #define CKM_X9_42_DH_KEY_PAIR_GEN (0x30) #define CKM_X9_42_DH_DERIVE (0x31) #define CKM_X9_42_DH_HYBRID_DERIVE (0x32) #define CKM_X9_42_MQV_DERIVE (0x33) #define CKM_SHA256_RSA_PKCS (0x40) #define CKM_SHA384_RSA_PKCS (0x41) #define CKM_SHA512_RSA_PKCS (0x42) #define CKM_SHA256_RSA_PKCS_PSS (0x43) #define CKM_SHA384_RSA_PKCS_PSS (0x44) #define CKM_SHA512_RSA_PKCS_PSS (0x45) #define CKM_RC2_KEY_GEN (0x100) #define CKM_RC2_ECB (0x101) #define CKM_RC2_CBC (0x102) #define CKM_RC2_MAC (0x103) #define CKM_RC2_MAC_GENERAL (0x104) #define CKM_RC2_CBC_PAD (0x105) #define CKM_RC4_KEY_GEN (0x110) #define CKM_RC4 (0x111) #define CKM_DES_KEY_GEN (0x120) #define CKM_DES_ECB (0x121) #define CKM_DES_CBC (0x122) #define CKM_DES_MAC (0x123) #define CKM_DES_MAC_GENERAL (0x124) #define CKM_DES_CBC_PAD (0x125) #define CKM_DES2_KEY_GEN (0x130) #define CKM_DES3_KEY_GEN (0x131) #define CKM_DES3_ECB (0x132) #define CKM_DES3_CBC (0x133) #define CKM_DES3_MAC (0x134) #define CKM_DES3_MAC_GENERAL (0x135) #define CKM_DES3_CBC_PAD (0x136) #define CKM_CDMF_KEY_GEN (0x140) #define CKM_CDMF_ECB (0x141) #define CKM_CDMF_CBC (0x142) #define CKM_CDMF_MAC (0x143) #define CKM_CDMF_MAC_GENERAL (0x144) #define CKM_CDMF_CBC_PAD (0x145) #define CKM_MD2 (0x200) #define CKM_MD2_HMAC (0x201) #define CKM_MD2_HMAC_GENERAL (0x202) #define CKM_MD5 (0x210) #define CKM_MD5_HMAC (0x211) #define CKM_MD5_HMAC_GENERAL (0x212) #define CKM_SHA_1 (0x220) #define CKM_SHA_1_HMAC (0x221) #define CKM_SHA_1_HMAC_GENERAL (0x222) #define CKM_RIPEMD128 (0x230) #define CKM_RIPEMD128_HMAC (0x231) #define CKM_RIPEMD128_HMAC_GENERAL (0x232) #define CKM_RIPEMD160 (0x240) #define CKM_RIPEMD160_HMAC (0x241) #define CKM_RIPEMD160_HMAC_GENERAL (0x242) #define CKM_SHA256 (0x250) #define CKM_SHA256_HMAC (0x251) #define CKM_SHA256_HMAC_GENERAL (0x252) #define CKM_SHA384 (0x260) #define CKM_SHA384_HMAC (0x261) #define CKM_SHA384_HMAC_GENERAL (0x262) #define CKM_SHA512 (0x270) #define CKM_SHA512_HMAC (0x271) #define CKM_SHA512_HMAC_GENERAL (0x272) #define CKM_CAST_KEY_GEN (0x300) #define CKM_CAST_ECB (0x301) #define CKM_CAST_CBC (0x302) #define CKM_CAST_MAC (0x303) #define CKM_CAST_MAC_GENERAL (0x304) #define CKM_CAST_CBC_PAD (0x305) #define CKM_CAST3_KEY_GEN (0x310) #define CKM_CAST3_ECB (0x311) #define CKM_CAST3_CBC (0x312) #define CKM_CAST3_MAC (0x313) #define CKM_CAST3_MAC_GENERAL (0x314) #define CKM_CAST3_CBC_PAD (0x315) #define CKM_CAST5_KEY_GEN (0x320) #define CKM_CAST128_KEY_GEN (0x320) #define CKM_CAST5_ECB (0x321) #define CKM_CAST128_ECB (0x321) #define CKM_CAST5_CBC (0x322) #define CKM_CAST128_CBC (0x322) #define CKM_CAST5_MAC (0x323) #define CKM_CAST128_MAC (0x323) #define CKM_CAST5_MAC_GENERAL (0x324) #define CKM_CAST128_MAC_GENERAL (0x324) #define CKM_CAST5_CBC_PAD (0x325) #define CKM_CAST128_CBC_PAD (0x325) #define CKM_RC5_KEY_GEN (0x330) #define CKM_RC5_ECB (0x331) #define CKM_RC5_CBC (0x332) #define CKM_RC5_MAC (0x333) #define CKM_RC5_MAC_GENERAL (0x334) #define CKM_RC5_CBC_PAD (0x335) #define CKM_IDEA_KEY_GEN (0x340) #define CKM_IDEA_ECB (0x341) #define CKM_IDEA_CBC (0x342) #define CKM_IDEA_MAC (0x343) #define CKM_IDEA_MAC_GENERAL (0x344) #define CKM_IDEA_CBC_PAD (0x345) #define CKM_GENERIC_SECRET_KEY_GEN (0x350) #define CKM_CONCATENATE_BASE_AND_KEY (0x360) #define CKM_CONCATENATE_BASE_AND_DATA (0x362) #define CKM_CONCATENATE_DATA_AND_BASE (0x363) #define CKM_XOR_BASE_AND_DATA (0x364) #define CKM_EXTRACT_KEY_FROM_KEY (0x365) #define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370) #define CKM_SSL3_MASTER_KEY_DERIVE (0x371) #define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372) #define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373) #define CKM_TLS_PRE_MASTER_KEY_GEN (0x374) #define CKM_TLS_MASTER_KEY_DERIVE (0x375) #define CKM_TLS_KEY_AND_MAC_DERIVE (0x376) #define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377) #define CKM_SSL3_MD5_MAC (0x380) #define CKM_SSL3_SHA1_MAC (0x381) #define CKM_MD5_KEY_DERIVATION (0x390) #define CKM_MD2_KEY_DERIVATION (0x391) #define CKM_SHA1_KEY_DERIVATION (0x392) #define CKM_PBE_MD2_DES_CBC (0x3a0) #define CKM_PBE_MD5_DES_CBC (0x3a1) #define CKM_PBE_MD5_CAST_CBC (0x3a2) #define CKM_PBE_MD5_CAST3_CBC (0x3a3) #define CKM_PBE_MD5_CAST5_CBC (0x3a4) #define CKM_PBE_MD5_CAST128_CBC (0x3a4) #define CKM_PBE_SHA1_CAST5_CBC (0x3a5) #define CKM_PBE_SHA1_CAST128_CBC (0x3a5) #define CKM_PBE_SHA1_RC4_128 (0x3a6) #define CKM_PBE_SHA1_RC4_40 (0x3a7) #define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8) #define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9) #define CKM_PBE_SHA1_RC2_128_CBC (0x3aa) #define CKM_PBE_SHA1_RC2_40_CBC (0x3ab) #define CKM_PKCS5_PBKD2 (0x3b0) #define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0) #define CKM_KEY_WRAP_LYNKS (0x400) #define CKM_KEY_WRAP_SET_OAEP (0x401) #define CKM_SKIPJACK_KEY_GEN (0x1000) #define CKM_SKIPJACK_ECB64 (0x1001) #define CKM_SKIPJACK_CBC64 (0x1002) #define CKM_SKIPJACK_OFB64 (0x1003) #define CKM_SKIPJACK_CFB64 (0x1004) #define CKM_SKIPJACK_CFB32 (0x1005) #define CKM_SKIPJACK_CFB16 (0x1006) #define CKM_SKIPJACK_CFB8 (0x1007) #define CKM_SKIPJACK_WRAP (0x1008) #define CKM_SKIPJACK_PRIVATE_WRAP (0x1009) #define CKM_SKIPJACK_RELAYX (0x100a) #define CKM_KEA_KEY_PAIR_GEN (0x1010) #define CKM_KEA_KEY_DERIVE (0x1011) #define CKM_FORTEZZA_TIMESTAMP (0x1020) #define CKM_BATON_KEY_GEN (0x1030) #define CKM_BATON_ECB128 (0x1031) #define CKM_BATON_ECB96 (0x1032) #define CKM_BATON_CBC128 (0x1033) #define CKM_BATON_COUNTER (0x1034) #define CKM_BATON_SHUFFLE (0x1035) #define CKM_BATON_WRAP (0x1036) #define CKM_ECDSA_KEY_PAIR_GEN (0x1040) #define CKM_EC_KEY_PAIR_GEN (0x1040) #define CKM_ECDSA (0x1041) #define CKM_ECDSA_SHA1 (0x1042) #define CKM_ECDH1_DERIVE (0x1050) #define CKM_ECDH1_COFACTOR_DERIVE (0x1051) #define CKM_ECMQV_DERIVE (0x1052) #define CKM_JUNIPER_KEY_GEN (0x1060) #define CKM_JUNIPER_ECB128 (0x1061) #define CKM_JUNIPER_CBC128 (0x1062) #define CKM_JUNIPER_COUNTER (0x1063) #define CKM_JUNIPER_SHUFFLE (0x1064) #define CKM_JUNIPER_WRAP (0x1065) #define CKM_FASTHASH (0x1070) #define CKM_AES_KEY_GEN (0x1080) #define CKM_AES_ECB (0x1081) #define CKM_AES_CBC (0x1082) #define CKM_AES_MAC (0x1083) #define CKM_AES_MAC_GENERAL (0x1084) #define CKM_AES_CBC_PAD (0x1085) #define CKM_DSA_PARAMETER_GEN (0x2000) #define CKM_DH_PKCS_PARAMETER_GEN (0x2001) #define CKM_X9_42_DH_PARAMETER_GEN (0x2002) #define CKM_VENDOR_DEFINED (1U << 31) struct ck_mechanism { ck_mechanism_type_t mechanism; void *parameter; unsigned long parameter_len; }; struct ck_mechanism_info { unsigned long min_key_size; unsigned long max_key_size; ck_flags_t flags; }; #define CKF_HW (1 << 0) #define CKF_ENCRYPT (1 << 8) #define CKF_DECRYPT (1 << 9) #define CKF_DIGEST (1 << 10) #define CKF_SIGN (1 << 11) #define CKF_SIGN_RECOVER (1 << 12) #define CKF_VERIFY (1 << 13) #define CKF_VERIFY_RECOVER (1 << 14) #define CKF_GENERATE (1 << 15) #define CKF_GENERATE_KEY_PAIR (1 << 16) #define CKF_WRAP (1 << 17) #define CKF_UNWRAP (1 << 18) #define CKF_DERIVE (1 << 19) #define CKF_EXTENSION (1U << 31) /* Flags for C_WaitForSlotEvent. */ #define CKF_DONT_BLOCK (1) typedef unsigned long ck_rv_t; typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session, ck_notification_t event, void *application); /* Forward reference. */ struct ck_function_list; #define _CK_DECLARE_FUNCTION(name, args) \ typedef ck_rv_t (*CK_ ## name) args; \ ck_rv_t CK_SPEC name args _CK_DECLARE_FUNCTION (C_Initialize, (void *init_args)); _CK_DECLARE_FUNCTION (C_Finalize, (void *reserved)); _CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info)); _CK_DECLARE_FUNCTION (C_GetFunctionList, (struct ck_function_list **function_list)); _CK_DECLARE_FUNCTION (C_GetSlotList, (unsigned char token_present, ck_slot_id_t *slot_list, unsigned long *count)); _CK_DECLARE_FUNCTION (C_GetSlotInfo, (ck_slot_id_t slot_id, struct ck_slot_info *info)); _CK_DECLARE_FUNCTION (C_GetTokenInfo, (ck_slot_id_t slot_id, struct ck_token_info *info)); _CK_DECLARE_FUNCTION (C_WaitForSlotEvent, (ck_flags_t flags, ck_slot_id_t *slot, void *reserved)); _CK_DECLARE_FUNCTION (C_GetMechanismList, (ck_slot_id_t slot_id, ck_mechanism_type_t *mechanism_list, unsigned long *count)); _CK_DECLARE_FUNCTION (C_GetMechanismInfo, (ck_slot_id_t slot_id, ck_mechanism_type_t type, struct ck_mechanism_info *info)); _CK_DECLARE_FUNCTION (C_InitToken, (ck_slot_id_t slot_id, unsigned char *pin, unsigned long pin_len, unsigned char *label)); _CK_DECLARE_FUNCTION (C_InitPIN, (ck_session_handle_t session, unsigned char *pin, unsigned long pin_len)); _CK_DECLARE_FUNCTION (C_SetPIN, (ck_session_handle_t session, unsigned char *old_pin, unsigned long old_len, unsigned char *new_pin, unsigned long new_len)); _CK_DECLARE_FUNCTION (C_OpenSession, (ck_slot_id_t slot_id, ck_flags_t flags, void *application, ck_notify_t notify, ck_session_handle_t *session)); _CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session)); _CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id)); _CK_DECLARE_FUNCTION (C_GetSessionInfo, (ck_session_handle_t session, struct ck_session_info *info)); _CK_DECLARE_FUNCTION (C_GetOperationState, (ck_session_handle_t session, unsigned char *operation_state, unsigned long *operation_state_len)); _CK_DECLARE_FUNCTION (C_SetOperationState, (ck_session_handle_t session, unsigned char *operation_state, unsigned long operation_state_len, ck_object_handle_t encryption_key, ck_object_handle_t authentiation_key)); _CK_DECLARE_FUNCTION (C_Login, (ck_session_handle_t session, ck_user_type_t user_type, unsigned char *pin, unsigned long pin_len)); _CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session)); _CK_DECLARE_FUNCTION (C_CreateObject, (ck_session_handle_t session, struct ck_attribute *templ, unsigned long count, ck_object_handle_t *object)); _CK_DECLARE_FUNCTION (C_CopyObject, (ck_session_handle_t session, ck_object_handle_t object, struct ck_attribute *templ, unsigned long count, ck_object_handle_t *new_object)); _CK_DECLARE_FUNCTION (C_DestroyObject, (ck_session_handle_t session, ck_object_handle_t object)); _CK_DECLARE_FUNCTION (C_GetObjectSize, (ck_session_handle_t session, ck_object_handle_t object, unsigned long *size)); _CK_DECLARE_FUNCTION (C_GetAttributeValue, (ck_session_handle_t session, ck_object_handle_t object, struct ck_attribute *templ, unsigned long count)); _CK_DECLARE_FUNCTION (C_SetAttributeValue, (ck_session_handle_t session, ck_object_handle_t object, struct ck_attribute *templ, unsigned long count)); _CK_DECLARE_FUNCTION (C_FindObjectsInit, (ck_session_handle_t session, struct ck_attribute *templ, unsigned long count)); _CK_DECLARE_FUNCTION (C_FindObjects, (ck_session_handle_t session, ck_object_handle_t *object, unsigned long max_object_count, unsigned long *object_count)); _CK_DECLARE_FUNCTION (C_FindObjectsFinal, (ck_session_handle_t session)); _CK_DECLARE_FUNCTION (C_EncryptInit, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t key)); _CK_DECLARE_FUNCTION (C_Encrypt, (ck_session_handle_t session, unsigned char *data, unsigned long data_len, unsigned char *encrypted_data, unsigned long *encrypted_data_len)); _CK_DECLARE_FUNCTION (C_EncryptUpdate, (ck_session_handle_t session, unsigned char *part, unsigned long part_len, unsigned char *encrypted_part, unsigned long *encrypted_part_len)); _CK_DECLARE_FUNCTION (C_EncryptFinal, (ck_session_handle_t session, unsigned char *last_encrypted_part, unsigned long *last_encrypted_part_len)); _CK_DECLARE_FUNCTION (C_DecryptInit, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t key)); _CK_DECLARE_FUNCTION (C_Decrypt, (ck_session_handle_t session, unsigned char *encrypted_data, unsigned long encrypted_data_len, unsigned char *data, unsigned long *data_len)); _CK_DECLARE_FUNCTION (C_DecryptUpdate, (ck_session_handle_t session, unsigned char *encrypted_part, unsigned long encrypted_part_len, unsigned char *part, unsigned long *part_len)); _CK_DECLARE_FUNCTION (C_DecryptFinal, (ck_session_handle_t session, unsigned char *last_part, unsigned long *last_part_len)); _CK_DECLARE_FUNCTION (C_DigestInit, (ck_session_handle_t session, struct ck_mechanism *mechanism)); _CK_DECLARE_FUNCTION (C_Digest, (ck_session_handle_t session, unsigned char *data, unsigned long data_len, unsigned char *digest, unsigned long *digest_len)); _CK_DECLARE_FUNCTION (C_DigestUpdate, (ck_session_handle_t session, unsigned char *part, unsigned long part_len)); _CK_DECLARE_FUNCTION (C_DigestKey, (ck_session_handle_t session, ck_object_handle_t key)); _CK_DECLARE_FUNCTION (C_DigestFinal, (ck_session_handle_t session, unsigned char *digest, unsigned long *digest_len)); _CK_DECLARE_FUNCTION (C_SignInit, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t key)); _CK_DECLARE_FUNCTION (C_Sign, (ck_session_handle_t session, unsigned char *data, unsigned long data_len, unsigned char *signature, unsigned long *signature_len)); _CK_DECLARE_FUNCTION (C_SignUpdate, (ck_session_handle_t session, unsigned char *part, unsigned long part_len)); _CK_DECLARE_FUNCTION (C_SignFinal, (ck_session_handle_t session, unsigned char *signature, unsigned long *signature_len)); _CK_DECLARE_FUNCTION (C_SignRecoverInit, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t key)); _CK_DECLARE_FUNCTION (C_SignRecover, (ck_session_handle_t session, unsigned char *data, unsigned long data_len, unsigned char *signature, unsigned long *signature_len)); _CK_DECLARE_FUNCTION (C_VerifyInit, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t key)); _CK_DECLARE_FUNCTION (C_Verify, (ck_session_handle_t session, unsigned char *data, unsigned long data_len, unsigned char *signature, unsigned long signature_len)); _CK_DECLARE_FUNCTION (C_VerifyUpdate, (ck_session_handle_t session, unsigned char *part, unsigned long part_len)); _CK_DECLARE_FUNCTION (C_VerifyFinal, (ck_session_handle_t session, unsigned char *signature, unsigned long signature_len)); _CK_DECLARE_FUNCTION (C_VerifyRecoverInit, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t key)); _CK_DECLARE_FUNCTION (C_VerifyRecover, (ck_session_handle_t session, unsigned char *signature, unsigned long signature_len, unsigned char *data, unsigned long *data_len)); _CK_DECLARE_FUNCTION (C_DigestEncryptUpdate, (ck_session_handle_t session, unsigned char *part, unsigned long part_len, unsigned char *encrypted_part, unsigned long *encrypted_part_len)); _CK_DECLARE_FUNCTION (C_DecryptDigestUpdate, (ck_session_handle_t session, unsigned char *encrypted_part, unsigned long encrypted_part_len, unsigned char *part, unsigned long *part_len)); _CK_DECLARE_FUNCTION (C_SignEncryptUpdate, (ck_session_handle_t session, unsigned char *part, unsigned long part_len, unsigned char *encrypted_part, unsigned long *encrypted_part_len)); _CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate, (ck_session_handle_t session, unsigned char *encrypted_part, unsigned long encrypted_part_len, unsigned char *part, unsigned long *part_len)); _CK_DECLARE_FUNCTION (C_GenerateKey, (ck_session_handle_t session, struct ck_mechanism *mechanism, struct ck_attribute *templ, unsigned long count, ck_object_handle_t *key)); _CK_DECLARE_FUNCTION (C_GenerateKeyPair, (ck_session_handle_t session, struct ck_mechanism *mechanism, struct ck_attribute *public_key_template, unsigned long public_key_attribute_count, struct ck_attribute *private_key_template, unsigned long private_key_attribute_count, ck_object_handle_t *public_key, ck_object_handle_t *private_key)); _CK_DECLARE_FUNCTION (C_WrapKey, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t wrapping_key, ck_object_handle_t key, unsigned char *wrapped_key, unsigned long *wrapped_key_len)); _CK_DECLARE_FUNCTION (C_UnwrapKey, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t unwrapping_key, unsigned char *wrapped_key, unsigned long wrapped_key_len, struct ck_attribute *templ, unsigned long attribute_count, ck_object_handle_t *key)); _CK_DECLARE_FUNCTION (C_DeriveKey, (ck_session_handle_t session, struct ck_mechanism *mechanism, ck_object_handle_t base_key, struct ck_attribute *templ, unsigned long attribute_count, ck_object_handle_t *key)); _CK_DECLARE_FUNCTION (C_SeedRandom, (ck_session_handle_t session, unsigned char *seed, unsigned long seed_len)); _CK_DECLARE_FUNCTION (C_GenerateRandom, (ck_session_handle_t session, unsigned char *random_data, unsigned long random_len)); _CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session)); _CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session)); struct ck_function_list { struct ck_version version; CK_C_Initialize C_Initialize; CK_C_Finalize C_Finalize; CK_C_GetInfo C_GetInfo; CK_C_GetFunctionList C_GetFunctionList; CK_C_GetSlotList C_GetSlotList; CK_C_GetSlotInfo C_GetSlotInfo; CK_C_GetTokenInfo C_GetTokenInfo; CK_C_GetMechanismList C_GetMechanismList; CK_C_GetMechanismInfo C_GetMechanismInfo; CK_C_InitToken C_InitToken; CK_C_InitPIN C_InitPIN; CK_C_SetPIN C_SetPIN; CK_C_OpenSession C_OpenSession; CK_C_CloseSession C_CloseSession; CK_C_CloseAllSessions C_CloseAllSessions; CK_C_GetSessionInfo C_GetSessionInfo; CK_C_GetOperationState C_GetOperationState; CK_C_SetOperationState C_SetOperationState; CK_C_Login C_Login; CK_C_Logout C_Logout; CK_C_CreateObject C_CreateObject; CK_C_CopyObject C_CopyObject; CK_C_DestroyObject C_DestroyObject; CK_C_GetObjectSize C_GetObjectSize; CK_C_GetAttributeValue C_GetAttributeValue; CK_C_SetAttributeValue C_SetAttributeValue; CK_C_FindObjectsInit C_FindObjectsInit; CK_C_FindObjects C_FindObjects; CK_C_FindObjectsFinal C_FindObjectsFinal; CK_C_EncryptInit C_EncryptInit; CK_C_Encrypt C_Encrypt; CK_C_EncryptUpdate C_EncryptUpdate; CK_C_EncryptFinal C_EncryptFinal; CK_C_DecryptInit C_DecryptInit; CK_C_Decrypt C_Decrypt; CK_C_DecryptUpdate C_DecryptUpdate; CK_C_DecryptFinal C_DecryptFinal; CK_C_DigestInit C_DigestInit; CK_C_Digest C_Digest; CK_C_DigestUpdate C_DigestUpdate; CK_C_DigestKey C_DigestKey; CK_C_DigestFinal C_DigestFinal; CK_C_SignInit C_SignInit; CK_C_Sign C_Sign; CK_C_SignUpdate C_SignUpdate; CK_C_SignFinal C_SignFinal; CK_C_SignRecoverInit C_SignRecoverInit; CK_C_SignRecover C_SignRecover; CK_C_VerifyInit C_VerifyInit; CK_C_Verify C_Verify; CK_C_VerifyUpdate C_VerifyUpdate; CK_C_VerifyFinal C_VerifyFinal; CK_C_VerifyRecoverInit C_VerifyRecoverInit; CK_C_VerifyRecover C_VerifyRecover; CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; CK_C_SignEncryptUpdate C_SignEncryptUpdate; CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; CK_C_GenerateKey C_GenerateKey; CK_C_GenerateKeyPair C_GenerateKeyPair; CK_C_WrapKey C_WrapKey; CK_C_UnwrapKey C_UnwrapKey; CK_C_DeriveKey C_DeriveKey; CK_C_SeedRandom C_SeedRandom; CK_C_GenerateRandom C_GenerateRandom; CK_C_GetFunctionStatus C_GetFunctionStatus; CK_C_CancelFunction C_CancelFunction; CK_C_WaitForSlotEvent C_WaitForSlotEvent; }; typedef ck_rv_t (*ck_createmutex_t) (void **mutex); typedef ck_rv_t (*ck_destroymutex_t) (void *mutex); typedef ck_rv_t (*ck_lockmutex_t) (void *mutex); typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex); struct ck_c_initialize_args { ck_createmutex_t create_mutex; ck_destroymutex_t destroy_mutex; ck_lockmutex_t lock_mutex; ck_unlockmutex_t unlock_mutex; ck_flags_t flags; void *reserved; }; #define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0) #define CKF_OS_LOCKING_OK (1 << 1) #define CKR_OK (0) #define CKR_CANCEL (1) #define CKR_HOST_MEMORY (2) #define CKR_SLOT_ID_INVALID (3) #define CKR_GENERAL_ERROR (5) #define CKR_FUNCTION_FAILED (6) #define CKR_ARGUMENTS_BAD (7) #define CKR_NO_EVENT (8) #define CKR_NEED_TO_CREATE_THREADS (9) #define CKR_CANT_LOCK (0xa) #define CKR_ATTRIBUTE_READ_ONLY (0x10) #define CKR_ATTRIBUTE_SENSITIVE (0x11) #define CKR_ATTRIBUTE_TYPE_INVALID (0x12) #define CKR_ATTRIBUTE_VALUE_INVALID (0x13) #define CKR_DATA_INVALID (0x20) #define CKR_DATA_LEN_RANGE (0x21) #define CKR_DEVICE_ERROR (0x30) #define CKR_DEVICE_MEMORY (0x31) #define CKR_DEVICE_REMOVED (0x32) #define CKR_ENCRYPTED_DATA_INVALID (0x40) #define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41) #define CKR_FUNCTION_CANCELED (0x50) #define CKR_FUNCTION_NOT_PARALLEL (0x51) #define CKR_FUNCTION_NOT_SUPPORTED (0x54) #define CKR_KEY_HANDLE_INVALID (0x60) #define CKR_KEY_SIZE_RANGE (0x62) #define CKR_KEY_TYPE_INCONSISTENT (0x63) #define CKR_KEY_NOT_NEEDED (0x64) #define CKR_KEY_CHANGED (0x65) #define CKR_KEY_NEEDED (0x66) #define CKR_KEY_INDIGESTIBLE (0x67) #define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68) #define CKR_KEY_NOT_WRAPPABLE (0x69) #define CKR_KEY_UNEXTRACTABLE (0x6a) #define CKR_MECHANISM_INVALID (0x70) #define CKR_MECHANISM_PARAM_INVALID (0x71) #define CKR_OBJECT_HANDLE_INVALID (0x82) #define CKR_OPERATION_ACTIVE (0x90) #define CKR_OPERATION_NOT_INITIALIZED (0x91) #define CKR_PIN_INCORRECT (0xa0) #define CKR_PIN_INVALID (0xa1) #define CKR_PIN_LEN_RANGE (0xa2) #define CKR_PIN_EXPIRED (0xa3) #define CKR_PIN_LOCKED (0xa4) #define CKR_SESSION_CLOSED (0xb0) #define CKR_SESSION_COUNT (0xb1) #define CKR_SESSION_HANDLE_INVALID (0xb3) #define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4) #define CKR_SESSION_READ_ONLY (0xb5) #define CKR_SESSION_EXISTS (0xb6) #define CKR_SESSION_READ_ONLY_EXISTS (0xb7) #define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8) #define CKR_SIGNATURE_INVALID (0xc0) #define CKR_SIGNATURE_LEN_RANGE (0xc1) #define CKR_TEMPLATE_INCOMPLETE (0xd0) #define CKR_TEMPLATE_INCONSISTENT (0xd1) #define CKR_TOKEN_NOT_PRESENT (0xe0) #define CKR_TOKEN_NOT_RECOGNIZED (0xe1) #define CKR_TOKEN_WRITE_PROTECTED (0xe2) #define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0) #define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1) #define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2) #define CKR_USER_ALREADY_LOGGED_IN (0x100) #define CKR_USER_NOT_LOGGED_IN (0x101) #define CKR_USER_PIN_NOT_INITIALIZED (0x102) #define CKR_USER_TYPE_INVALID (0x103) #define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104) #define CKR_USER_TOO_MANY_TYPES (0x105) #define CKR_WRAPPED_KEY_INVALID (0x110) #define CKR_WRAPPED_KEY_LEN_RANGE (0x112) #define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113) #define CKR_WRAPPING_KEY_SIZE_RANGE (0x114) #define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115) #define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120) #define CKR_RANDOM_NO_RNG (0x121) #define CKR_DOMAIN_PARAMS_INVALID (0x130) #define CKR_BUFFER_TOO_SMALL (0x150) #define CKR_SAVED_STATE_INVALID (0x160) #define CKR_INFORMATION_SENSITIVE (0x170) #define CKR_STATE_UNSAVEABLE (0x180) #define CKR_CRYPTOKI_NOT_INITIALIZED (0x190) #define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191) #define CKR_MUTEX_BAD (0x1a0) #define CKR_MUTEX_NOT_LOCKED (0x1a1) #define CKR_FUNCTION_REJECTED (0x200) #define CKR_VENDOR_DEFINED (1U << 31) /* Compatibility layer. */ #ifdef CRYPTOKI_COMPAT #undef CK_DEFINE_FUNCTION #define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name /* For NULL. */ #include typedef unsigned char CK_BYTE; typedef unsigned char CK_CHAR; typedef unsigned char CK_UTF8CHAR; typedef unsigned char CK_BBOOL; typedef unsigned long int CK_ULONG; typedef long int CK_LONG; typedef CK_BYTE *CK_BYTE_PTR; typedef CK_CHAR *CK_CHAR_PTR; typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; typedef CK_ULONG *CK_ULONG_PTR; typedef void *CK_VOID_PTR; typedef void **CK_VOID_PTR_PTR; #define CK_FALSE 0 #define CK_TRUE 1 #ifndef CK_DISABLE_TRUE_FALSE #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #endif typedef struct ck_version CK_VERSION; typedef struct ck_version *CK_VERSION_PTR; typedef struct ck_info CK_INFO; typedef struct ck_info *CK_INFO_PTR; typedef ck_slot_id_t *CK_SLOT_ID_PTR; typedef struct ck_slot_info CK_SLOT_INFO; typedef struct ck_slot_info *CK_SLOT_INFO_PTR; typedef struct ck_token_info CK_TOKEN_INFO; typedef struct ck_token_info *CK_TOKEN_INFO_PTR; typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; typedef struct ck_session_info CK_SESSION_INFO; typedef struct ck_session_info *CK_SESSION_INFO_PTR; typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; typedef struct ck_attribute CK_ATTRIBUTE; typedef struct ck_attribute *CK_ATTRIBUTE_PTR; typedef struct ck_date CK_DATE; typedef struct ck_date *CK_DATE_PTR; typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; typedef struct ck_mechanism CK_MECHANISM; typedef struct ck_mechanism *CK_MECHANISM_PTR; typedef struct ck_mechanism_info CK_MECHANISM_INFO; typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; typedef struct ck_function_list CK_FUNCTION_LIST; typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; #define NULL_PTR NULL /* Delete the helper macros defined at the top of the file. */ #undef ck_flags_t #undef ck_version #undef ck_info #undef cryptoki_version #undef manufacturer_id #undef library_description #undef library_version #undef ck_notification_t #undef ck_slot_id_t #undef ck_slot_info #undef slot_description #undef hardware_version #undef firmware_version #undef ck_token_info #undef serial_number #undef max_session_count #undef session_count #undef max_rw_session_count #undef rw_session_count #undef max_pin_len #undef min_pin_len #undef total_public_memory #undef free_public_memory #undef total_private_memory #undef free_private_memory #undef utc_time #undef ck_session_handle_t #undef ck_user_type_t #undef ck_state_t #undef ck_session_info #undef slot_id #undef device_error #undef ck_object_handle_t #undef ck_object_class_t #undef ck_hw_feature_type_t #undef ck_key_type_t #undef ck_certificate_type_t #undef ck_attribute_type_t #undef ck_attribute #undef value #undef value_len #undef ck_date #undef ck_mechanism_type_t #undef ck_mechanism #undef parameter #undef parameter_len #undef ck_mechanism_info #undef min_key_size #undef max_key_size #undef ck_rv_t #undef ck_notify_t #undef ck_function_list #undef ck_createmutex_t #undef ck_destroymutex_t #undef ck_lockmutex_t #undef ck_unlockmutex_t #undef ck_c_initialize_args #undef create_mutex #undef destroy_mutex #undef lock_mutex #undef unlock_mutex #undef reserved #endif /* CRYPTOKI_COMPAT */ /* System dependencies. */ #if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) #pragma pack(pop, cryptoki) #endif #if defined(__cplusplus) } #endif #endif /* PKCS11_H */ openssh-10.0p1/PaxHeaders.10889/platform-listen.c100644 001750 001750 0000000003614775415623 0016440xustar0030 atime=1744182234.680494057 openssh-10.0p1/platform-listen.c010064400017500001750000000043461477541562300150320ustar00djmdjm/* * 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 #include #include #include #include "log.h" #include "misc.h" #include "platform.h" #include "openbsd-compat/openbsd-compat.h" void platform_pre_listen(void) { #ifdef LINUX_OOM_ADJUST /* Adjust out-of-memory killer so listening process is not killed */ oom_adjust_setup(); #endif #ifdef LINUX_MEMLOCK_ONFAULT /* * Protect ourselves against kcompactd so that we are able to process * new connections while it is active and migrating pages. */ memlock_onfault_setup(); #endif } void platform_post_listen(void) { #ifdef SYSTEMD_NOTIFY ssh_systemd_notify_ready(); #endif } void platform_pre_fork(void) { #ifdef USE_SOLARIS_PROCESS_CONTRACTS solaris_contract_pre_fork(); #endif } void platform_pre_restart(void) { #ifdef SYSTEMD_NOTIFY ssh_systemd_notify_reload(); #endif #ifdef LINUX_OOM_ADJUST oom_adjust_restore(); #endif } void platform_post_fork_parent(pid_t child_pid) { #ifdef USE_SOLARIS_PROCESS_CONTRACTS solaris_contract_post_fork_parent(child_pid); #endif } void platform_post_fork_child(void) { #ifdef USE_SOLARIS_PROCESS_CONTRACTS solaris_contract_post_fork_child(); #endif #ifdef LINUX_OOM_ADJUST oom_adjust_restore(); #endif } void platform_pre_session_start(void) { #ifdef LINUX_MEMLOCK_ONFAULT /* * Memlock flags are dropped on fork, lock the memory again so that the * child connection is also protected against kcompactd. */ memlock_onfault_setup(); #endif } openssh-10.0p1/PaxHeaders.10889/platform-misc.c100644 001750 001750 0000000003614775415623 0016075xustar0030 atime=1744182234.680494057 openssh-10.0p1/platform-misc.c010064400017500001750000000021371477541562300144630ustar00djmdjm/* * 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; } openssh-10.0p1/PaxHeaders.10889/platform-pledge.c100644 001750 001750 0000000003614775415623 0016402xustar0030 atime=1744182234.680494057 openssh-10.0p1/platform-pledge.c010064400017500001750000000035651477541562300147760ustar00djmdjm/* * Copyright (c) 2015 Joyent, Inc * Author: Alex Wilson * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include "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 } openssh-10.0p1/PaxHeaders.10889/platform-tracing.c100644 001750 001750 0000000003614775415623 0016571xustar0030 atime=1744182234.680494057 openssh-10.0p1/platform-tracing.c010064400017500001750000000047271477541562300151660ustar00djmdjm/* * 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 #ifdef HAVE_SYS_PROCCTL_H #include #endif #if defined(HAVE_SYS_PRCTL_H) #include /* For prctl() and PR_SET_DUMPABLE */ #endif #ifdef HAVE_SYS_PTRACE_H #include #endif #ifdef HAVE_PRIV_H #include /* For setpflags() and __PROC_PROTECT */ #endif #include #include #include #include #include "log.h" void platform_disable_tracing(int strict) { #if defined(HAVE_PROCCTL) && defined(PROC_TRACE_CTL) /* On FreeBSD, we should make this process untraceable */ int disable_trace = PROC_TRACE_CTL_DISABLE; /* * On FreeBSD, we should make this process untraceable. * pid=0 means "this process" but some older kernels do not * understand that so retry with our own pid before failing. */ if (procctl(P_PID, 0, PROC_TRACE_CTL, &disable_trace) == 0) return; if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &disable_trace) == 0) return; if (strict) fatal("unable to make the process untraceable: %s", strerror(errno)); #endif #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: %s", strerror(errno)); #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: %s", strerror(errno)); #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: %s", strerror(errno)); #endif } openssh-10.0p1/PaxHeaders.10889/platform.c100644 001750 001750 0000000003614775415623 0015144xustar0030 atime=1744182234.680494057 openssh-10.0p1/platform.c010064400017500001750000000121011477541562300135220ustar00djmdjm/* * 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 #include #include #include #include "log.h" #include "misc.h" #include "servconf.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "auth-pam.h" #include "platform.h" #include "openbsd-compat/openbsd-compat.h" extern ServerOptions options; /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */ int platform_privileged_uidswap(void) { #ifdef HAVE_CYGWIN /* uid 0 is not special on Cygwin so always try */ return 1; #else return (getuid() == 0 || geteuid() == 0); #endif } /* * This gets called before switching UIDs, and is called even when sshd is * not running as root. */ void platform_setusercontext(struct passwd *pw) { #ifdef WITH_SELINUX /* Cache selinux status for later use */ (void)ssh_selinux_enabled(); #endif #ifdef USE_SOLARIS_PROJECTS /* * 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 #if defined(HAVE_LOGIN_CAP) && defined (__bsdi__) if (getuid() == 0 || geteuid() == 0) setpgid(0, 0); # endif #if defined(HAVE_LOGIN_CAP) && defined(USE_PAM) /* * If we have both LOGIN_CAP and PAM, we want to establish creds * before calling setusercontext (in session.c:do_setusercontext). */ if (getuid() == 0 || geteuid() == 0) { if (options.use_pam) { do_pam_setcred(); } } # endif /* USE_PAM */ #if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID) if (getuid() == 0 || geteuid() == 0) { /* Sets login uid for accounting */ if (getluid() == -1 && setluid(pw->pw_uid) == -1) error("setluid: %s", strerror(errno)); } #endif } /* * This gets called after we've established the user's groups, and is only * called if sshd is running as root. */ void platform_setusercontext_post_groups(struct passwd *pw) { #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) /* * PAM credentials may take the form of supplementary groups. * These will have been wiped by the above initgroups() call. * Reestablish them here. */ if (options.use_pam) { do_pam_setcred(); } #endif /* USE_PAM */ #if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \ defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)) irix_setusercontext(pw); #endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ #ifdef _AIX aix_usrinfo(pw); #endif /* _AIX */ #ifdef HAVE_SETPCRED /* * If we have a chroot directory, we set all creds except real * uid which we will need for chroot. If we don't have a * chroot directory, we don't override anything. */ { char **creds = NULL, *chroot_creds[] = { "REAL_USER=root", NULL }; if (options.chroot_directory != NULL && strcasecmp(options.chroot_directory, "none") != 0) creds = chroot_creds; if (setpcred(pw->pw_name, creds) == -1) fatal("Failed to set process credentials"); } #endif /* HAVE_SETPCRED */ #ifdef WITH_SELINUX ssh_selinux_setup_exec_context(pw->pw_name); #endif } char * platform_krb5_get_principal_name(const char *pw_name) { #ifdef USE_AIX_KRB_NAME return aix_krb5_get_principal_name(pw_name); #else return NULL; #endif } /* returns 1 if account is locked */ int platform_locked_account(struct passwd *pw) { int locked = 0; char *passwd = pw->pw_passwd; #ifdef USE_SHADOW struct spwd *spw = NULL; #ifdef USE_LIBIAF char *iaf_passwd = NULL; #endif spw = getspnam(pw->pw_name); #ifdef HAS_SHADOW_EXPIRE if (spw != NULL && auth_shadow_acctexpired(spw)) return 1; #endif /* HAS_SHADOW_EXPIRE */ if (spw != NULL) #ifdef USE_LIBIAF iaf_passwd = passwd = get_iaf_password(pw); #else passwd = spw->sp_pwdp; #endif /* USE_LIBIAF */ #endif /* check for locked account */ if (passwd && *passwd) { #ifdef LOCKED_PASSWD_STRING if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0) locked = 1; #endif #ifdef LOCKED_PASSWD_PREFIX if (strncmp(passwd, LOCKED_PASSWD_PREFIX, strlen(LOCKED_PASSWD_PREFIX)) == 0) locked = 1; #endif #ifdef LOCKED_PASSWD_SUBSTR if (strstr(passwd, LOCKED_PASSWD_SUBSTR)) locked = 1; #endif } #ifdef USE_LIBIAF if (iaf_passwd != NULL) freezero(iaf_passwd, strlen(iaf_passwd)); #endif /* USE_LIBIAF */ return locked; } openssh-10.0p1/PaxHeaders.10889/platform.h100644 001750 001750 0000000003614775415623 0015151xustar0030 atime=1744182234.680494057 openssh-10.0p1/platform.h010064400017500001750000000030621477541562300135350ustar00djmdjm/* * 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 #include void platform_pre_listen(void); void platform_pre_fork(void); void platform_pre_restart(void); void platform_post_listen(void); void platform_post_fork_parent(pid_t child_pid); void platform_post_fork_child(void); void platform_pre_session_start(void); int platform_privileged_uidswap(void); void platform_setusercontext(struct passwd *); void platform_setusercontext_post_groups(struct passwd *); char *platform_get_krb5_client(const char *); char *platform_krb5_get_principal_name(const char *); int platform_locked_account(struct passwd *); 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); openssh-10.0p1/PaxHeaders.10889/poly1305.c100644 001750 001750 0000000003614775415623 0014614xustar0030 atime=1744182234.681470114 openssh-10.0p1/poly1305.c010064400017500001750000000110541477541562300132000ustar00djmdjm/* $OpenBSD: poly1305.c,v 1.4 2023/07/17 05:26:38 djm Exp $ */ /* * Public Domain poly1305 from Andrew Moon * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna */ #include "includes.h" #include #ifdef HAVE_STDINT_H # include #endif #include "poly1305.h" #define mul32x32_64(a,b) ((uint64_t)(a) * (b)) #define U8TO32_LE(p) \ (((uint32_t)((p)[0])) | \ ((uint32_t)((p)[1]) << 8) | \ ((uint32_t)((p)[2]) << 16) | \ ((uint32_t)((p)[3]) << 24)) #define U32TO8_LE(p, v) \ do { \ (p)[0] = (uint8_t)((v)); \ (p)[1] = (uint8_t)((v) >> 8); \ (p)[2] = (uint8_t)((v) >> 16); \ (p)[3] = (uint8_t)((v) >> 24); \ } while (0) void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) { uint32_t t0,t1,t2,t3; uint32_t h0,h1,h2,h3,h4; uint32_t r0,r1,r2,r3,r4; uint32_t s1,s2,s3,s4; uint32_t b, nb; size_t j; uint64_t t[5]; uint64_t f0,f1,f2,f3; uint32_t g0,g1,g2,g3,g4; uint64_t c; unsigned char mp[16]; /* clamp key */ t0 = U8TO32_LE(key+0); t1 = U8TO32_LE(key+4); t2 = U8TO32_LE(key+8); t3 = U8TO32_LE(key+12); /* precompute multipliers */ r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6; r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12; r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18; r3 = t2 & 0x3f03fff; t3 >>= 8; r4 = t3 & 0x00fffff; s1 = r1 * 5; s2 = r2 * 5; s3 = r3 * 5; s4 = r4 * 5; /* init state */ h0 = 0; h1 = 0; h2 = 0; h3 = 0; h4 = 0; /* full blocks */ if (inlen < 16) goto poly1305_donna_atmost15bytes; poly1305_donna_16bytes: m += 16; inlen -= 16; t0 = U8TO32_LE(m-16); t1 = U8TO32_LE(m-12); t2 = U8TO32_LE(m-8); t3 = U8TO32_LE(m-4); h0 += t0 & 0x3ffffff; h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; h4 += (t3 >> 8) | (1 << 24); poly1305_donna_mul: t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1); t[1] = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2); t[2] = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3); t[3] = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4); t[4] = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0); h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26); t[1] += c; h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26); t[2] += b; h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26); t[3] += b; h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26); t[4] += b; h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26); h0 += b * 5; if (inlen >= 16) goto poly1305_donna_16bytes; /* final bytes */ poly1305_donna_atmost15bytes: if (!inlen) goto poly1305_donna_finish; for (j = 0; j < inlen; j++) mp[j] = m[j]; mp[j++] = 1; for (; j < 16; j++) mp[j] = 0; inlen = 0; t0 = U8TO32_LE(mp+0); t1 = U8TO32_LE(mp+4); t2 = U8TO32_LE(mp+8); t3 = U8TO32_LE(mp+12); h0 += t0 & 0x3ffffff; h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; h4 += (t3 >> 8); goto poly1305_donna_mul; poly1305_donna_finish: b = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff; h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff; h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff; h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff; h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += b; g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff; g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff; g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff; g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff; g4 = h4 + b - (1 << 26); b = (g4 >> 31) - 1; nb = ~b; h0 = (h0 & nb) | (g0 & b); h1 = (h1 & nb) | (g1 & b); h2 = (h2 & nb) | (g2 & b); h3 = (h3 & nb) | (g3 & b); h4 = (h4 & nb) | (g4 & b); f0 = ((h0 ) | (h1 << 26)) + (uint64_t)U8TO32_LE(&key[16]); f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)U8TO32_LE(&key[20]); f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)U8TO32_LE(&key[24]); f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)U8TO32_LE(&key[28]); U32TO8_LE(&out[ 0], f0); f1 += (f0 >> 32); U32TO8_LE(&out[ 4], f1); f2 += (f1 >> 32); U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32); U32TO8_LE(&out[12], f3); } openssh-10.0p1/PaxHeaders.10889/poly1305.h100644 001750 001750 0000000003614775415623 0014621xustar0030 atime=1744182234.681470114 openssh-10.0p1/poly1305.h010064400017500001750000000012051477541562300132020ustar00djmdjm/* $OpenBSD: poly1305.h,v 1.4 2014/05/02 03:27:54 djm Exp $ */ /* * Public Domain poly1305 from Andrew Moon * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna */ #ifndef POLY1305_H #define POLY1305_H #include #define POLY1305_KEYLEN 32 #define POLY1305_TAGLEN 16 void poly1305_auth(u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen, const u_char key[POLY1305_KEYLEN]) __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN))) __attribute__((__bounded__(__buffer__, 2, 3))) __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN))); #endif /* POLY1305_H */ openssh-10.0p1/PaxHeaders.10889/progressmeter.c100644 001750 001750 0000000003614775415623 0016221xustar0030 atime=1744182234.681470114 openssh-10.0p1/progressmeter.c010064400017500001750000000167351477541562300146200ustar00djmdjm/* $OpenBSD: progressmeter.c,v 1.54 2024/09/22 12:56:21 jsg Exp $ */ /* * Copyright (c) 2003 Nils Nordman. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "progressmeter.h" #include "atomicio.h" #include "misc.h" #include "utf8.h" #define DEFAULT_WINSIZE 80 #define MAX_WINSIZE 512 #define UPDATE_INTERVAL 1 /* update the progress meter every second */ #define STALL_TIME 5 /* we're stalled after this many seconds */ /* determines whether we can output to the terminal */ static int can_output(void); /* window resizing */ static void sig_winch(int); static void setscreensize(void); /* signal handler for updating the progress meter */ static void sig_alarm(int); 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 */ static off_t cur_pos; /* transfer position as of last refresh */ static volatile off_t *counter; /* progress counter */ 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"; static int can_output(void) { return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); } /* size needed to format integer type v, using (nbits(v) * log2(10) / 10) */ #define STRING_SIZE(v) (((sizeof(v) * 8 * 4) / 10) + 1) static const char * format_rate(off_t bytes) { int i; static char buf[STRING_SIZE(bytes) * 2 + 16]; bytes *= 100; for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++) bytes = (bytes + 512) / 1024; if (i == 0) { i++; bytes = (bytes + 512) / 1024; } snprintf(buf, sizeof(buf), "%3lld.%1lld%c%s", (long long) (bytes + 5) / 100, (long long) (bytes + 5) / 10 % 10, unit[i], i ? "B" : " "); return buf; } static const char * format_size(off_t bytes) { int i; static char buf[STRING_SIZE(bytes) + 16]; for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++) bytes = (bytes + 512) / 1024; snprintf(buf, sizeof(buf), "%4lld%c%s", (long long) bytes, unit[i], i ? "B" : " "); return buf; } void refresh_progress_meter(int force_update) { char *buf = NULL, *obuf = NULL; off_t transferred; double elapsed, now; int percent; off_t bytes_left; int cur_speed; int hours, minutes, seconds; int file_len, cols; 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_double(); bytes_left = end_pos - cur_pos; if (bytes_left > 0) elapsed = now - last_update; else { elapsed = now - start; /* Calculate true total speed when done */ transferred = end_pos - start_pos; bytes_per_second = 0; } /* calculate speed */ if (elapsed != 0) cur_speed = (transferred / elapsed); else cur_speed = transferred; #define AGE_FACTOR 0.9 if (bytes_per_second != 0) { bytes_per_second = (bytes_per_second * AGE_FACTOR) + (cur_speed * (1.0 - AGE_FACTOR)); } else bytes_per_second = cur_speed; last_update = now; /* Don't bother if we can't even display the completion percentage */ if (win_size < 4) return; /* filename */ file_len = cols = win_size - 36; if (file_len > 0) { asmprintf(&buf, INT_MAX, &cols, "%-*s", file_len, file); /* If we used fewer columns than expected then pad */ if (cols < file_len) xextendf(&buf, NULL, "%*s", file_len - cols, ""); } /* percent of transfer done */ if (end_pos == 0 || cur_pos == end_pos) percent = 100; else percent = ((float)cur_pos / end_pos) * 100; /* percent / amount transferred / bandwidth usage */ xextendf(&buf, NULL, " %3d%% %s %s/s ", percent, format_size(cur_pos), format_rate((off_t)bytes_per_second)); /* ETA */ if (!transferred) stalled += elapsed; else stalled = 0; if (stalled >= STALL_TIME) xextendf(&buf, NULL, "- stalled -"); else if (bytes_per_second == 0 && bytes_left) xextendf(&buf, NULL, " --:-- ETA"); else { if (bytes_left > 0) seconds = bytes_left / bytes_per_second; else seconds = elapsed; hours = seconds / 3600; seconds -= hours * 3600; minutes = seconds / 60; seconds -= minutes * 60; if (hours != 0) { xextendf(&buf, NULL, "%d:%02d:%02d", hours, minutes, seconds); } else xextendf(&buf, NULL, " %02d:%02d", minutes, seconds); if (bytes_left > 0) xextendf(&buf, NULL, " ETA"); else xextendf(&buf, NULL, " "); } /* Finally, truncate string at window width */ cols = win_size - 1; asmprintf(&obuf, INT_MAX, &cols, " %s", buf); if (obuf != NULL) { *obuf = '\r'; /* must insert as asmprintf() would escape it */ atomicio(vwrite, STDOUT_FILENO, obuf, strlen(obuf)); } free(buf); free(obuf); } static void sig_alarm(int ignore) { alarm_fired = 1; alarm(UPDATE_INTERVAL); } void start_progress_meter(const char *f, off_t filesize, off_t *ctr) { start = last_update = monotime_double(); file = f; start_pos = *ctr; end_pos = filesize; cur_pos = 0; counter = ctr; stalled = 0; bytes_per_second = 0; setscreensize(); refresh_progress_meter(1); ssh_signal(SIGALRM, sig_alarm); ssh_signal(SIGWINCH, sig_winch); alarm(UPDATE_INTERVAL); } void stop_progress_meter(void) { alarm(0); if (!can_output()) return; /* Ensure we complete the progress */ if (cur_pos != end_pos) refresh_progress_meter(1); atomicio(vwrite, STDOUT_FILENO, "\n", 1); } static void sig_winch(int sig) { win_resized = 1; } static void setscreensize(void) { struct winsize winsize; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 && winsize.ws_col != 0) { if (winsize.ws_col > MAX_WINSIZE) win_size = MAX_WINSIZE; else win_size = winsize.ws_col; } else win_size = DEFAULT_WINSIZE; win_size += 1; /* trailing \0 */ } openssh-10.0p1/PaxHeaders.10889/progressmeter.h100644 001750 001750 0000000003614775415623 0016226xustar0030 atime=1744182234.681470114 openssh-10.0p1/progressmeter.h010064400017500001750000000027471477541562300146230ustar00djmdjm/* $OpenBSD: progressmeter.h,v 1.5 2019/01/24 16:52:17 dtucker Exp $ */ /* * Copyright (c) 2002 Nils Nordman. 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. */ void start_progress_meter(const char *, off_t, off_t *); void refresh_progress_meter(int); void stop_progress_meter(void); openssh-10.0p1/PaxHeaders.10889/readconf.c100644 001750 001750 0000000003614775415623 0015101xustar0030 atime=1744182234.687328805 openssh-10.0p1/readconf.c010064400017500001750000003307621477541562300134770ustar00djmdjm/* $OpenBSD: readconf.c,v 1.398 2025/03/18 04:53:14 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for reading the configuration files. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_IFADDRS_H # include #endif #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #ifdef USE_SYSTEM_GLOB # include #else # include "openbsd-compat/glob.h" #endif #ifdef HAVE_UTIL_H #include #endif #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) # include #endif #include "xmalloc.h" #include "ssh.h" #include "ssherr.h" #include "cipher.h" #include "pathnames.h" #include "log.h" #include "sshkey.h" #include "misc.h" #include "readconf.h" #include "match.h" #include "kex.h" #include "mac.h" #include "uidswap.h" #include "myproposal.h" #include "digest.h" #include "version.h" /* Format of the configuration file: # Configuration data is parsed as follows: # 1. command line options # 2. user-specific file # 3. system-wide file # Any configuration value is only changed the first time it is set. # Thus, host-specific definitions should be at the beginning of the # configuration file, and defaults at the end. # Host-specific declarations. These may override anything above. A single # host may match multiple declarations; these are processed in the order # that they are given in. Host *.ngs.fi ngs.fi User foo Host fake.com Hostname another.host.name.real.org User blaah Port 34289 ForwardX11 no ForwardAgent no Host books.com RemoteForward 9999 shadows.cs.hut.fi:9999 Ciphers 3des-cbc Host fascist.blob.com Port 23123 User tylonen PasswordAuthentication no Host puukko.hut.fi User t35124p ProxyCommand ssh-proxy %h %p Host *.fr PublicKeyAuthentication no Host *.su Ciphers aes128-ctr PasswordAuthentication no Host vpn.fake.com Tunnel yes TunnelDevice 3 # Defaults for various options Host * ForwardAgent no ForwardX11 no PasswordAuthentication yes StrictHostKeyChecking yes TcpKeepAlive no IdentityFile ~/.ssh/identity Port 22 EscapeChar ~ */ static int read_config_file_depth(const char *filename, struct passwd *pw, const char *host, const char *original_host, const char *remote_command, 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, const char *remote_command, char *line, const char *filename, int linenum, int *activep, int flags, int *want_final_pass, int depth); /* Keyword tokens. */ typedef enum { oBadOption, oHost, oMatch, oInclude, oTag, oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, oGatewayPorts, oExitOnForwardFailure, oPasswordAuthentication, oXAuthLocation, oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, oPermitRemoteOpen, oCertificateFile, oAddKeysToAgent, oIdentityAgent, oUser, oEscapeChar, oProxyCommand, oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oTCPKeepAlive, oNumberOfPasswordPrompts, oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider, oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, oRemoteCommand, oVisualHostKey, oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull, oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize, oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout, oVersionAddendum, oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported } OpCodes; /* Textual representations of the tokens. */ static struct { const char *name; OpCodes opcode; } keywords[] = { /* Deprecated options */ { "protocol", oIgnore }, /* NB. silently ignored */ { "cipher", oDeprecated }, { "fallbacktorsh", oDeprecated }, { "globalknownhostsfile2", oDeprecated }, { "rhostsauthentication", oDeprecated }, { "userknownhostsfile2", oDeprecated }, { "useroaming", oDeprecated }, { "usersh", oDeprecated }, { "useprivilegedport", oDeprecated }, /* Unsupported options */ { "afstokenpassing", oUnsupported }, { "kerberosauthentication", oUnsupported }, { "kerberostgtpassing", oUnsupported }, { "rsaauthentication", oUnsupported }, { "rhostsrsaauthentication", oUnsupported }, { "compressionlevel", oUnsupported }, /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, { "gssapidelegatecredentials", oGssDelegateCreds }, # else { "gssapiauthentication", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, { "smartcarddevice", oPKCS11Provider }, # else { "smartcarddevice", oUnsupported }, { "pkcs11provider", oUnsupported }, #endif { "forwardagent", oForwardAgent }, { "forwardx11", oForwardX11 }, { "forwardx11trusted", oForwardX11Trusted }, { "forwardx11timeout", oForwardX11Timeout }, { "exitonforwardfailure", oExitOnForwardFailure }, { "xauthlocation", oXAuthLocation }, { "gatewayports", oGatewayPorts }, { "passwordauthentication", oPasswordAuthentication }, { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, { "kbdinteractivedevices", oKbdInteractiveDevices }, { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */ { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */ { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */ { "pubkeyauthentication", oPubkeyAuthentication }, { "dsaauthentication", oPubkeyAuthentication }, /* alias */ { "hostbasedauthentication", oHostbasedAuthentication }, { "identityfile", oIdentityFile }, { "identityfile2", oIdentityFile }, /* obsolete */ { "identitiesonly", oIdentitiesOnly }, { "certificatefile", oCertificateFile }, { "addkeystoagent", oAddKeysToAgent }, { "identityagent", oIdentityAgent }, { "hostname", oHostname }, { "hostkeyalias", oHostKeyAlias }, { "proxycommand", oProxyCommand }, { "port", oPort }, { "ciphers", oCiphers }, { "macs", oMacs }, { "remoteforward", oRemoteForward }, { "localforward", oLocalForward }, { "permitremoteopen", oPermitRemoteOpen }, { "user", oUser }, { "host", oHost }, { "match", oMatch }, { "tag", oTag }, { "escapechar", oEscapeChar }, { "globalknownhostsfile", oGlobalKnownHostsFile }, { "userknownhostsfile", oUserKnownHostsFile }, { "connectionattempts", oConnectionAttempts }, { "batchmode", oBatchMode }, { "checkhostip", oCheckHostIP }, { "stricthostkeychecking", oStrictHostKeyChecking }, { "compression", oCompression }, { "tcpkeepalive", oTCPKeepAlive }, { "keepalive", oTCPKeepAlive }, /* obsolete */ { "numberofpasswordprompts", oNumberOfPasswordPrompts }, { "syslogfacility", oLogFacility }, { "loglevel", oLogLevel }, { "logverbose", oLogVerbose }, { "dynamicforward", oDynamicForward }, { "preferredauthentications", oPreferredAuthentications }, { "hostkeyalgorithms", oHostKeyAlgorithms }, { "casignaturealgorithms", oCASignatureAlgorithms }, { "bindaddress", oBindAddress }, { "bindinterface", oBindInterface }, { "clearallforwardings", oClearAllForwardings }, { "enablesshkeysign", oEnableSSHKeysign }, { "verifyhostkeydns", oVerifyHostKeyDNS }, { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, { "rekeylimit", oRekeyLimit }, { "connecttimeout", oConnectTimeout }, { "addressfamily", oAddressFamily }, { "serveraliveinterval", oServerAliveInterval }, { "serveralivecountmax", oServerAliveCountMax }, { "sendenv", oSendEnv }, { "setenv", oSetEnv }, { "controlpath", oControlPath }, { "controlmaster", oControlMaster }, { "controlpersist", oControlPersist }, { "hashknownhosts", oHashKnownHosts }, { "include", oInclude }, { "tunnel", oTunnel }, { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, { "remotecommand", oRemoteCommand }, { "visualhostkey", oVisualHostKey }, { "kexalgorithms", oKexAlgorithms }, { "ipqos", oIPQoS }, { "requesttty", oRequestTTY }, { "sessiontype", oSessionType }, { "stdinnull", oStdinNull }, { "forkafterauthentication", oForkAfterAuthentication }, { "proxyusefdpass", oProxyUseFdpass }, { "canonicaldomains", oCanonicalDomains }, { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, { "canonicalizehostname", oCanonicalizeHostname }, { "canonicalizemaxdots", oCanonicalizeMaxDots }, { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, { "streamlocalbindmask", oStreamLocalBindMask }, { "streamlocalbindunlink", oStreamLocalBindUnlink }, { "revokedhostkeys", oRevokedHostKeys }, { "fingerprinthash", oFingerprintHash }, { "updatehostkeys", oUpdateHostkeys }, { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms }, { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */ { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms }, { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */ { "ignoreunknown", oIgnoreUnknown }, { "proxyjump", oProxyJump }, { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, { "requiredrsasize", oRequiredRSASize }, { "enableescapecommandline", oEnableEscapeCommandline }, { "obscurekeystroketiming", oObscureKeystrokeTiming }, { "channeltimeout", oChannelTimeout }, { "versionaddendum", oVersionAddendum }, { NULL, oBadOption } }; static const char *lookup_opcode_name(OpCodes code); const char * kex_default_pk_alg(void) { static char *pkalgs; if (pkalgs == NULL) { char *all_key; all_key = sshkey_alg_list(0, 0, 1, ','); pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); free(all_key); } return pkalgs; } char * ssh_connection_hash(const char *thishost, const char *host, const char *portstr, const char *user, const char *jumphost) { struct ssh_digest_ctx *md; u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || ssh_digest_update(md, thishost, strlen(thishost)) < 0 || ssh_digest_update(md, host, strlen(host)) < 0 || ssh_digest_update(md, portstr, strlen(portstr)) < 0 || ssh_digest_update(md, user, strlen(user)) < 0 || ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 || ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) fatal_f("mux digest failed"); ssh_digest_free(md); return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); } /* * Adds a local TCP/IP port forward to options. Never returns if there is an * error. */ void add_local_forward(Options *options, const struct Forward *newfwd) { struct Forward *fwd; int i; /* Don't add duplicates */ for (i = 0; i < options->num_local_forwards; i++) { if (forward_equals(newfwd, options->local_forwards + i)) return; } options->local_forwards = xreallocarray(options->local_forwards, options->num_local_forwards + 1, sizeof(*options->local_forwards)); fwd = &options->local_forwards[options->num_local_forwards++]; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; fwd->listen_path = newfwd->listen_path; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; fwd->connect_path = newfwd->connect_path; } /* * Adds a remote TCP/IP port forward to options. Never returns if there is * an error. */ void add_remote_forward(Options *options, const struct Forward *newfwd) { struct Forward *fwd; int i; /* Don't add duplicates */ for (i = 0; i < options->num_remote_forwards; i++) { if (forward_equals(newfwd, options->remote_forwards + i)) return; } options->remote_forwards = xreallocarray(options->remote_forwards, options->num_remote_forwards + 1, sizeof(*options->remote_forwards)); fwd = &options->remote_forwards[options->num_remote_forwards++]; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; fwd->listen_path = newfwd->listen_path; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; fwd->connect_path = newfwd->connect_path; fwd->handle = newfwd->handle; fwd->allocated_port = 0; } static void clear_forwardings(Options *options) { int i; for (i = 0; i < options->num_local_forwards; i++) { free(options->local_forwards[i].listen_host); free(options->local_forwards[i].listen_path); free(options->local_forwards[i].connect_host); free(options->local_forwards[i].connect_path); } if (options->num_local_forwards > 0) { free(options->local_forwards); options->local_forwards = NULL; } options->num_local_forwards = 0; for (i = 0; i < options->num_remote_forwards; i++) { free(options->remote_forwards[i].listen_host); free(options->remote_forwards[i].listen_path); free(options->remote_forwards[i].connect_host); free(options->remote_forwards[i].connect_path); } if (options->num_remote_forwards > 0) { free(options->remote_forwards); options->remote_forwards = NULL; } options->num_remote_forwards = 0; options->tun_open = SSH_TUNMODE_NO; } void add_certificate_file(Options *options, const char *path, int userprovided) { int i; if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) fatal("Too many certificate files specified (max %d)", SSH_MAX_CERTIFICATE_FILES); /* Avoid registering duplicates */ for (i = 0; i < options->num_certificate_files; i++) { if (options->certificate_file_userprovided[i] == userprovided && strcmp(options->certificate_files[i], path) == 0) { debug2_f("ignoring duplicate key %s", path); return; } } options->certificate_file_userprovided[options->num_certificate_files] = userprovided; options->certificate_files[options->num_certificate_files++] = xstrdup(path); } void add_identity_file(Options *options, const char *dir, const char *filename, int userprovided) { char *path; int i; if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) fatal("Too many identity files specified (max %d)", SSH_MAX_IDENTITY_FILES); if (dir == NULL) /* no dir, filename is absolute */ path = xstrdup(filename); else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) fatal("Identity file path %s too long", path); /* Avoid registering duplicates */ for (i = 0; i < options->num_identity_files; i++) { if (options->identity_file_userprovided[i] == userprovided && strcmp(options->identity_files[i], path) == 0) { debug2_f("ignoring duplicate key %s", path); free(path); return; } } options->identity_file_userprovided[options->num_identity_files] = userprovided; options->identity_files[options->num_identity_files++] = path; } int default_ssh_port(void) { static int port; struct servent *sp; if (port == 0) { sp = getservbyname(SSH_SERVICE_NAME, "tcp"); port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; } return port; } /* * Execute a command in a shell. * Return its exit status or -1 on abnormal exit. */ static int execute_in_shell(const char *cmd) { char *shell; pid_t pid; int status; if ((shell = getenv("SHELL")) == NULL) shell = _PATH_BSHELL; if (access(shell, X_OK) == -1) { fatal("Shell \"%s\" is not executable: %s", shell, strerror(errno)); } debug("Executing command: '%.500s'", cmd); /* Fork and execute the command. */ if ((pid = fork()) == 0) { char *argv[4]; if (stdfd_devnull(1, 1, 0) == -1) fatal_f("stdfd_devnull failed"); closefrom(STDERR_FILENO + 1); argv[0] = shell; argv[1] = "-c"; argv[2] = xstrdup(cmd); argv[3] = NULL; execv(argv[0], argv); error("Unable to execute '%.100s': %s", cmd, strerror(errno)); /* Die with signal to make this error apparent to parent. */ ssh_signal(SIGTERM, SIG_DFL); kill(getpid(), SIGTERM); _exit(1); } /* Parent. */ if (pid == -1) fatal_f("fork: %.100s", strerror(errno)); while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR && errno != EAGAIN) fatal_f("waitpid: %s", strerror(errno)); } if (!WIFEXITED(status)) { error("command '%.100s' exited abnormally", cmd); return -1; } debug3("command returned status %d", WEXITSTATUS(status)); return WEXITSTATUS(status); } /* * Check whether a local network interface address appears in CIDR pattern- * list 'addrlist'. Returns 1 if matched or 0 otherwise. */ static int check_match_ifaddrs(const char *addrlist) { #ifdef HAVE_IFADDRS_H struct ifaddrs *ifa, *ifaddrs = NULL; int r, found = 0; char addr[NI_MAXHOST]; socklen_t salen; if (getifaddrs(&ifaddrs) != 0) { error("match localnetwork: getifaddrs failed: %s", strerror(errno)); return 0; } for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0) continue; switch (ifa->ifa_addr->sa_family) { case AF_INET: salen = sizeof(struct sockaddr_in); break; case AF_INET6: salen = sizeof(struct sockaddr_in6); break; #ifdef AF_LINK case AF_LINK: /* ignore */ continue; #endif /* AF_LINK */ default: debug2_f("interface %s: unsupported address family %d", ifa->ifa_name, ifa->ifa_addr->sa_family); continue; } if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) { debug2_f("interface %s getnameinfo failed: %s", ifa->ifa_name, gai_strerror(r)); continue; } debug3_f("interface %s addr %s", ifa->ifa_name, addr); if (addr_match_cidr_list(addr, addrlist) == 1) { debug3_f("matched interface %s: address %s in %s", ifa->ifa_name, addr, addrlist); found = 1; break; } } freeifaddrs(ifaddrs); return found; #else /* HAVE_IFADDRS_H */ error("match localnetwork: not supported on this platform"); return 0; #endif /* HAVE_IFADDRS_H */ } /* * Expand a "match exec" command or an Include path, caller must free returned * value. */ static char * expand_match_exec_or_include_path(const char *path, Options *options, struct passwd *pw, const char *host_arg, const char *original_host, int final_pass, int is_include_path) { char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; char uidstr[32], *conn_hash_hex, *keyalias, *jmphost, *ruser; char *host, *ret; int port; port = options->port <= 0 ? default_ssh_port() : options->port; ruser = options->user == NULL ? pw->pw_name : options->user; if (final_pass) { host = xstrdup(options->hostname); } else if (options->hostname != NULL) { /* NB. Please keep in sync with ssh.c:main() */ host = percent_expand(options->hostname, "h", host_arg, (char *)NULL); } else { host = xstrdup(host_arg); } if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); jmphost = option_clear_or_none(options->jump_host) ? "" : options->jump_host; strlcpy(shorthost, thishost, sizeof(shorthost)); shorthost[strcspn(thishost, ".")] = '\0'; snprintf(portstr, sizeof(portstr), "%d", port); snprintf(uidstr, sizeof(uidstr), "%llu", (unsigned long long)pw->pw_uid); conn_hash_hex = ssh_connection_hash(thishost, host, portstr, ruser, jmphost); keyalias = options->host_key_alias ? options->host_key_alias : host; ret = (is_include_path ? percent_dollar_expand : percent_expand)(path, "C", conn_hash_hex, "L", shorthost, "d", pw->pw_dir, "h", host, "k", keyalias, "l", thishost, "n", original_host, "p", portstr, "r", ruser, "u", pw->pw_name, "i", uidstr, "j", jmphost, (char *)NULL); free(host); free(conn_hash_hex); return ret; } /* * Parse and execute a Match directive. */ static int match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, struct passwd *pw, const char *host_arg, const char *original_host, const char *remote_command, int final_pass, int *want_final_pass, const char *filename, int linenum) { char *arg, *oattrib = NULL, *attrib = NULL, *cmd, *host, *criteria; const char *ruser; int r, this_result, result = 1, attributes = 0, negate; /* * Configuration is likely to be incomplete at this point so we * must be prepared to use default values. */ ruser = options->user == NULL ? pw->pw_name : options->user; if (final_pass) { host = xstrdup(options->hostname); } else if (options->hostname != NULL) { /* NB. Please keep in sync with ssh.c:main() */ host = percent_expand(options->hostname, "h", host_arg, (char *)NULL); } else { host = xstrdup(host_arg); } debug2("checking match for '%s' host %s originally %s", full_line, host, original_host); while ((attrib = argv_next(acp, avp)) != NULL) { attrib = oattrib = xstrdup(attrib); /* Terminate on comment */ if (*attrib == '#') { argv_consume(acp); break; } arg = criteria = NULL; this_result = 1; if ((negate = (attrib[0] == '!'))) attrib++; /* Criterion "all" has no argument and must appear alone */ if (strcasecmp(attrib, "all") == 0) { if (attributes > 1 || ((arg = argv_next(acp, avp)) != NULL && *arg != '\0' && *arg != '#')) { error("%.200s line %d: '%s' cannot be combined " "with other Match attributes", filename, linenum, oattrib); result = -1; goto out; } if (arg != NULL && *arg == '#') argv_consume(acp); /* consume remaining args */ if (result) result = negate ? 0 : 1; goto out; } attributes++; /* criteria "final" and "canonical" have no argument */ if (strcasecmp(attrib, "canonical") == 0 || strcasecmp(attrib, "final") == 0) { /* * If the config requests "Match final" then remember * this so we can perform a second pass later. */ if (strcasecmp(attrib, "final") == 0 && want_final_pass != NULL) *want_final_pass = 1; r = !!final_pass; /* force bitmask member to boolean */ if (r == (negate ? 1 : 0)) this_result = result = 0; debug3("%.200s line %d: %smatched '%s'", filename, linenum, this_result ? "" : "not ", oattrib); continue; } /* Keep this list in sync with below */ if (strprefix(attrib, "host=", 1) != NULL || strprefix(attrib, "originalhost=", 1) != NULL || strprefix(attrib, "user=", 1) != NULL || strprefix(attrib, "localuser=", 1) != NULL || strprefix(attrib, "localnetwork=", 1) != NULL || strprefix(attrib, "version=", 1) != NULL || strprefix(attrib, "tagged=", 1) != NULL || strprefix(attrib, "command=", 1) != NULL || strprefix(attrib, "exec=", 1) != NULL) { arg = strchr(attrib, '='); *(arg++) = '\0'; } else if ((arg = argv_next(acp, avp)) == NULL) { error("%.200s line %d: missing argument for Match '%s'", filename, linenum, oattrib); result = -1; goto out; } /* * All other criteria require an argument, though it may * be the empty string for the "tagged" and "command" * options. */ if (*arg == '\0' && strcasecmp(attrib, "tagged") != 0 && strcasecmp(attrib, "command") != 0) arg = NULL; if (arg == NULL || *arg == '#') { error("Missing Match criteria for %s", attrib); result = -1; goto out; } if (strcasecmp(attrib, "host") == 0) { criteria = xstrdup(host); r = match_hostname(host, arg) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "originalhost") == 0) { criteria = xstrdup(original_host); r = match_hostname(original_host, arg) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "user") == 0) { criteria = xstrdup(ruser); r = match_pattern_list(ruser, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "localuser") == 0) { criteria = xstrdup(pw->pw_name); r = match_pattern_list(pw->pw_name, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "localnetwork") == 0) { if (addr_match_cidr_list(NULL, arg) == -1) { /* Error already printed */ result = -1; goto out; } r = check_match_ifaddrs(arg) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "version") == 0) { criteria = xstrdup(SSH_RELEASE); r = match_pattern_list(SSH_RELEASE, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "tagged") == 0) { criteria = xstrdup(options->tag == NULL ? "" : options->tag); /* Special case: empty criteria matches empty arg */ r = (*criteria == '\0') ? *arg == '\0' : match_pattern_list(criteria, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "command") == 0) { criteria = xstrdup(remote_command == NULL ? "" : remote_command); /* Special case: empty criteria matches empty arg */ r = (*criteria == '\0') ? *arg == '\0' : match_pattern_list(criteria, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "sessiontype") == 0) { if (options->session_type == SESSION_TYPE_SUBSYSTEM) criteria = xstrdup("subsystem"); else if (options->session_type == SESSION_TYPE_NONE) criteria = xstrdup("none"); else if (remote_command != NULL && *remote_command != '\0') criteria = xstrdup("exec"); else criteria = xstrdup("shell"); r = match_pattern_list(criteria, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "exec") == 0) { if ((cmd = expand_match_exec_or_include_path(arg, options, pw, host_arg, original_host, final_pass, 0)) == NULL) { fatal("%.200s line %d: failed to expand match " "exec '%.100s'", filename, linenum, arg); } if (result != 1) { /* skip execution if prior predicate failed */ debug3("%.200s line %d: skipped exec " "\"%.100s\"", filename, linenum, cmd); free(cmd); continue; } r = execute_in_shell(cmd); if (r == -1) { fatal("%.200s line %d: match exec " "'%.100s' error", filename, linenum, cmd); } criteria = xstrdup(cmd); free(cmd); /* Force exit status to boolean */ r = r == 0; if (r == (negate ? 1 : 0)) this_result = result = 0; } else { error("Unsupported Match attribute %s", attrib); result = -1; goto out; } debug3("%.200s line %d: %smatched '%s%s%.100s%s' ", filename, linenum, this_result ? "": "not ", oattrib, criteria == NULL ? "" : " \"", criteria == NULL ? "" : criteria, criteria == NULL ? "" : "\""); free(criteria); free(oattrib); oattrib = attrib = NULL; } if (attributes == 0) { error("One or more attributes required for Match"); result = -1; goto out; } out: if (result != -1) debug2("match %sfound", result ? "" : "not "); free(oattrib); free(host); return result; } /* Remove environment variable by pattern */ static void rm_env(Options *options, const char *arg, const char *filename, int linenum) { u_int i, j, onum_send_env = options->num_send_env; /* Remove an environment variable */ for (i = 0; i < options->num_send_env; ) { if (!match_pattern(options->send_env[i], arg + 1)) { i++; continue; } debug3("%s line %d: removing environment %s", filename, linenum, options->send_env[i]); free(options->send_env[i]); options->send_env[i] = NULL; for (j = i; j < options->num_send_env - 1; j++) { options->send_env[j] = options->send_env[j + 1]; options->send_env[j + 1] = NULL; } options->num_send_env--; /* NB. don't increment i */ } if (onum_send_env != options->num_send_env) { options->send_env = xrecallocarray(options->send_env, onum_send_env, options->num_send_env, sizeof(*options->send_env)); } } /* * Returns the number of the token pointed to by cp or oBadOption. */ static OpCodes parse_token(const char *cp, const char *filename, int linenum, const char *ignored_unknown) { int i; for (i = 0; keywords[i].name; i++) if (strcmp(cp, keywords[i].name) == 0) return keywords[i].opcode; if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown, 1) == 1) return oIgnoredUnknownOption; error("%s: line %d: Bad configuration option: %s", filename, linenum, cp); return oBadOption; } static void free_canon_cnames(struct allowed_cname *cnames, u_int n) { u_int i; if (cnames == NULL || n == 0) return; for (i = 0; i < n; i++) { free(cnames[i].source_list); free(cnames[i].target_list); } free(cnames); } /* Multistate option parsing */ struct multistate { char *key; int value; }; static const struct multistate multistate_flag[] = { { "true", 1 }, { "false", 0 }, { "yes", 1 }, { "no", 0 }, { NULL, -1 } }; static const struct multistate multistate_yesnoask[] = { { "true", 1 }, { "false", 0 }, { "yes", 1 }, { "no", 0 }, { "ask", 2 }, { NULL, -1 } }; static const struct multistate multistate_strict_hostkey[] = { { "true", SSH_STRICT_HOSTKEY_YES }, { "false", SSH_STRICT_HOSTKEY_OFF }, { "yes", SSH_STRICT_HOSTKEY_YES }, { "no", SSH_STRICT_HOSTKEY_OFF }, { "ask", SSH_STRICT_HOSTKEY_ASK }, { "off", SSH_STRICT_HOSTKEY_OFF }, { "accept-new", SSH_STRICT_HOSTKEY_NEW }, { NULL, -1 } }; static const struct multistate multistate_yesnoaskconfirm[] = { { "true", 1 }, { "false", 0 }, { "yes", 1 }, { "no", 0 }, { "ask", 2 }, { "confirm", 3 }, { NULL, -1 } }; static const struct multistate multistate_addressfamily[] = { { "inet", AF_INET }, { "inet6", AF_INET6 }, { "any", AF_UNSPEC }, { NULL, -1 } }; static const struct multistate multistate_controlmaster[] = { { "true", SSHCTL_MASTER_YES }, { "yes", SSHCTL_MASTER_YES }, { "false", SSHCTL_MASTER_NO }, { "no", SSHCTL_MASTER_NO }, { "auto", SSHCTL_MASTER_AUTO }, { "ask", SSHCTL_MASTER_ASK }, { "autoask", SSHCTL_MASTER_AUTO_ASK }, { NULL, -1 } }; static const struct multistate multistate_tunnel[] = { { "ethernet", SSH_TUNMODE_ETHERNET }, { "point-to-point", SSH_TUNMODE_POINTOPOINT }, { "true", SSH_TUNMODE_DEFAULT }, { "yes", SSH_TUNMODE_DEFAULT }, { "false", SSH_TUNMODE_NO }, { "no", SSH_TUNMODE_NO }, { NULL, -1 } }; static const struct multistate multistate_requesttty[] = { { "true", REQUEST_TTY_YES }, { "yes", REQUEST_TTY_YES }, { "false", REQUEST_TTY_NO }, { "no", REQUEST_TTY_NO }, { "force", REQUEST_TTY_FORCE }, { "auto", REQUEST_TTY_AUTO }, { NULL, -1 } }; static const struct multistate multistate_sessiontype[] = { { "none", SESSION_TYPE_NONE }, { "subsystem", SESSION_TYPE_SUBSYSTEM }, { "default", SESSION_TYPE_DEFAULT }, { NULL, -1 } }; static const struct multistate multistate_canonicalizehostname[] = { { "true", SSH_CANONICALISE_YES }, { "false", SSH_CANONICALISE_NO }, { "yes", SSH_CANONICALISE_YES }, { "no", SSH_CANONICALISE_NO }, { "always", SSH_CANONICALISE_ALWAYS }, { NULL, -1 } }; static const struct multistate multistate_pubkey_auth[] = { { "true", SSH_PUBKEY_AUTH_ALL }, { "false", SSH_PUBKEY_AUTH_NO }, { "yes", SSH_PUBKEY_AUTH_ALL }, { "no", SSH_PUBKEY_AUTH_NO }, { "unbound", SSH_PUBKEY_AUTH_UNBOUND }, { "host-bound", SSH_PUBKEY_AUTH_HBOUND }, { NULL, -1 } }; static const struct multistate multistate_compression[] = { #ifdef WITH_ZLIB { "yes", COMP_DELAYED }, #endif { "no", COMP_NONE }, { NULL, -1 } }; static int parse_multistate_value(const char *arg, const char *filename, int linenum, const struct multistate *multistate_ptr) { int i; if (!arg || *arg == '\0') { error("%s line %d: missing argument.", filename, linenum); return -1; } for (i = 0; multistate_ptr[i].key != NULL; i++) { if (strcasecmp(arg, multistate_ptr[i].key) == 0) return multistate_ptr[i].value; } return -1; } /* * Processes a single option line as used in the configuration files. This * only sets those values that have not already been set. */ int process_config_line(Options *options, struct passwd *pw, const char *host, const char *original_host, const char *remote_command, char *line, const char *filename, int linenum, int *activep, int flags) { return process_config_line_depth(options, pw, host, original_host, remote_command, 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, const char *remote_command, char *line, const char *filename, int linenum, int *activep, int flags, int *want_final_pass, int depth) { char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p; char **cpptr, ***cppptr, fwdarg[256]; u_int i, *uintptr, max_entries = 0; int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; int remotefwd, dynamicfwd, ca_only = 0, found = 0; LogLevel *log_level_ptr; SyslogFacility *log_facility_ptr; long long val64; size_t len; struct Forward fwd; const struct multistate *multistate_ptr; glob_t gl; const char *errstr; char **oav = NULL, **av; int oac = 0, ac; int ret = -1; struct allowed_cname *cnames = NULL; u_int ncnames = 0; char **strs = NULL; /* string array arguments; freed implicitly */ u_int nstrs = 0; if (activep == NULL) { /* We are processing a command line directive */ cmdline = 1; activep = &cmdline; } /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ if ((len = strlen(line)) == 0) return 0; for (len--; len > 0; len--) { if (strchr(WHITESPACE "\f", line[len]) == NULL) break; line[len] = '\0'; } str = line; /* Get the keyword. (Each line is supposed to begin with a keyword). */ if ((keyword = strdelim(&str)) == NULL) return 0; /* Ignore leading whitespace. */ if (*keyword == '\0') keyword = strdelim(&str); if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') return 0; /* Match lowercase keyword */ lowercase(keyword); /* Prepare to parse remainder of line */ if (str != NULL) str += strspn(str, WHITESPACE); if (str == NULL || *str == '\0') { error("%s line %d: no argument after keyword \"%s\"", filename, linenum, keyword); return -1; } opcode = parse_token(keyword, filename, linenum, options->ignored_unknown); if (argv_split(str, &oac, &oav, 1) != 0) { error("%s line %d: invalid quotes", filename, linenum); return -1; } ac = oac; av = oav; switch (opcode) { case oBadOption: /* don't panic, but count bad options */ goto out; case oIgnore: argv_consume(&ac); break; case oIgnoredUnknownOption: debug("%s line %d: Ignored unknown option \"%s\"", filename, linenum, keyword); argv_consume(&ac); break; case oConnectTimeout: intptr = &options->connection_timeout; parse_time: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%s line %d: missing time value.", filename, linenum); goto out; } if (strcmp(arg, "none") == 0) value = -1; else if ((value = convtime(arg)) == -1) { error("%s line %d: invalid time value.", filename, linenum); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oForwardAgent: intptr = &options->forward_agent; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%s line %d: missing argument.", filename, linenum); goto out; } value = -1; multistate_ptr = multistate_flag; for (i = 0; multistate_ptr[i].key != NULL; i++) { if (strcasecmp(arg, multistate_ptr[i].key) == 0) { value = multistate_ptr[i].value; break; } } if (value != -1) { if (*activep && *intptr == -1) *intptr = value; break; } /* ForwardAgent wasn't 'yes' or 'no', assume a path */ if (*activep && *intptr == -1) *intptr = 1; charptr = &options->forward_agent_sock_path; goto parse_agent_path; case oForwardX11: intptr = &options->forward_x11; parse_flag: multistate_ptr = multistate_flag; parse_multistate: arg = argv_next(&ac, &av); if ((value = parse_multistate_value(arg, filename, linenum, multistate_ptr)) == -1) { error("%s line %d: unsupported option \"%s\".", filename, linenum, arg); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oForwardX11Trusted: intptr = &options->forward_x11_trusted; goto parse_flag; case oForwardX11Timeout: intptr = &options->forward_x11_timeout; goto parse_time; case oGatewayPorts: intptr = &options->fwd_opts.gateway_ports; goto parse_flag; case oExitOnForwardFailure: intptr = &options->exit_on_forward_failure; goto parse_flag; case oPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; case oKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; case oKbdInteractiveDevices: charptr = &options->kbd_interactive_devices; goto parse_string; case oPubkeyAuthentication: multistate_ptr = multistate_pubkey_auth; intptr = &options->pubkey_authentication; goto parse_multistate; case oHostbasedAuthentication: intptr = &options->hostbased_authentication; goto parse_flag; case oGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; case oGssDelegateCreds: intptr = &options->gss_deleg_creds; goto parse_flag; case oBatchMode: intptr = &options->batch_mode; goto parse_flag; case oCheckHostIP: intptr = &options->check_host_ip; goto parse_flag; case oVerifyHostKeyDNS: intptr = &options->verify_host_key_dns; multistate_ptr = multistate_yesnoask; goto parse_multistate; case oStrictHostKeyChecking: intptr = &options->strict_host_key_checking; multistate_ptr = multistate_strict_hostkey; goto parse_multistate; case oCompression: intptr = &options->compression; multistate_ptr = multistate_compression; goto parse_multistate; case oTCPKeepAlive: intptr = &options->tcp_keep_alive; goto parse_flag; case oNoHostAuthenticationForLocalhost: intptr = &options->no_host_authentication_for_localhost; goto parse_flag; case oNumberOfPasswordPrompts: intptr = &options->number_of_password_prompts; goto parse_int; case oRekeyLimit: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (strcmp(arg, "default") == 0) { val64 = 0; } else { if (scan_scaled(arg, &val64) == -1) { error("%.200s line %d: Bad number '%s': %s", filename, linenum, arg, strerror(errno)); goto out; } if (val64 != 0 && val64 < 16) { error("%.200s line %d: RekeyLimit too small", filename, linenum); goto out; } } if (*activep && options->rekey_limit == -1) options->rekey_limit = val64; if (ac != 0) { /* optional rekey interval present */ if (strcmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* discard */ break; } intptr = &options->rekey_interval; goto parse_time; } break; case oIdentityFile: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*activep) { intptr = &options->num_identity_files; if (*intptr >= SSH_MAX_IDENTITY_FILES) { error("%.200s line %d: Too many identity files " "specified (max %d).", filename, linenum, SSH_MAX_IDENTITY_FILES); goto out; } add_identity_file(options, NULL, arg, flags & SSHCONF_USERCONF); } break; case oCertificateFile: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*activep) { intptr = &options->num_certificate_files; if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { error("%.200s line %d: Too many certificate " "files specified (max %d).", filename, linenum, SSH_MAX_CERTIFICATE_FILES); goto out; } add_certificate_file(options, arg, flags & SSHCONF_USERCONF); } break; case oXAuthLocation: charptr=&options->xauth_location; goto parse_string; case oUser: charptr = &options->user; parse_string: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case oGlobalKnownHostsFile: cpptr = (char **)&options->system_hostfiles; uintptr = &options->num_system_hostfiles; max_entries = SSH_MAX_HOSTS_FILES; parse_char_array: i = 0; value = *uintptr == 0; /* was array empty when we started? */ while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } i++; if (*activep && value) { if ((*uintptr) >= max_entries) { error("%s line %d: too many %s " "entries.", filename, linenum, keyword); goto out; } cpptr[(*uintptr)++] = xstrdup(arg); } } break; case oUserKnownHostsFile: cpptr = (char **)&options->user_hostfiles; uintptr = &options->num_user_hostfiles; max_entries = SSH_MAX_HOSTS_FILES; goto parse_char_array; case oHostname: charptr = &options->hostname; goto parse_string; case oTag: charptr = &options->tag; goto parse_string; case oHostKeyAlias: charptr = &options->host_key_alias; goto parse_string; case oPreferredAuthentications: charptr = &options->preferred_authentications; goto parse_string; case oBindAddress: charptr = &options->bind_address; goto parse_string; case oBindInterface: charptr = &options->bind_interface; goto parse_string; case oPKCS11Provider: charptr = &options->pkcs11_provider; goto parse_string; case oSecurityKeyProvider: charptr = &options->sk_provider; goto parse_string; case oKnownHostsCommand: charptr = &options->known_hosts_command; goto parse_command; case oProxyCommand: charptr = &options->proxy_command; /* Ignore ProxyCommand if ProxyJump already specified */ if (options->jump_host != NULL) charptr = &options->jump_host; /* Skip below */ parse_command: if (str == NULL) { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } len = strspn(str, WHITESPACE "="); if (*activep && *charptr == NULL) *charptr = xstrdup(str + len); argv_consume(&ac); break; case oProxyJump: if (str == NULL) { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } len = strspn(str, WHITESPACE "="); /* XXX use argv? */ if (parse_jump(str + len, options, *activep) == -1) { error("%.200s line %d: Invalid ProxyJump \"%s\"", filename, linenum, str + len); goto out; } argv_consume(&ac); break; case oPort: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } value = a2port(arg); if (value <= 0) { error("%.200s line %d: Bad port '%s'.", filename, linenum, arg); goto out; } if (*activep && options->port == -1) options->port = value; break; case oConnectionAttempts: intptr = &options->connection_attempts; parse_int: arg = argv_next(&ac, &av); if ((errstr = atoi_err(arg, &value)) != NULL) { error("%s line %d: integer value %s.", filename, linenum, errstr); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oCiphers: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){ error("%.200s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && options->ciphers == NULL) options->ciphers = xstrdup(arg); break; case oMacs: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { error("%.200s line %d: Bad SSH2 MAC spec '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && options->macs == NULL) options->macs = xstrdup(arg); break; case oKexAlgorithms: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !kex_names_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && options->kex_algorithms == NULL) options->kex_algorithms = xstrdup(arg); break; case oHostKeyAlgorithms: charptr = &options->hostkeyalgorithms; ca_only = 0; parse_pubkey_algos: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !sshkey_names_valid2(*arg == '+' || *arg == '^' ? arg + 1 : arg, 1, ca_only)) { error("%s line %d: Bad key types '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case oCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; ca_only = 1; goto parse_pubkey_algos; case oLogLevel: log_level_ptr = &options->log_level; arg = argv_next(&ac, &av); value = log_level_number(arg); if (value == SYSLOG_LEVEL_NOT_SET) { error("%.200s line %d: unsupported log level '%s'", filename, linenum, arg ? arg : ""); goto out; } if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) *log_level_ptr = (LogLevel) value; break; case oLogFacility: log_facility_ptr = &options->log_facility; arg = argv_next(&ac, &av); value = log_facility_number(arg); if (value == SYSLOG_FACILITY_NOT_SET) { error("%.200s line %d: unsupported log facility '%s'", filename, linenum, arg ? arg : ""); goto out; } if (*log_facility_ptr == -1) *log_facility_ptr = (SyslogFacility) value; break; case oLogVerbose: cppptr = &options->log_verbose; uintptr = &options->num_log_verbose; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } i++; if (*activep && *uintptr == 0) { *cppptr = xrecallocarray(*cppptr, *uintptr, *uintptr + 1, sizeof(**cppptr)); (*cppptr)[(*uintptr)++] = xstrdup(arg); } } break; case oLocalForward: case oRemoteForward: case oDynamicForward: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } remotefwd = (opcode == oRemoteForward); dynamicfwd = (opcode == oDynamicForward); if (!dynamicfwd) { arg2 = argv_next(&ac, &av); if (arg2 == NULL || *arg2 == '\0') { if (remotefwd) dynamicfwd = 1; else { error("%.200s line %d: Missing target " "argument.", filename, linenum); goto out; } } else { /* construct a string for parse_forward */ snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); } } if (dynamicfwd) strlcpy(fwdarg, arg, sizeof(fwdarg)); if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) { error("%.200s line %d: Bad forwarding specification.", filename, linenum); goto out; } if (*activep) { if (remotefwd) { add_remote_forward(options, &fwd); } else { add_local_forward(options, &fwd); } } break; case oPermitRemoteOpen: uintptr = &options->num_permitted_remote_opens; cppptr = &options->permitted_remote_opens; found = *uintptr == 0; while ((arg = argv_next(&ac, &av)) != NULL) { arg2 = xstrdup(arg); /* Allow any/none only in first position */ if (strcasecmp(arg, "none") == 0 || strcasecmp(arg, "any") == 0) { if (nstrs > 0 || ac > 0) { error("%s line %d: keyword %s \"%s\" " "argument must appear alone.", filename, linenum, keyword, arg); free(arg2); goto out; } } else { p = hpdelim(&arg); if (p == NULL) { fatal("%s line %d: missing host in %s", filename, linenum, lookup_opcode_name(opcode)); } p = cleanhostname(p); /* * don't want to use permitopen_port to avoid * dependency on channels.[ch] here. */ if (arg == NULL || (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) { fatal("%s line %d: bad port number " "in %s", filename, linenum, lookup_opcode_name(opcode)); } } opt_array_append(filename, linenum, lookup_opcode_name(opcode), &strs, &nstrs, arg2); free(arg2); } if (nstrs == 0) fatal("%s line %d: missing %s specification", filename, linenum, lookup_opcode_name(opcode)); if (found && *activep) { *cppptr = strs; *uintptr = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case oClearAllForwardings: intptr = &options->clear_forwardings; goto parse_flag; case oHost: if (cmdline) { error("Host directive not supported as a command-line " "option"); goto out; } *activep = 0; arg2 = NULL; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } if ((flags & SSHCONF_NEVERMATCH) != 0) { argv_consume(&ac); break; } negated = *arg == '!'; if (negated) arg++; if (match_pattern(host, arg)) { if (negated) { debug("%.200s line %d: Skipping Host " "block because of negated match " "for %.100s", filename, linenum, arg); *activep = 0; argv_consume(&ac); break; } if (!*activep) arg2 = arg; /* logged below */ *activep = 1; } } if (*activep) debug("%.200s line %d: Applying options for %.100s", filename, linenum, arg2); break; case oMatch: if (cmdline) { error("Host directive not supported as a command-line " "option"); goto out; } value = match_cfg_line(options, str, &ac, &av, pw, host, original_host, remote_command, flags & SSHCONF_FINAL, want_final_pass, filename, linenum); if (value < 0) { error("%.200s line %d: Bad Match condition", filename, linenum); goto out; } *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; break; case oEscapeChar: intptr = &options->escape_char; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (strcmp(arg, "none") == 0) value = SSH_ESCAPECHAR_NONE; else if (arg[1] == '\0') value = (u_char) arg[0]; else if (arg[0] == '^' && arg[2] == 0 && (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) value = (u_char) arg[1] & 31; else { error("%.200s line %d: Bad escape character.", filename, linenum); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oAddressFamily: intptr = &options->address_family; multistate_ptr = multistate_addressfamily; goto parse_multistate; case oEnableSSHKeysign: intptr = &options->enable_ssh_keysign; goto parse_flag; case oIdentitiesOnly: intptr = &options->identities_only; goto parse_flag; case oServerAliveInterval: intptr = &options->server_alive_interval; goto parse_time; case oServerAliveCountMax: intptr = &options->server_alive_count_max; goto parse_int; case oSendEnv: /* XXX appends to list; doesn't respect first-match-wins */ while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || strchr(arg, '=') != NULL) { error("%s line %d: Invalid environment name.", filename, linenum); goto out; } found = 1; if (!*activep) continue; if (*arg == '-') { /* Removing an env var */ rm_env(options, arg, filename, linenum); continue; } opt_array_append(filename, linenum, lookup_opcode_name(opcode), &options->send_env, &options->num_send_env, arg); } if (!found) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } break; case oSetEnv: found = options->num_setenv == 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (strchr(arg, '=') == NULL) { error("%s line %d: Invalid SetEnv.", filename, linenum); goto out; } if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) { debug2("%s line %d: ignoring duplicate env " "name \"%.64s\"", filename, linenum, arg); continue; } opt_array_append(filename, linenum, lookup_opcode_name(opcode), &strs, &nstrs, arg); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->setenv = strs; options->num_setenv = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case oControlPath: charptr = &options->control_path; goto parse_string; case oControlMaster: intptr = &options->control_master; multistate_ptr = multistate_controlmaster; goto parse_multistate; case oControlPersist: /* no/false/yes/true, or a time spec */ intptr = &options->control_persist; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing ControlPersist" " argument.", filename, linenum); goto out; } value = 0; value2 = 0; /* timeout */ if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) value = 0; else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) value = 1; else if ((value2 = convtime(arg)) >= 0) value = 1; else { error("%.200s line %d: Bad ControlPersist argument.", filename, linenum); goto out; } if (*activep && *intptr == -1) { *intptr = value; options->control_persist_timeout = value2; } break; case oHashKnownHosts: intptr = &options->hash_known_hosts; goto parse_flag; case oTunnel: intptr = &options->tun_open; multistate_ptr = multistate_tunnel; goto parse_multistate; case oTunnelDevice: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } value = a2tun(arg, &value2); if (value == SSH_TUNID_ERR) { error("%.200s line %d: Bad tun device.", filename, linenum); goto out; } if (*activep && options->tun_local == -1) { options->tun_local = value; options->tun_remote = value2; } break; case oLocalCommand: charptr = &options->local_command; goto parse_command; case oPermitLocalCommand: intptr = &options->permit_local_command; goto parse_flag; case oRemoteCommand: charptr = &options->remote_command; goto parse_command; case oVisualHostKey: intptr = &options->visual_host_key; goto parse_flag; case oInclude: if (cmdline) { error("Include directive not supported as a " "command-line option"); goto out; } value = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Expand %tokens and environment variables */ if ((p = expand_match_exec_or_include_path(arg, options, pw, host, original_host, flags & SSHCONF_FINAL, 1)) == NULL) { error("%.200s line %d: Unable to expand user " "config file '%.100s'", filename, linenum, arg); continue; } /* * 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 (*p == '~' && (flags & SSHCONF_USERCONF) == 0) { error("%.200s line %d: bad include path %s.", filename, linenum, p); goto out; } if (!path_absolute(p) && *p != '~') { xasprintf(&arg2, "%s/%s", (flags & SSHCONF_USERCONF) ? "~/" _PATH_SSH_USER_DIR : SSHDIR, p); } else { arg2 = xstrdup(p); } free(p); memset(&gl, 0, sizeof(gl)); r = glob(arg2, GLOB_TILDE, NULL, &gl); if (r == GLOB_NOMATCH) { debug("%.200s line %d: include %s matched no " "files",filename, linenum, arg2); free(arg2); continue; } else if (r != 0) { error("%.200s line %d: glob failed for %s.", filename, linenum, arg2); goto out; } free(arg2); oactive = *activep; for (i = 0; i < gl.gl_pathc; i++) { debug3("%.200s line %d: Including file %s " "depth %d%s", filename, linenum, gl.gl_pathv[i], depth, oactive ? "" : " (parse only)"); r = read_config_file_depth(gl.gl_pathv[i], pw, host, original_host, remote_command, options, flags | SSHCONF_CHECKPERM | (oactive ? 0 : SSHCONF_NEVERMATCH), activep, want_final_pass, depth + 1); if (r != 1 && errno != ENOENT) { error("%.200s line %d: Can't open user " "config file %.100s: %.100s", filename, linenum, gl.gl_pathv[i], strerror(errno)); globfree(&gl); goto out; } /* * don't let Match in includes clobber the * containing file's Match state. */ *activep = oactive; if (r != 1) value = -1; } globfree(&gl); } if (value != 0) ret = value; break; case oIPQoS: arg = argv_next(&ac, &av); if ((value = parse_ipqos(arg)) == -1) { error("%s line %d: Bad IPQoS value: %s", filename, linenum, arg); goto out; } arg = argv_next(&ac, &av); if (arg == NULL) value2 = value; else if ((value2 = parse_ipqos(arg)) == -1) { error("%s line %d: Bad IPQoS value: %s", filename, linenum, arg); goto out; } if (*activep && options->ip_qos_interactive == -1) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; } break; case oRequestTTY: intptr = &options->request_tty; multistate_ptr = multistate_requesttty; goto parse_multistate; case oSessionType: intptr = &options->session_type; multistate_ptr = multistate_sessiontype; goto parse_multistate; case oStdinNull: intptr = &options->stdin_null; goto parse_flag; case oForkAfterAuthentication: intptr = &options->fork_after_authentication; goto parse_flag; case oIgnoreUnknown: charptr = &options->ignored_unknown; goto parse_string; case oProxyUseFdpass: intptr = &options->proxy_use_fdpass; goto parse_flag; case oCanonicalDomains: found = options->num_canonical_domains == 0; while ((arg = argv_next(&ac, &av)) != NULL) { /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (nstrs > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } if (!valid_domain(arg, 1, &errstr)) { error("%s line %d: %s", filename, linenum, errstr); goto out; } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->canonical_domains = strs; options->num_canonical_domains = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case oCanonicalizePermittedCNAMEs: found = options->num_permitted_cnames == 0; while ((arg = argv_next(&ac, &av)) != NULL) { /* * Either 'none' (only in first position), '*' for * everything or 'list:list' */ if (strcasecmp(arg, "none") == 0) { if (ncnames > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } arg2 = ""; } else if (strcmp(arg, "*") == 0) { arg2 = arg; } else { lowercase(arg); if ((arg2 = strchr(arg, ':')) == NULL || arg2[1] == '\0') { error("%s line %d: " "Invalid permitted CNAME \"%s\"", filename, linenum, arg); goto out; } *arg2 = '\0'; arg2++; } cnames = xrecallocarray(cnames, ncnames, ncnames + 1, sizeof(*cnames)); cnames[ncnames].source_list = xstrdup(arg); cnames[ncnames].target_list = xstrdup(arg2); ncnames++; } if (ncnames == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->permitted_cnames = cnames; options->num_permitted_cnames = ncnames; cnames = NULL; /* transferred */ ncnames = 0; } /* un-transferred cnames is cleaned up before exit */ break; case oCanonicalizeHostname: intptr = &options->canonicalize_hostname; multistate_ptr = multistate_canonicalizehostname; goto parse_multistate; case oCanonicalizeMaxDots: intptr = &options->canonicalize_max_dots; goto parse_int; case oCanonicalizeFallbackLocal: intptr = &options->canonicalize_fallback_local; goto parse_flag; case oStreamLocalBindMask: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing StreamLocalBindMask " "argument.", filename, linenum); goto out; } /* Parse mode in octal format */ value = strtol(arg, &endofnumber, 8); if (arg == endofnumber || value < 0 || value > 0777) { error("%.200s line %d: Bad mask.", filename, linenum); goto out; } options->fwd_opts.streamlocal_bind_mask = (mode_t)value; break; case oStreamLocalBindUnlink: intptr = &options->fwd_opts.streamlocal_bind_unlink; goto parse_flag; case oRevokedHostKeys: charptr = &options->revoked_host_keys; goto parse_string; case oFingerprintHash: intptr = &options->fingerprint_hash; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if ((value = ssh_digest_alg_by_name(arg)) == -1) { error("%.200s line %d: Invalid hash algorithm \"%s\".", filename, linenum, arg); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oUpdateHostkeys: intptr = &options->update_hostkeys; multistate_ptr = multistate_yesnoask; goto parse_multistate; case oHostbasedAcceptedAlgorithms: charptr = &options->hostbased_accepted_algos; ca_only = 0; goto parse_pubkey_algos; case oPubkeyAcceptedAlgorithms: charptr = &options->pubkey_accepted_algos; ca_only = 0; goto parse_pubkey_algos; case oAddKeysToAgent: arg = argv_next(&ac, &av); arg2 = argv_next(&ac, &av); value = parse_multistate_value(arg, filename, linenum, multistate_yesnoaskconfirm); value2 = 0; /* unlimited lifespan by default */ if (value == 3 && arg2 != NULL) { /* allow "AddKeysToAgent confirm 5m" */ if ((value2 = convtime(arg2)) == -1) { error("%s line %d: invalid time value.", filename, linenum); goto out; } } else if (value == -1 && arg2 == NULL) { if ((value2 = convtime(arg)) == -1) { error("%s line %d: unsupported option", filename, linenum); goto out; } value = 1; /* yes */ } else if (value == -1 || arg2 != NULL) { error("%s line %d: unsupported option", filename, linenum); goto out; } if (*activep && options->add_keys_to_agent == -1) { options->add_keys_to_agent = value; options->add_keys_to_agent_lifespan = value2; } break; case oIdentityAgent: charptr = &options->identity_agent; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } parse_agent_path: /* Extra validation if the string represents an env var. */ if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { error("%.200s line %d: Invalid environment expansion " "%s.", filename, linenum, arg); goto out; } free(arg2); /* check for legacy environment format */ if (arg[0] == '$' && arg[1] != '{' && !valid_env_name(arg + 1)) { error("%.200s line %d: Invalid environment name %s.", filename, linenum, arg); goto out; } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case oEnableEscapeCommandline: intptr = &options->enable_escape_commandline; goto parse_flag; case oRequiredRSASize: intptr = &options->required_rsa_size; goto parse_int; case oObscureKeystrokeTiming: value = -1; while ((arg = argv_next(&ac, &av)) != NULL) { if (value != -1) { error("%s line %d: invalid arguments", filename, linenum); goto out; } if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) value = 0; else if (strncmp(arg, "interval:", 9) == 0) { if ((errstr = atoi_err(arg + 9, &value)) != NULL) { error("%s line %d: integer value %s.", filename, linenum, errstr); goto out; } if (value <= 0 || value > 1000) { error("%s line %d: value out of range.", filename, linenum); goto out; } } else { error("%s line %d: unsupported argument \"%s\"", filename, linenum, arg); goto out; } } if (value == -1) { error("%s line %d: missing argument", filename, linenum); goto out; } intptr = &options->obscure_keystroke_timing_interval; if (*activep && *intptr == -1) *intptr = value; break; case oChannelTimeout: found = options->num_channel_timeouts == 0; while ((arg = argv_next(&ac, &av)) != NULL) { /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (nstrs > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } else if (parse_pattern_interval(arg, NULL, NULL) != 0) { fatal("%s line %d: invalid channel timeout %s", filename, linenum, arg); } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->channel_timeouts = strs; options->num_channel_timeouts = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case oVersionAddendum: if (str == NULL || *str == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); len = strspn(str, WHITESPACE); if (strchr(str + len, '\r') != NULL) { fatal("%.200s line %d: Invalid %s argument", filename, linenum, keyword); } if ((arg = strchr(line, '#')) != NULL) { *arg = '\0'; rtrim(line); } if (*activep && options->version_addendum == NULL) { if (strcasecmp(str + len, "none") == 0) options->version_addendum = xstrdup(""); else options->version_addendum = xstrdup(str + len); } argv_consume(&ac); break; case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); argv_consume(&ac); break; case oUnsupported: error("%s line %d: Unsupported option \"%s\"", filename, linenum, keyword); argv_consume(&ac); break; default: error("%s line %d: Unimplemented opcode %d", filename, linenum, opcode); goto out; } /* Check that there is no garbage at end of line. */ if (ac > 0) { error("%.200s line %d: keyword %s extra arguments " "at end of line", filename, linenum, keyword); goto out; } /* success */ ret = 0; out: free_canon_cnames(cnames, ncnames); opt_array_free2(strs, NULL, nstrs); argv_free(oav, oac); return ret; } /* * Reads the config file and modifies the options accordingly. Options * should already be initialized before this call. This never returns if * there is an error. If the file does not exist, this returns 0. */ int read_config_file(const char *filename, struct passwd *pw, const char *host, const char *original_host, const char *remote_command, Options *options, int flags, int *want_final_pass) { int active = 1; return read_config_file_depth(filename, pw, host, original_host, remote_command, 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, const char *remote_command, Options *options, int flags, int *activep, int *want_final_pass, int depth) { FILE *f; char *line = NULL; size_t linesize = 0; int linenum; int bad_options = 0; if (depth < 0 || depth > READCONF_MAX_DEPTH) fatal("Too many recursive configuration includes"); if ((f = fopen(filename, "r")) == NULL) return 0; if (flags & SSHCONF_CHECKPERM) { struct stat sb; if (fstat(fileno(f), &sb) == -1) fatal("fstat %s: %s", filename, strerror(errno)); if (((sb.st_uid != 0 && sb.st_uid != getuid()) || (sb.st_mode & 022) != 0)) fatal("Bad owner or permissions on %s", filename); } debug("Reading configuration data %.200s", filename); /* * Mark that we are now processing the options. This flag is turned * on/off by Host specifications. */ linenum = 0; while (getline(&line, &linesize, f) != -1) { /* Update line number counter. */ linenum++; /* * Trim out comments and strip whitespace. * NB - preserve newlines, they are needed to reproduce * line numbers later for error messages. */ if (process_config_line_depth(options, pw, host, original_host, remote_command, line, filename, linenum, activep, flags, want_final_pass, depth) != 0) bad_options++; } free(line); fclose(f); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", filename, bad_options); return 1; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ int option_clear_or_none(const char *o) { return o == NULL || strcasecmp(o, "none") == 0; } /* * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise. * Allowed to be called on non-final configuration. */ int config_has_permitted_cnames(Options *options) { if (options->num_permitted_cnames == 1 && strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 && strcmp(options->permitted_cnames[0].target_list, "") == 0) return 0; return options->num_permitted_cnames > 0; } /* * Initializes options to special values that indicate that they have not yet * been set. Read_config_file will only set options with this value. Options * are processed in the following order: command line, user config file, * system config file. Last, fill_default_options is called. */ void initialize_options(Options * options) { memset(options, 'X', sizeof(*options)); options->host_arg = NULL; options->forward_agent = -1; options->forward_agent_sock_path = NULL; options->forward_x11 = -1; options->forward_x11_trusted = -1; options->forward_x11_timeout = -1; options->stdio_forward_host = NULL; options->stdio_forward_port = 0; options->clear_forwardings = -1; options->exit_on_forward_failure = -1; options->xauth_location = NULL; options->fwd_opts.gateway_ports = -1; options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; options->gss_deleg_creds = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; options->hostbased_authentication = -1; options->batch_mode = -1; options->check_host_ip = -1; options->strict_host_key_checking = -1; options->compression = -1; options->tcp_keep_alive = -1; options->port = -1; options->address_family = -1; options->connection_attempts = -1; options->connection_timeout = -1; options->number_of_password_prompts = -1; options->ciphers = NULL; options->macs = NULL; options->kex_algorithms = NULL; options->hostkeyalgorithms = NULL; options->ca_sign_algorithms = NULL; options->num_identity_files = 0; memset(options->identity_keys, 0, sizeof(options->identity_keys)); options->num_certificate_files = 0; memset(options->certificates, 0, sizeof(options->certificates)); options->hostname = NULL; options->host_key_alias = NULL; options->proxy_command = NULL; options->jump_user = NULL; options->jump_host = NULL; options->jump_port = -1; options->jump_extra = NULL; options->user = NULL; options->escape_char = -1; options->num_system_hostfiles = 0; options->num_user_hostfiles = 0; options->local_forwards = NULL; options->num_local_forwards = 0; options->remote_forwards = NULL; options->num_remote_forwards = 0; options->permitted_remote_opens = NULL; options->num_permitted_remote_opens = 0; options->log_facility = SYSLOG_FACILITY_NOT_SET; options->log_level = SYSLOG_LEVEL_NOT_SET; options->num_log_verbose = 0; options->log_verbose = NULL; options->preferred_authentications = NULL; options->bind_address = NULL; options->bind_interface = NULL; options->pkcs11_provider = NULL; options->sk_provider = NULL; options->enable_ssh_keysign = - 1; options->no_host_authentication_for_localhost = - 1; options->identities_only = - 1; options->rekey_limit = - 1; options->rekey_interval = -1; options->verify_host_key_dns = -1; options->server_alive_interval = -1; options->server_alive_count_max = -1; options->send_env = NULL; options->num_send_env = 0; options->setenv = NULL; options->num_setenv = 0; options->control_path = NULL; options->control_master = -1; options->control_persist = -1; options->control_persist_timeout = 0; options->hash_known_hosts = -1; options->tun_open = -1; options->tun_local = -1; options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; options->remote_command = NULL; options->add_keys_to_agent = -1; options->add_keys_to_agent_lifespan = -1; options->identity_agent = NULL; options->visual_host_key = -1; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->request_tty = -1; options->session_type = -1; options->stdin_null = -1; options->fork_after_authentication = -1; options->proxy_use_fdpass = -1; options->ignored_unknown = NULL; options->num_canonical_domains = 0; options->num_permitted_cnames = 0; options->canonicalize_max_dots = -1; options->canonicalize_fallback_local = -1; options->canonicalize_hostname = -1; options->revoked_host_keys = NULL; options->fingerprint_hash = -1; options->update_hostkeys = -1; options->hostbased_accepted_algos = NULL; options->pubkey_accepted_algos = NULL; options->known_hosts_command = NULL; options->required_rsa_size = -1; options->enable_escape_commandline = -1; options->obscure_keystroke_timing_interval = -1; options->tag = NULL; options->channel_timeouts = NULL; options->num_channel_timeouts = 0; options->version_addendum = NULL; } /* * A petite version of fill_default_options() that just fills the options * needed for hostname canonicalization to proceed. */ void fill_default_options_for_canonicalization(Options *options) { if (options->canonicalize_max_dots == -1) options->canonicalize_max_dots = 1; if (options->canonicalize_fallback_local == -1) options->canonicalize_fallback_local = 1; if (options->canonicalize_hostname == -1) options->canonicalize_hostname = SSH_CANONICALISE_NO; } /* * Called after processing other sources of option data, this fills those * options for which no value has been specified with their default values. */ int fill_default_options(Options * options) { char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; int ret = 0, r; if (options->forward_agent == -1) options->forward_agent = 0; if (options->forward_x11 == -1) options->forward_x11 = 0; if (options->forward_x11_trusted == -1) options->forward_x11_trusted = 0; if (options->forward_x11_timeout == -1) options->forward_x11_timeout = 1200; /* * stdio forwarding (-W) changes the default for these but we defer * setting the values so they can be overridden. */ if (options->exit_on_forward_failure == -1) options->exit_on_forward_failure = options->stdio_forward_host != NULL ? 1 : 0; if (options->clear_forwardings == -1) options->clear_forwardings = options->stdio_forward_host != NULL ? 1 : 0; if (options->clear_forwardings == 1) clear_forwardings(options); if (options->xauth_location == NULL) options->xauth_location = xstrdup(_PATH_XAUTH); if (options->fwd_opts.gateway_ports == -1) options->fwd_opts.gateway_ports = 0; if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) options->fwd_opts.streamlocal_bind_mask = 0177; if (options->fwd_opts.streamlocal_bind_unlink == -1) options->fwd_opts.streamlocal_bind_unlink = 0; if (options->pubkey_authentication == -1) options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_deleg_creds == -1) options->gss_deleg_creds = 0; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) options->kbd_interactive_authentication = 1; if (options->hostbased_authentication == -1) options->hostbased_authentication = 0; if (options->batch_mode == -1) options->batch_mode = 0; if (options->check_host_ip == -1) options->check_host_ip = 0; if (options->strict_host_key_checking == -1) options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; if (options->compression == -1) options->compression = 0; if (options->tcp_keep_alive == -1) options->tcp_keep_alive = 1; if (options->port == -1) options->port = 0; /* Filled in ssh_connect. */ if (options->address_family == -1) options->address_family = AF_UNSPEC; if (options->connection_attempts == -1) options->connection_attempts = 1; if (options->number_of_password_prompts == -1) options->number_of_password_prompts = 3; /* options->hostkeyalgorithms, default set in myproposals.h */ if (options->add_keys_to_agent == -1) { options->add_keys_to_agent = 0; options->add_keys_to_agent_lifespan = 0; } if (options->num_identity_files == 0) { add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); #ifdef OPENSSL_HAS_ECC add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); #endif add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ED25519, 0); add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ED25519_SK, 0); add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); #ifdef WITH_DSA add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); #endif } if (options->escape_char == -1) options->escape_char = '~'; if (options->num_system_hostfiles == 0) { options->system_hostfiles[options->num_system_hostfiles++] = xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); options->system_hostfiles[options->num_system_hostfiles++] = xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); } if (options->update_hostkeys == -1) { if (options->verify_host_key_dns <= 0 && (options->num_user_hostfiles == 0 || (options->num_user_hostfiles == 1 && strcmp(options-> user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; else options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; } if (options->num_user_hostfiles == 0) { options->user_hostfiles[options->num_user_hostfiles++] = xstrdup(_PATH_SSH_USER_HOSTFILE); options->user_hostfiles[options->num_user_hostfiles++] = xstrdup(_PATH_SSH_USER_HOSTFILE2); } if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; if (options->log_facility == SYSLOG_FACILITY_NOT_SET) options->log_facility = SYSLOG_FACILITY_USER; if (options->no_host_authentication_for_localhost == - 1) options->no_host_authentication_for_localhost = 0; if (options->identities_only == -1) options->identities_only = 0; if (options->enable_ssh_keysign == -1) options->enable_ssh_keysign = 0; if (options->rekey_limit == -1) options->rekey_limit = 0; if (options->rekey_interval == -1) options->rekey_interval = 0; if (options->verify_host_key_dns == -1) options->verify_host_key_dns = 0; if (options->server_alive_interval == -1) options->server_alive_interval = 0; if (options->server_alive_count_max == -1) options->server_alive_count_max = 3; if (options->control_master == -1) options->control_master = 0; if (options->control_persist == -1) { options->control_persist = 0; options->control_persist_timeout = 0; } if (options->hash_known_hosts == -1) options->hash_known_hosts = 0; if (options->tun_open == -1) options->tun_open = SSH_TUNMODE_NO; if (options->tun_local == -1) options->tun_local = SSH_TUNID_ANY; if (options->tun_remote == -1) options->tun_remote = SSH_TUNID_ANY; if (options->permit_local_command == -1) options->permit_local_command = 0; if (options->visual_host_key == -1) options->visual_host_key = 0; if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_DSCP_AF21; if (options->ip_qos_bulk == -1) options->ip_qos_bulk = IPTOS_DSCP_CS1; if (options->request_tty == -1) options->request_tty = REQUEST_TTY_AUTO; if (options->session_type == -1) options->session_type = SESSION_TYPE_DEFAULT; if (options->stdin_null == -1) options->stdin_null = 0; if (options->fork_after_authentication == -1) options->fork_after_authentication = 0; if (options->proxy_use_fdpass == -1) options->proxy_use_fdpass = 0; if (options->canonicalize_max_dots == -1) options->canonicalize_max_dots = 1; if (options->canonicalize_fallback_local == -1) options->canonicalize_fallback_local = 1; if (options->canonicalize_hostname == -1) options->canonicalize_hostname = SSH_CANONICALISE_NO; if (options->fingerprint_hash == -1) options->fingerprint_hash = SSH_FP_HASH_DEFAULT; #ifdef ENABLE_SK_INTERNAL if (options->sk_provider == NULL) options->sk_provider = xstrdup("internal"); #else if (options->sk_provider == NULL) options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); #endif if (options->required_rsa_size == -1) options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; if (options->enable_escape_commandline == -1) options->enable_escape_commandline = 0; if (options->obscure_keystroke_timing_interval == -1) { options->obscure_keystroke_timing_interval = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; } /* Expand KEX name lists */ all_cipher = cipher_alg_list(',', 0); all_mac = mac_alg_list(','); all_kex = kex_alg_list(','); all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* remove unsupported algos from default lists */ def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); #define ASSEMBLE(what, defaults, all) \ do { \ if ((r = kex_assemble_names(&options->what, \ defaults, all)) != 0) { \ error_fr(r, "%s", #what); \ goto fail; \ } \ } while (0) ASSEMBLE(ciphers, def_cipher, all_cipher); ASSEMBLE(macs, def_mac, all_mac); ASSEMBLE(kex_algorithms, def_kex, all_kex); ASSEMBLE(hostbased_accepted_algos, def_key, all_key); ASSEMBLE(pubkey_accepted_algos, def_key, all_key); ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); #undef ASSEMBLE #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ free(v); \ v = NULL; \ } \ } while(0) #define CLEAR_ON_NONE_ARRAY(v, nv, none) \ do { \ if (options->nv == 1 && \ strcasecmp(options->v[0], none) == 0) { \ free(options->v[0]); \ free(options->v); \ options->v = NULL; \ options->nv = 0; \ } \ } while (0) CLEAR_ON_NONE(options->local_command); CLEAR_ON_NONE(options->remote_command); CLEAR_ON_NONE(options->proxy_command); CLEAR_ON_NONE(options->control_path); CLEAR_ON_NONE(options->revoked_host_keys); CLEAR_ON_NONE(options->pkcs11_provider); CLEAR_ON_NONE(options->sk_provider); CLEAR_ON_NONE(options->known_hosts_command); CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); #undef CLEAR_ON_NONE #undef CLEAR_ON_NONE_ARRAY if (options->jump_host != NULL && strcmp(options->jump_host, "none") == 0 && options->jump_port == 0 && options->jump_user == NULL) { free(options->jump_host); options->jump_host = NULL; } if (options->num_permitted_cnames == 1 && !config_has_permitted_cnames(options)) { /* clean up CanonicalizePermittedCNAMEs=none */ free(options->permitted_cnames[0].source_list); free(options->permitted_cnames[0].target_list); memset(options->permitted_cnames, '\0', sizeof(*options->permitted_cnames)); options->num_permitted_cnames = 0; } /* options->identity_agent distinguishes NULL from 'none' */ /* options->user will be set in the main program if appropriate */ /* options->hostname will be set in the main program if appropriate */ /* options->host_key_alias should not be set by default */ /* options->preferred_authentications will be set in ssh */ /* success */ ret = 0; fail: free(all_cipher); free(all_mac); free(all_kex); free(all_key); free(all_sig); free(def_cipher); free(def_mac); free(def_kex); free(def_key); free(def_sig); return ret; } void free_options(Options *o) { int i; if (o == NULL) return; #define FREE_ARRAY(type, n, a) \ do { \ type _i; \ for (_i = 0; _i < (n); _i++) \ free((a)[_i]); \ } while (0) free(o->forward_agent_sock_path); free(o->xauth_location); FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); free(o->log_verbose); free(o->ciphers); free(o->macs); free(o->hostkeyalgorithms); free(o->kex_algorithms); free(o->ca_sign_algorithms); free(o->hostname); free(o->host_key_alias); free(o->proxy_command); free(o->user); FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); free(o->preferred_authentications); free(o->bind_address); free(o->bind_interface); free(o->pkcs11_provider); free(o->sk_provider); for (i = 0; i < o->num_identity_files; i++) { free(o->identity_files[i]); sshkey_free(o->identity_keys[i]); } for (i = 0; i < o->num_certificate_files; i++) { free(o->certificate_files[i]); sshkey_free(o->certificates[i]); } free(o->identity_agent); for (i = 0; i < o->num_local_forwards; i++) { free(o->local_forwards[i].listen_host); free(o->local_forwards[i].listen_path); free(o->local_forwards[i].connect_host); free(o->local_forwards[i].connect_path); } free(o->local_forwards); for (i = 0; i < o->num_remote_forwards; i++) { free(o->remote_forwards[i].listen_host); free(o->remote_forwards[i].listen_path); free(o->remote_forwards[i].connect_host); free(o->remote_forwards[i].connect_path); } free(o->remote_forwards); free(o->stdio_forward_host); FREE_ARRAY(u_int, o->num_send_env, o->send_env); free(o->send_env); FREE_ARRAY(u_int, o->num_setenv, o->setenv); free(o->setenv); free(o->control_path); free(o->local_command); free(o->remote_command); FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); for (i = 0; i < o->num_permitted_cnames; i++) { free(o->permitted_cnames[i].source_list); free(o->permitted_cnames[i].target_list); } free(o->revoked_host_keys); free(o->hostbased_accepted_algos); free(o->pubkey_accepted_algos); free(o->jump_user); free(o->jump_host); free(o->jump_extra); free(o->ignored_unknown); explicit_bzero(o, sizeof(*o)); #undef FREE_ARRAY } struct fwdarg { char *arg; int ispath; }; /* * parse_fwd_field * parses the next field in a port forwarding specification. * sets fwd to the parsed field and advances p past the colon * or sets it to NULL at end of string. * returns 0 on success, else non-zero. */ static int parse_fwd_field(char **p, struct fwdarg *fwd) { char *ep, *cp = *p; int ispath = 0; if (*cp == '\0') { *p = NULL; return -1; /* end of string */ } /* * A field escaped with square brackets is used literally. * XXX - allow ']' to be escaped via backslash? */ if (*cp == '[') { /* find matching ']' */ for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { if (*ep == '/') ispath = 1; } /* no matching ']' or not at end of field. */ if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) return -1; /* NUL terminate the field and advance p past the colon */ *ep++ = '\0'; if (*ep != '\0') *ep++ = '\0'; fwd->arg = cp + 1; fwd->ispath = ispath; *p = ep; return 0; } for (cp = *p; *cp != '\0'; cp++) { switch (*cp) { case '\\': memmove(cp, cp + 1, strlen(cp + 1) + 1); if (*cp == '\0') return -1; break; case '/': ispath = 1; break; case ':': *cp++ = '\0'; goto done; } } done: fwd->arg = *p; fwd->ispath = ispath; *p = cp; return 0; } /* * parse_forward * parses a string containing a port forwarding specification of the form: * dynamicfwd == 0 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath * listenpath:connectpath * dynamicfwd == 1 * [listenhost:]listenport * returns number of arguments parsed or zero on error */ int parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) { struct fwdarg fwdargs[4]; char *p, *cp; int i, err; memset(fwd, 0, sizeof(*fwd)); memset(fwdargs, 0, sizeof(fwdargs)); /* * We expand environment variables before checking if we think they're * paths so that if ${VAR} expands to a fully qualified path it is * treated as a path. */ cp = p = dollar_expand(&err, fwdspec); if (p == NULL || err) return 0; /* skip leading spaces */ while (isspace((u_char)*cp)) cp++; for (i = 0; i < 4; ++i) { if (parse_fwd_field(&cp, &fwdargs[i]) != 0) break; } /* Check for trailing garbage */ if (cp != NULL && *cp != '\0') { i = 0; /* failure */ } switch (i) { case 1: if (fwdargs[0].ispath) { fwd->listen_path = xstrdup(fwdargs[0].arg); fwd->listen_port = PORT_STREAMLOCAL; } else { fwd->listen_host = NULL; fwd->listen_port = a2port(fwdargs[0].arg); } fwd->connect_host = xstrdup("socks"); break; case 2: if (fwdargs[0].ispath && fwdargs[1].ispath) { fwd->listen_path = xstrdup(fwdargs[0].arg); fwd->listen_port = PORT_STREAMLOCAL; fwd->connect_path = xstrdup(fwdargs[1].arg); fwd->connect_port = PORT_STREAMLOCAL; } else if (fwdargs[1].ispath) { fwd->listen_host = NULL; fwd->listen_port = a2port(fwdargs[0].arg); fwd->connect_path = xstrdup(fwdargs[1].arg); fwd->connect_port = PORT_STREAMLOCAL; } else { fwd->listen_host = xstrdup(fwdargs[0].arg); fwd->listen_port = a2port(fwdargs[1].arg); fwd->connect_host = xstrdup("socks"); } break; case 3: if (fwdargs[0].ispath) { fwd->listen_path = xstrdup(fwdargs[0].arg); fwd->listen_port = PORT_STREAMLOCAL; fwd->connect_host = xstrdup(fwdargs[1].arg); fwd->connect_port = a2port(fwdargs[2].arg); } else if (fwdargs[2].ispath) { fwd->listen_host = xstrdup(fwdargs[0].arg); fwd->listen_port = a2port(fwdargs[1].arg); fwd->connect_path = xstrdup(fwdargs[2].arg); fwd->connect_port = PORT_STREAMLOCAL; } else { fwd->listen_host = NULL; fwd->listen_port = a2port(fwdargs[0].arg); fwd->connect_host = xstrdup(fwdargs[1].arg); fwd->connect_port = a2port(fwdargs[2].arg); } break; case 4: fwd->listen_host = xstrdup(fwdargs[0].arg); fwd->listen_port = a2port(fwdargs[1].arg); fwd->connect_host = xstrdup(fwdargs[2].arg); fwd->connect_port = a2port(fwdargs[3].arg); break; default: i = 0; /* failure */ } free(p); if (dynamicfwd) { if (!(i == 1 || i == 2)) goto fail_free; } else { if (!(i == 3 || i == 4)) { if (fwd->connect_path == NULL && fwd->listen_path == NULL) goto fail_free; } if (fwd->connect_port <= 0 && fwd->connect_path == NULL) goto fail_free; } if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || (!remotefwd && fwd->listen_port == 0)) goto fail_free; if (fwd->connect_host != NULL && strlen(fwd->connect_host) >= NI_MAXHOST) goto fail_free; /* * XXX - if connecting to a remote socket, max sun len may not * match this host */ if (fwd->connect_path != NULL && strlen(fwd->connect_path) >= PATH_MAX_SUN) goto fail_free; if (fwd->listen_host != NULL && strlen(fwd->listen_host) >= NI_MAXHOST) goto fail_free; if (fwd->listen_path != NULL && strlen(fwd->listen_path) >= PATH_MAX_SUN) goto fail_free; return (i); fail_free: free(fwd->connect_host); fwd->connect_host = NULL; free(fwd->connect_path); fwd->connect_path = NULL; free(fwd->listen_host); fwd->listen_host = NULL; free(fwd->listen_path); fwd->listen_path = NULL; return (0); } int parse_jump(const char *s, Options *o, int active) { char *orig, *sdup, *cp; char *host = NULL, *user = NULL; int r, ret = -1, port = -1, first; active &= o->proxy_command == NULL && o->jump_host == NULL; orig = sdup = xstrdup(s); /* Remove comment and trailing whitespace */ if ((cp = strchr(orig, '#')) != NULL) *cp = '\0'; rtrim(orig); first = active; do { if (strcasecmp(s, "none") == 0) break; if ((cp = strrchr(sdup, ',')) == NULL) cp = sdup; /* last */ else *cp++ = '\0'; if (first) { /* First argument and configuration is active */ r = parse_ssh_uri(cp, &user, &host, &port); if (r == -1 || (r == 1 && parse_user_host_port(cp, &user, &host, &port) != 0)) goto out; } else { /* Subsequent argument or inactive configuration */ r = parse_ssh_uri(cp, NULL, NULL, NULL); if (r == -1 || (r == 1 && parse_user_host_port(cp, NULL, NULL, NULL) != 0)) goto out; } first = 0; /* only check syntax for subsequent hosts */ } while (cp != sdup); /* success */ if (active) { if (strcasecmp(s, "none") == 0) { o->jump_host = xstrdup("none"); o->jump_port = 0; } else { o->jump_user = user; o->jump_host = host; o->jump_port = port; o->proxy_command = xstrdup("none"); user = host = NULL; if ((cp = strrchr(s, ',')) != NULL && cp != s) { o->jump_extra = xstrdup(s); o->jump_extra[cp - s] = '\0'; } } } ret = 0; out: free(orig); free(user); free(host); return ret; } int parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) { char *user = NULL, *host = NULL, *path = NULL; int r, port; r = parse_uri("ssh", uri, &user, &host, &port, &path); if (r == 0 && path != NULL) r = -1; /* path not allowed */ if (r == 0) { if (userp != NULL) { *userp = user; user = NULL; } if (hostp != NULL) { *hostp = host; host = NULL; } if (portp != NULL) *portp = port; } free(user); free(host); free(path); return r; } /* XXX the following is a near-verbatim copy from servconf.c; refactor */ static const char * fmt_multistate_int(int val, const struct multistate *m) { u_int i; for (i = 0; m[i].key != NULL; i++) { if (m[i].value == val) return m[i].key; } return "UNKNOWN"; } static const char * fmt_intarg(OpCodes code, int val) { if (val == -1) return "unset"; switch (code) { case oAddressFamily: return fmt_multistate_int(val, multistate_addressfamily); case oCompression: return fmt_multistate_int(val, multistate_compression); case oVerifyHostKeyDNS: case oUpdateHostkeys: return fmt_multistate_int(val, multistate_yesnoask); case oStrictHostKeyChecking: return fmt_multistate_int(val, multistate_strict_hostkey); case oControlMaster: return fmt_multistate_int(val, multistate_controlmaster); case oTunnel: return fmt_multistate_int(val, multistate_tunnel); case oRequestTTY: return fmt_multistate_int(val, multistate_requesttty); case oSessionType: return fmt_multistate_int(val, multistate_sessiontype); case oCanonicalizeHostname: return fmt_multistate_int(val, multistate_canonicalizehostname); case oAddKeysToAgent: return fmt_multistate_int(val, multistate_yesnoaskconfirm); case oPubkeyAuthentication: return fmt_multistate_int(val, multistate_pubkey_auth); case oFingerprintHash: return ssh_digest_alg_name(val); default: switch (val) { case 0: return "no"; case 1: return "yes"; default: return "UNKNOWN"; } } } static const char * lookup_opcode_name(OpCodes code) { u_int i; for (i = 0; keywords[i].name != NULL; i++) if (keywords[i].opcode == code) return(keywords[i].name); return "UNKNOWN"; } static void dump_cfg_int(OpCodes code, int val) { if (code == oObscureKeystrokeTiming) { if (val == 0) { printf("%s no\n", lookup_opcode_name(code)); return; } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) { printf("%s yes\n", lookup_opcode_name(code)); return; } /* FALLTHROUGH */ } printf("%s %d\n", lookup_opcode_name(code), val); } static void dump_cfg_fmtint(OpCodes code, int val) { printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); } static void dump_cfg_string(OpCodes code, const char *val) { if (val == NULL) return; printf("%s %s\n", lookup_opcode_name(code), val); } static void dump_cfg_strarray(OpCodes code, u_int count, char **vals) { u_int i; for (i = 0; i < count; i++) printf("%s %s\n", lookup_opcode_name(code), vals[i]); } static void dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) { u_int i; printf("%s", lookup_opcode_name(code)); if (count == 0) printf(" none"); for (i = 0; i < count; i++) printf(" %s", vals[i]); printf("\n"); } static void dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) { const struct Forward *fwd; u_int i; /* oDynamicForward */ for (i = 0; i < count; i++) { fwd = &fwds[i]; if (code == oDynamicForward && fwd->connect_host != NULL && strcmp(fwd->connect_host, "socks") != 0) continue; if (code == oLocalForward && fwd->connect_host != NULL && strcmp(fwd->connect_host, "socks") == 0) continue; printf("%s", lookup_opcode_name(code)); if (fwd->listen_port == PORT_STREAMLOCAL) printf(" %s", fwd->listen_path); else if (fwd->listen_host == NULL) printf(" %d", fwd->listen_port); else { printf(" [%s]:%d", fwd->listen_host, fwd->listen_port); } if (code != oDynamicForward) { if (fwd->connect_port == PORT_STREAMLOCAL) printf(" %s", fwd->connect_path); else if (fwd->connect_host == NULL) printf(" %d", fwd->connect_port); else { printf(" [%s]:%d", fwd->connect_host, fwd->connect_port); } } printf("\n"); } } void dump_client_config(Options *o, const char *host) { int i, r; char buf[8], *all_key; /* * Expand HostKeyAlgorithms name lists. This isn't handled in * fill_default_options() like the other algorithm lists because * the host key algorithms are by default dynamically chosen based * on the host's keys found in known_hosts. */ all_key = sshkey_alg_list(0, 0, 1, ','); if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), all_key)) != 0) fatal_fr(r, "expand HostKeyAlgorithms"); free(all_key); /* Most interesting options first: user, host, port */ dump_cfg_string(oHost, o->host_arg); dump_cfg_string(oUser, o->user); dump_cfg_string(oHostname, host); dump_cfg_int(oPort, o->port); /* Flag options */ dump_cfg_fmtint(oAddressFamily, o->address_family); dump_cfg_fmtint(oBatchMode, o->batch_mode); dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); dump_cfg_fmtint(oCompression, o->compression); dump_cfg_fmtint(oControlMaster, o->control_master); dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(oForwardX11, o->forward_x11); dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); #ifdef GSSAPI dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); dump_cfg_fmtint(oRequestTTY, o->request_tty); dump_cfg_fmtint(oSessionType, o->session_type); dump_cfg_fmtint(oStdinNull, o->stdin_null); dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); dump_cfg_fmtint(oTunnel, o->tun_open); dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); /* Integer options */ dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); dump_cfg_int(oConnectionAttempts, o->connection_attempts); dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); dump_cfg_int(oServerAliveInterval, o->server_alive_interval); dump_cfg_int(oRequiredRSASize, o->required_rsa_size); dump_cfg_int(oObscureKeystrokeTiming, o->obscure_keystroke_timing_interval); /* String options */ dump_cfg_string(oBindAddress, o->bind_address); dump_cfg_string(oBindInterface, o->bind_interface); dump_cfg_string(oCiphers, o->ciphers); dump_cfg_string(oControlPath, o->control_path); dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); dump_cfg_string(oHostKeyAlias, o->host_key_alias); dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); dump_cfg_string(oIdentityAgent, o->identity_agent); dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); dump_cfg_string(oKexAlgorithms, o->kex_algorithms); dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); dump_cfg_string(oLocalCommand, o->local_command); dump_cfg_string(oRemoteCommand, o->remote_command); dump_cfg_string(oLogLevel, log_level_name(o->log_level)); dump_cfg_string(oMacs, o->macs); #ifdef ENABLE_PKCS11 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); #endif dump_cfg_string(oSecurityKeyProvider, o->sk_provider); dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); dump_cfg_string(oXAuthLocation, o->xauth_location); dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); dump_cfg_string(oTag, o->tag); dump_cfg_string(oVersionAddendum, o->version_addendum); /* Forwards */ dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); /* String array options */ dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); dump_cfg_strarray_oneline(oLogVerbose, o->num_log_verbose, o->log_verbose); dump_cfg_strarray_oneline(oChannelTimeout, o->num_channel_timeouts, o->channel_timeouts); /* Special cases */ /* PermitRemoteOpen */ if (o->num_permitted_remote_opens == 0) printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); else dump_cfg_strarray_oneline(oPermitRemoteOpen, o->num_permitted_remote_opens, o->permitted_remote_opens); /* AddKeysToAgent */ if (o->add_keys_to_agent_lifespan <= 0) dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); else { printf("addkeystoagent%s %d\n", o->add_keys_to_agent == 3 ? " confirm" : "", o->add_keys_to_agent_lifespan); } /* oForwardAgent */ if (o->forward_agent_sock_path == NULL) dump_cfg_fmtint(oForwardAgent, o->forward_agent); else dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); /* oConnectTimeout */ if (o->connection_timeout == -1) printf("connecttimeout none\n"); else dump_cfg_int(oConnectTimeout, o->connection_timeout); /* oTunnelDevice */ printf("tunneldevice"); if (o->tun_local == SSH_TUNID_ANY) printf(" any"); else printf(" %d", o->tun_local); if (o->tun_remote == SSH_TUNID_ANY) printf(":any"); else printf(":%d", o->tun_remote); printf("\n"); /* oCanonicalizePermittedCNAMEs */ printf("canonicalizePermittedcnames"); if (o->num_permitted_cnames == 0) printf(" none"); for (i = 0; i < o->num_permitted_cnames; i++) { printf(" %s:%s", o->permitted_cnames[i].source_list, o->permitted_cnames[i].target_list); } printf("\n"); /* oControlPersist */ if (o->control_persist == 0 || o->control_persist_timeout == 0) dump_cfg_fmtint(oControlPersist, o->control_persist); else dump_cfg_int(oControlPersist, o->control_persist_timeout); /* oEscapeChar */ if (o->escape_char == SSH_ESCAPECHAR_NONE) printf("escapechar none\n"); else { vis(buf, o->escape_char, VIS_WHITE, 0); printf("escapechar %s\n", buf); } /* oIPQoS */ printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); printf("%s\n", iptos2str(o->ip_qos_bulk)); /* oRekeyLimit */ printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, o->rekey_interval); /* oStreamLocalBindMask */ printf("streamlocalbindmask 0%o\n", o->fwd_opts.streamlocal_bind_mask); /* oLogFacility */ printf("syslogfacility %s\n", log_facility_name(o->log_facility)); /* oProxyCommand / oProxyJump */ if (o->jump_host == NULL) dump_cfg_string(oProxyCommand, o->proxy_command); else { /* Check for numeric addresses */ i = strchr(o->jump_host, ':') != NULL || strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); snprintf(buf, sizeof(buf), "%d", o->jump_port); printf("proxyjump %s%s%s%s%s%s%s%s%s\n", /* optional additional jump spec */ o->jump_extra == NULL ? "" : o->jump_extra, o->jump_extra == NULL ? "" : ",", /* optional user */ o->jump_user == NULL ? "" : o->jump_user, o->jump_user == NULL ? "" : "@", /* opening [ if hostname is numeric */ i ? "[" : "", /* mandatory hostname */ o->jump_host, /* closing ] if hostname is numeric */ i ? "]" : "", /* optional port number */ o->jump_port <= 0 ? "" : ":", o->jump_port <= 0 ? "" : buf); } } openssh-10.0p1/PaxHeaders.10889/readconf.h100644 001750 001750 0000000003614775415623 0015106xustar0030 atime=1744182234.687328805 openssh-10.0p1/readconf.h010064400017500001750000000221021477541562300134660ustar00djmdjm/* $OpenBSD: readconf.h,v 1.159 2025/02/15 01:48:30 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for reading the configuration file. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef READCONF_H #define READCONF_H /* Data structure for representing option data. */ #define SSH_MAX_HOSTS_FILES 32 #define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path) struct allowed_cname { char *source_list; char *target_list; }; typedef struct { char *host_arg; /* Host arg as specified on command line. */ int forward_agent; /* Forward authentication agent. */ char *forward_agent_sock_path; /* Optional path of the agent. */ int forward_x11; /* Forward X11 display. */ int forward_x11_timeout; /* Expiration for Cookies */ int forward_x11_trusted; /* Trust Forward X11 display. */ int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ char *xauth_location; /* Location for xauth program */ struct ForwardOptions fwd_opts; /* forwarding options */ int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ int gss_authentication; /* Try GSS authentication */ int gss_deleg_creds; /* Delegate GSS credentials */ int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ int batch_mode; /* Batch mode: do not ask for passwords. */ int check_host_ip; /* Also keep track of keys for IP address */ int strict_host_key_checking; /* Strict host key checking. */ int compression; /* Compress packets in both directions. */ int tcp_keep_alive; /* Set SO_KEEPALIVE. */ int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for logging. */ u_int num_log_verbose; /* Verbose log overrides */ char **log_verbose; int port; /* Port to connect. */ int address_family; int connection_attempts; /* Max attempts (seconds) before * giving up */ int connection_timeout; /* Max time (seconds) before * aborting connection attempt */ int number_of_password_prompts; /* Max number of password * prompts. */ char *ciphers; /* SSH2 ciphers in order of preference. */ char *macs; /* SSH2 macs in order of preference. */ char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */ char *kex_algorithms; /* SSH2 kex methods in order of preference. */ char *ca_sign_algorithms; /* Allowed CA signature algorithms */ char *hostname; /* Real host to connect. */ char *tag; /* Configuration tag name. */ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ char *proxy_command; /* Proxy command for connecting the host. */ char *user; /* User to log in as. */ int escape_char; /* Escape character; -2 = none */ u_int num_system_hostfiles; /* Paths for /etc/ssh/ssh_known_hosts */ char *system_hostfiles[SSH_MAX_HOSTS_FILES]; u_int num_user_hostfiles; /* Path for $HOME/.ssh/known_hosts */ char *user_hostfiles[SSH_MAX_HOSTS_FILES]; char *preferred_authentications; char *bind_address; /* local socket address for connection to sshd */ char *bind_interface; /* local interface for bind address */ char *pkcs11_provider; /* PKCS#11 provider */ char *sk_provider; /* Security key provider */ int verify_host_key_dns; /* Verify host key using DNS */ int num_identity_files; /* Number of files for identities. */ char *identity_files[SSH_MAX_IDENTITY_FILES]; int identity_file_userprovided[SSH_MAX_IDENTITY_FILES]; struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; int num_certificate_files; /* Number of extra certificates for ssh. */ char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int add_keys_to_agent; int add_keys_to_agent_lifespan; char *identity_agent; /* Optional path to ssh-agent socket */ /* Local TCP/IP forward requests. */ int num_local_forwards; struct Forward *local_forwards; /* Remote TCP/IP forward requests. */ int num_remote_forwards; struct Forward *remote_forwards; int clear_forwardings; /* Restrict remote dynamic forwarding */ char **permitted_remote_opens; u_int num_permitted_remote_opens; /* stdio forwarding (-W) host and port */ char *stdio_forward_host; int stdio_forward_port; int enable_ssh_keysign; int64_t rekey_limit; int rekey_interval; int no_host_authentication_for_localhost; int identities_only; int server_alive_interval; int server_alive_count_max; u_int num_send_env; char **send_env; u_int num_setenv; char **setenv; char *control_path; int control_master; int control_persist; /* ControlPersist flag */ int control_persist_timeout; /* ControlPersist timeout (seconds) */ int hash_known_hosts; int tun_open; /* tun(4) */ int tun_local; /* force tun device (optional) */ int tun_remote; /* force tun device (optional) */ char *local_command; int permit_local_command; char *remote_command; int visual_host_key; int request_tty; int session_type; int stdin_null; int fork_after_authentication; int proxy_use_fdpass; int num_canonical_domains; char **canonical_domains; int canonicalize_hostname; int canonicalize_max_dots; int canonicalize_fallback_local; int num_permitted_cnames; struct allowed_cname *permitted_cnames; char *revoked_host_keys; int fingerprint_hash; int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */ char *hostbased_accepted_algos; char *pubkey_accepted_algos; char *jump_user; char *jump_host; int jump_port; char *jump_extra; char *known_hosts_command; int required_rsa_size; /* minimum size of RSA keys */ int enable_escape_commandline; /* ~C commandline */ int obscure_keystroke_timing_interval; char **channel_timeouts; /* inactivity timeout by channel type */ u_int num_channel_timeouts; char *version_addendum; char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ } Options; #define SSH_PUBKEY_AUTH_NO 0x00 #define SSH_PUBKEY_AUTH_UNBOUND 0x01 #define SSH_PUBKEY_AUTH_HBOUND 0x02 #define SSH_PUBKEY_AUTH_ALL 0x03 #define SSH_CANONICALISE_NO 0 #define SSH_CANONICALISE_YES 1 #define SSH_CANONICALISE_ALWAYS 2 #define SSHCTL_MASTER_NO 0 #define SSHCTL_MASTER_YES 1 #define SSHCTL_MASTER_AUTO 2 #define SSHCTL_MASTER_ASK 3 #define SSHCTL_MASTER_AUTO_ASK 4 #define REQUEST_TTY_AUTO 0 #define REQUEST_TTY_NO 1 #define REQUEST_TTY_YES 2 #define REQUEST_TTY_FORCE 3 #define SESSION_TYPE_NONE 0 #define SESSION_TYPE_SUBSYSTEM 1 #define SESSION_TYPE_DEFAULT 2 #define SSHCONF_CHECKPERM 1 /* check permissions on config file */ #define SSHCONF_USERCONF 2 /* user provided config file not system */ #define SSHCONF_FINAL 4 /* Final pass over config, after canon. */ #define SSHCONF_NEVERMATCH 8 /* Match/Host never matches; internal only */ #define SSH_UPDATE_HOSTKEYS_NO 0 #define SSH_UPDATE_HOSTKEYS_YES 1 #define SSH_UPDATE_HOSTKEYS_ASK 2 #define SSH_STRICT_HOSTKEY_OFF 0 #define SSH_STRICT_HOSTKEY_NEW 1 #define SSH_STRICT_HOSTKEY_YES 2 #define SSH_STRICT_HOSTKEY_ASK 3 /* ObscureKeystrokes parameters */ #define SSH_KEYSTROKE_DEFAULT_INTERVAL_MS 20 #define SSH_KEYSTROKE_CHAFF_MIN_MS 1024 #define SSH_KEYSTROKE_CHAFF_RNG_MS 2048 const char *kex_default_pk_alg(void); char *ssh_connection_hash(const char *thishost, const char *host, const char *portstr, const char *user, const char *jump_host); void initialize_options(Options *); int fill_default_options(Options *); void fill_default_options_for_canonicalization(Options *); void free_options(Options *o); int process_config_line(Options *, struct passwd *, const char *, const char *, const char *, char *, const char *, int, int *, int); int read_config_file(const char *, struct passwd *, const char *, const char *, const char *, Options *, int, int *); int parse_forward(struct Forward *, const char *, int, int); int parse_jump(const char *, Options *, int); int parse_ssh_uri(const char *, char **, char **, int *); int default_ssh_port(void); int option_clear_or_none(const char *); int config_has_permitted_cnames(Options *); void dump_client_config(Options *o, const char *host); void add_local_forward(Options *, const struct Forward *); void add_remote_forward(Options *, const struct Forward *); void add_identity_file(Options *, const char *, const char *, int); void add_certificate_file(Options *, const char *, int); #endif /* READCONF_H */ openssh-10.0p1/PaxHeaders.10889/readpass.c100644 001750 001750 0000000003614775415623 0015122xustar0030 atime=1744182234.687328805 openssh-10.0p1/readpass.c010064400017500001750000000206171477541562300135130ustar00djmdjm/* $OpenBSD: readpass.c,v 1.71 2024/03/30 04:27:44 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 #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #include "xmalloc.h" #include "misc.h" #include "pathnames.h" #include "log.h" #include "ssh.h" #include "uidswap.h" static char * ssh_askpass(char *askpass, const char *msg, const char *env_hint) { pid_t pid, ret; size_t len; char *pass; int p[2], status; char buf[1024]; void (*osigchld)(int); if (fflush(stdout) != 0) error_f("fflush: %s", strerror(errno)); if (askpass == NULL) fatal("internal error: askpass undefined"); if (pipe(p) == -1) { error_f("pipe: %s", strerror(errno)); return NULL; } osigchld = ssh_signal(SIGCHLD, SIG_DFL); if ((pid = fork()) == -1) { error_f("fork: %s", strerror(errno)); ssh_signal(SIGCHLD, osigchld); return NULL; } if (pid == 0) { close(p[0]); if (dup2(p[1], STDOUT_FILENO) == -1) fatal_f("dup2: %s", strerror(errno)); if (env_hint != NULL) setenv("SSH_ASKPASS_PROMPT", env_hint, 1); execlp(askpass, askpass, msg, (char *)NULL); fatal_f("exec(%s): %s", askpass, strerror(errno)); } close(p[1]); len = 0; do { ssize_t r = read(p[0], buf + len, sizeof(buf) - 1 - len); if (r == -1 && errno == EINTR) continue; if (r <= 0) break; len += r; } while (sizeof(buf) - 1 - len > 0); buf[len] = '\0'; close(p[0]); while ((ret = waitpid(pid, &status, 0)) == -1) if (errno != EINTR) break; ssh_signal(SIGCHLD, osigchld); if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { explicit_bzero(buf, sizeof(buf)); return NULL; } buf[strcspn(buf, "\r\n")] = '\0'; pass = xstrdup(buf); explicit_bzero(buf, sizeof(buf)); 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 * RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no * tty is or askpass program is available */ char * read_passphrase(const char *prompt, int flags) { char cr = '\r', *askpass = NULL, *ret, buf[1024]; int rppflags, ttyfd, use_askpass = 0, allow_askpass = 0; const char *askpass_hint = NULL; const char *s; if (((s = getenv("DISPLAY")) != NULL && *s != '\0') || ((s = getenv("WAYLAND_DISPLAY")) != NULL && *s != '\0')) allow_askpass = 1; if ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) != NULL) { if (strcasecmp(s, "force") == 0) { use_askpass = 1; allow_askpass = 1; } else if (strcasecmp(s, "prefer") == 0) use_askpass = allow_askpass; else if (strcasecmp(s, "never") == 0) allow_askpass = 0; } rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF; if (use_askpass) debug_f("requested to askpass"); else if (flags & RP_USE_ASKPASS) use_askpass = 1; else if (flags & RP_ALLOW_STDIN) { if (!isatty(STDIN_FILENO)) { debug_f("stdin is not a tty"); use_askpass = 1; } } else { rppflags |= RPP_REQUIRE_TTY; ttyfd = open(_PATH_TTY, O_RDWR); 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 { debug_f("can't open %s: %s", _PATH_TTY, strerror(errno)); use_askpass = 1; } } if ((flags & RP_USE_ASKPASS) && !allow_askpass) return (flags & RP_ALLOW_EOF) ? NULL : xstrdup(""); if (use_askpass && allow_askpass) { if (getenv(SSH_ASKPASS_ENV)) askpass = getenv(SSH_ASKPASS_ENV); else askpass = _PATH_SSH_ASKPASS_DEFAULT; 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; } if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) { if (flags & RP_ALLOW_EOF) return NULL; return xstrdup(""); } ret = xstrdup(buf); explicit_bzero(buf, sizeof(buf)); return ret; } int ask_permission(const char *fmt, ...) { va_list args; char *p, prompt[1024]; int allowed = 0; va_start(args, fmt); vsnprintf(prompt, sizeof(prompt), fmt, args); va_end(args); p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF|RP_ASK_PERMISSION); if (p != NULL) { /* * Accept empty responses and responses consisting * of the word "yes" as affirmative. */ if (*p == '\0' || *p == '\n' || strcasecmp(p, "yes") == 0) allowed = 1; free(p); } return (allowed); } static void writemsg(const char *msg) { (void)write(STDERR_FILENO, "\r", 1); (void)write(STDERR_FILENO, msg, strlen(msg)); (void)write(STDERR_FILENO, "\r\n", 2); } struct notifier_ctx { pid_t pid; void (*osigchld)(int); }; struct notifier_ctx * notify_start(int force_askpass, const char *fmt, ...) { va_list args; char *prompt = NULL; pid_t pid = -1; void (*osigchld)(int) = NULL; const char *askpass, *s; struct notifier_ctx *ret = NULL; va_start(args, fmt); xvasprintf(&prompt, fmt, args); va_end(args); if (fflush(NULL) != 0) error_f("fflush: %s", strerror(errno)); if (!force_askpass && isatty(STDERR_FILENO)) { writemsg(prompt); goto out_ctx; } if ((askpass = getenv("SSH_ASKPASS")) == NULL) askpass = _PATH_SSH_ASKPASS_DEFAULT; if (*askpass == '\0') { debug3_f("cannot notify: no askpass"); goto out; } if (getenv("DISPLAY") == NULL && getenv("WAYLAND_DISPLAY") == NULL && ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) == NULL || strcmp(s, "force") != 0)) { debug3_f("cannot notify: no display"); goto out; } osigchld = ssh_signal(SIGCHLD, SIG_DFL); if ((pid = fork()) == -1) { error_f("fork: %s", strerror(errno)); ssh_signal(SIGCHLD, osigchld); free(prompt); return NULL; } if (pid == 0) { if (stdfd_devnull(1, 1, 0) == -1) fatal_f("stdfd_devnull failed"); closefrom(STDERR_FILENO + 1); setenv("SSH_ASKPASS_PROMPT", "none", 1); /* hint to UI */ execlp(askpass, askpass, prompt, (char *)NULL); error_f("exec(%s): %s", askpass, strerror(errno)); _exit(1); /* NOTREACHED */ } out_ctx: if ((ret = calloc(1, sizeof(*ret))) == NULL) { if (pid != -1) kill(pid, SIGTERM); fatal_f("calloc failed"); } ret->pid = pid; ret->osigchld = osigchld; out: free(prompt); return ret; } void notify_complete(struct notifier_ctx *ctx, const char *fmt, ...) { int ret; char *msg = NULL; va_list args; if (ctx != NULL && fmt != NULL && ctx->pid == -1) { /* * notify_start wrote to stderr, so send conclusion message * there too */ va_start(args, fmt); xvasprintf(&msg, fmt, args); va_end(args); writemsg(msg); free(msg); } if (ctx == NULL || ctx->pid <= 0) { free(ctx); return; } kill(ctx->pid, SIGTERM); while ((ret = waitpid(ctx->pid, NULL, 0)) == -1) { if (errno != EINTR) break; } if (ret == -1) fatal_f("waitpid: %s", strerror(errno)); ssh_signal(SIGCHLD, ctx->osigchld); free(ctx); } openssh-10.0p1/PaxHeaders.10889/regress040755 001750 001750 0000000003614775415623 0014557xustar0030 atime=1744182234.687328805 openssh-10.0p1/regress004075500017500001750000000000001477541562300131355ustar00djmdjmopenssh-10.0p1/regress/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0016266xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/Makefile010064400017500001750000000222531477541562300146550ustar00djmdjm# $OpenBSD: Makefile,v 1.136 2025/03/11 07:50:20 dtucker Exp $ tests: prep file-tests t-exec unit REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 # File based tests file-tests: $(REGRESS_TARGETS) # Interop tests are not run by default interop interop-tests: t-exec-interop extra extra-tests: t-extra prep: test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out clean: for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done rm -rf $(OBJ).putty rm -rf $(OBJ).dropbear distclean: clean LTESTS= connect \ proxy-connect \ sshfp-connect \ connect-privsep \ connect-uri \ proto-version \ proto-mismatch \ exit-status \ exit-status-signal \ envpass \ transfer \ banner \ rekey \ dhgex \ stderr-data \ stderr-after-eof \ broken-pipe \ try-ciphers \ yes-head \ login-timeout \ agent \ agent-getpeereid \ agent-timeout \ agent-ptrace \ agent-subprocess \ keyscan \ keygen-change \ keygen-comment \ keygen-convert \ keygen-knownhosts \ keygen-moduli \ keygen-sshfp \ key-options \ scp \ scp3 \ scp-uri \ sftp \ sftp-chroot \ sftp-cmds \ sftp-badcmds \ sftp-batch \ sftp-glob \ sftp-perm \ sftp-resume \ sftp-uri \ reconfigure \ dynamic-forward \ forwarding \ multiplex \ reexec \ brokenkeys \ sshcfgparse \ cfgparse \ cfgmatch \ cfgmatchlisten \ percent \ addrmatch \ localcommand \ forcecommand \ portnum \ keytype \ kextype \ cert-hostkey \ cert-userkey \ host-expand \ keys-command \ forward-control \ integrity \ krl \ multipubkey \ limit-keytype \ hostkey-agent \ hostkey-rotate \ principals-command \ cert-file \ cfginclude \ servcfginclude \ allow-deny-users \ authinfo \ sshsig \ knownhosts \ knownhosts-command \ agent-restrict \ hostbased \ channel-timeout \ connection-timeout \ match-subsystem \ agent-pkcs11-restrict \ agent-pkcs11-cert \ penalty \ penalty-expire INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers INTEROP_TESTS+= dropbear-ciphers dropbear-kex #INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp EXTRA_TESTS= agent-pkcs11 #EXTRA_TESTS+= cipher-speed USERNAME= ${LOGNAME} CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ authorized_keys_${USERNAME}.* \ authorized_principals_${USERNAME} \ banner.in banner.out cert_host_key* cert_user_key* \ copy.1 copy.2 data ed25519-agent ed25519-agent* \ ed25519-agent.pub ed25519 ed25519.pub empty.in \ expect failed-regress.log failed-ssh.log failed-sshd.log \ hkr.* host.ecdsa-sha2-nistp256 host.ecdsa-sha2-nistp384 \ host.ecdsa-sha2-nistp521 host.ssh-dss host.ssh-ed25519 \ host.ssh-rsa host_ca_key* host_krl_* host_revoked_* key.* \ key.dsa-* key.ecdsa-* key.ed25519-512 \ key.ed25519-512.pub key.rsa-* keys-command-args kh.* askpass \ known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ modpipe netcat no_identity_config \ pidfile putty.rsa2 ready regress.log remote_pid \ revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa_ssh2_cr.prv \ rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ ssh-agent.log ssh-add.log slow-sftp-server.sh \ ssh-rsa_oldfmt knownhosts_command \ ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \ ssh_proxy_* sshd.log sshd_config sshd_config.* \ sshd_config.* sshd_proxy sshd_proxy.* sshd_proxy_bak \ sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \ t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \ t8.out t8.out.pub t9.out t9.out.pub \ timestamp testdata user_*key* user_ca* user_key* # Enable all malloc(3) randomisations and checks TEST_ENV= "MALLOC_OPTIONS=CFGJRSUX" TEST_SSH_SSHKEYGEN?=ssh-keygen CPPFLAGS=-I.. t1: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ ${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 ; \ fi t2: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ 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 ; \ fi t3: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ ${TEST_SSH_SSHKEYGEN} -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/t3.out ; \ ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub ; \ fi t4: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t4.ok ; \ fi t5: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ ${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t5.ok ; \ fi t6: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.prv > $(OBJ)/t6.out1 ; \ ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.pub > $(OBJ)/t6.out2 ; \ chmod 600 $(OBJ)/t6.out1 ; \ ${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t6.out1 | diff - $(OBJ)/t6.out2 ; \ fi $(OBJ)/t7.out: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@ ; \ fi t7: $(OBJ)/t7.out set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null ; \ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null ; \ fi $(OBJ)/t8.out: set -xe ; if ssh -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -q -t dsa -N '' -f $@ ; \ fi t8: $(OBJ)/t8.out set -xe ; if ssh -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t8.out > /dev/null ; \ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null ; \ fi $(OBJ)/t9.out: ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ ${TEST_SSH_SSHKEYGEN} -q -t ecdsa -N '' -f $@ t9: $(OBJ)/t9.out ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t9.out > /dev/null ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null $(OBJ)/t10.out: ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -f $@ t10: $(OBJ)/t10.out ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null t11: set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t11.ok ; \ fi $(OBJ)/t12.out: ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $@ t12: $(OBJ)/t12.out ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t12.out.pub | grep test-comment-1234 >/dev/null t-exec: ${LTESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ _started=""; test -z "${LTESTS_FROM}" && _started=1 ;\ for TEST in ""$?; do \ if [ -z "$$_started" ] ; then \ if [ "x$$TEST" = "x${LTESTS_FROM}.sh" ]; then \ _started=1; \ else \ continue; \ fi ; \ fi ; \ skip=no; \ for t in ""$${SKIP_LTESTS}; do \ if [ "x$${t}.sh" = "x$${TEST}" ]; then skip=yes; fi; \ done; \ if [ "x$${skip}" = "xno" ]; then \ echo "run test $${TEST}" ... 1>&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ else \ echo skip test $${TEST} 1>&2; \ fi; \ done t-exec-interop: ${INTEROP_TESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ for TEST in ""$?; do \ echo "run test $${TEST}" ... 1>&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ done t-extra: ${EXTRA_TESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ for TEST in ""$?; do \ echo "run test $${TEST}" ... 1>&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ done # Not run by default interop: ${INTEROP_TARGETS} # Unit tests, built by top-level Makefile unit: set -e ; if test -z "${SKIP_UNIT}" ; then \ V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -d ${.CURDIR}/unittests/sshkey/testdata ; \ $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ -d ${.CURDIR}/unittests/sshsig/testdata ; \ $$V ${.OBJDIR}/unittests/authopt/test_authopt \ -d ${.CURDIR}/unittests/authopt/testdata ; \ $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \ $$V ${.OBJDIR}/unittests/conversion/test_conversion ; \ $$V ${.OBJDIR}/unittests/kex/test_kex ; \ $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \ -d ${.CURDIR}/unittests/hostkeys/testdata ; \ $$V ${.OBJDIR}/unittests/match/test_match ; \ $$V ${.OBJDIR}/unittests/misc/test_misc ; \ if test "x${TEST_SSH_UTF8}" = "xyes" ; then \ $$V ${.OBJDIR}/unittests/utf8/test_utf8 ; \ fi \ fi openssh-10.0p1/regress/PaxHeaders.10889/README.regress100644 001750 001750 0000000003614775415623 0017157xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/README.regress010064400017500001750000000133271477541562300155500ustar00djmdjmOverview. $ ./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. openssh-10.0p1/regress/PaxHeaders.10889/addrmatch.sh100644 001750 001750 0000000003614775415623 0017111xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/addrmatch.sh010064400017500001750000000046511477541562300155020ustar00djmdjm# $OpenBSD: addrmatch.sh,v 1.6 2020/08/28 03:17:13 dtucker 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 < $OBJ/sshd_proxy ${SUDO} ${SSHD} -f $OBJ/sshd_proxy -t >/dev/null 2>&1 && \ fail "accepted invalid match $a $i" done done cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy rm $OBJ/sshd_proxy_bak openssh-10.0p1/regress/PaxHeaders.10889/agent-getpeereid.sh100644 001750 001750 0000000003614775415623 0020373xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/agent-getpeereid.sh010064400017500001750000000025751477541562300167670ustar00djmdjm# $OpenBSD: agent-getpeereid.sh,v 1.15 2023/02/08 08:06:03 dtucker Exp $ # $OpenBSD: agent-getpeereid.sh,v 1.13 2021/09/01 00:50:27 dtucker Exp $ # Placed in the Public Domain. tid="disallow agent attach from other uid" UNPRIV=nobody ASOCK=${OBJ}/agent SSH_AUTH_SOCK=/nonexistent >$OBJ/ssh-agent.log >$OBJ/ssh-add.log if config_defined HAVE_GETPEEREID HAVE_GETPEERUCRED HAVE_SO_PEERCRED ; then : else skip "skipped (not supported on this platform)" fi if test "x$USER" = "xroot"; then skip "skipped (running as root)" fi case "x$SUDO" in xsudo) sudo=1;; xdoas|xdoas\ *) ;; x) skip "need SUDO to switch to uid $UNPRIV" ;; *) skip "unsupported $SUDO - "doas" and "sudo" are allowed" ;; esac trace "start agent" eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s -a ${ASOCK}` >$OBJ/ssh-agent.log 2>&1 r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" else chmod 644 ${SSH_AUTH_SOCK} ${SSHADD} -vvv -l >>$OBJ/ssh-add.log 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} -vvv -l >>$OBJ/ssh-add.log 2>&1 fi r=$? if [ $r -lt 2 ]; then fail "ssh-add did not fail for ${UNPRIV}: $r < 2" cat $OBJ/ssh-add.log fi trace "kill agent" ${SSHAGENT} -k >>$OBJ/ssh-agent.log 2>&1 fi rm -f ${OBJ}/agent openssh-10.0p1/regress/PaxHeaders.10889/agent-pkcs11-cert.sh100644 001750 001750 0000000003614775415623 0020313xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/agent-pkcs11-cert.sh010064400017500001750000000057131477541562300167040ustar00djmdjm# $OpenBSD: agent-pkcs11-cert.sh,v 1.1 2023/12/18 14:50:08 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent certificate test" SSH_AUTH_SOCK="$OBJ/agent.sock" export SSH_AUTH_SOCK LC_ALL=C export LC_ALL p11_setup || skip "No PKCS#11 library found" rm -f $SSH_AUTH_SOCK $OBJ/agent.log rm -f $OBJ/output_* $OBJ/expect_* rm -f $OBJ/ca* trace "generate CA key and certify keys" $SSHKEYGEN -q -t ed25519 -C ca -N '' -f $OBJ/ca || fatal "ssh-keygen CA failed" $SSHKEYGEN -qs $OBJ/ca -I "ecdsa_key" -n $USER -z 1 ${SSH_SOFTHSM_DIR}/EC.pub || fatal "certify ECDSA key failed" $SSHKEYGEN -qs $OBJ/ca -I "rsa_key" -n $USER -z 2 ${SSH_SOFTHSM_DIR}/RSA.pub || fatal "certify RSA key failed" $SSHKEYGEN -qs $OBJ/ca -I "ca_ca" -n $USER -z 3 $OBJ/ca.pub || fatal "certify CA key failed" rm -f $SSH_AUTH_SOCK trace "start agent" ${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & AGENT_PID=$! trap "kill $AGENT_PID" EXIT for x in 0 1 2 3 4 ; do # Give it a chance to start ${SSHADD} -l > /dev/null 2>&1 r=$? test $r -eq 1 && break sleep 1 done if [ $r -ne 1 ]; then fatal "ssh-add -l did not fail with exit code 1 (got $r)" fi trace "load pkcs11 keys and certs" # Note: deliberately contains non-cert keys and non-matching cert on commandline p11_ssh_add -qs ${TEST_SSH_PKCS11} \ $OBJ/ca.pub \ ${SSH_SOFTHSM_DIR}/EC.pub \ ${SSH_SOFTHSM_DIR}/EC-cert.pub \ ${SSH_SOFTHSM_DIR}/RSA.pub \ ${SSH_SOFTHSM_DIR}/RSA-cert.pub || fatal "failed to add keys" # Verify their presence cut -d' ' -f1-2 \ ${SSH_SOFTHSM_DIR}/EC.pub \ ${SSH_SOFTHSM_DIR}/RSA.pub \ ${SSH_SOFTHSM_DIR}/EC-cert.pub \ ${SSH_SOFTHSM_DIR}/RSA-cert.pub | sort > $OBJ/expect_list $SSHADD -L | cut -d' ' -f1-2 | sort > $OBJ/output_list diff $OBJ/expect_list $OBJ/output_list # Verify that all can perform signatures. for x in ${SSH_SOFTHSM_DIR}/EC.pub ${SSH_SOFTHSM_DIR}/RSA.pub \ ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub ; do $SSHADD -T $x || fail "Signing failed for $x" done # Delete plain keys. $SSHADD -qd ${SSH_SOFTHSM_DIR}/EC.pub ${SSH_SOFTHSM_DIR}/RSA.pub # Verify that certs can still perform signatures. for x in ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub ; do $SSHADD -T $x || fail "Signing failed for $x" done $SSHADD -qD >/dev/null || fatal "clear agent failed" trace "load pkcs11 certs only" p11_ssh_add -qCs ${TEST_SSH_PKCS11} \ $OBJ/ca.pub \ ${SSH_SOFTHSM_DIR}/EC.pub \ ${SSH_SOFTHSM_DIR}/EC-cert.pub \ ${SSH_SOFTHSM_DIR}/RSA.pub \ ${SSH_SOFTHSM_DIR}/RSA-cert.pub || fatal "failed to add keys" # Verify their presence cut -d' ' -f1-2 \ ${SSH_SOFTHSM_DIR}/EC-cert.pub \ ${SSH_SOFTHSM_DIR}/RSA-cert.pub | sort > $OBJ/expect_list $SSHADD -L | cut -d' ' -f1-2 | sort > $OBJ/output_list diff $OBJ/expect_list $OBJ/output_list # Verify that certs can perform signatures. for x in ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub ; do $SSHADD -T $x || fail "Signing failed for $x" done openssh-10.0p1/regress/PaxHeaders.10889/agent-pkcs11-restrict.sh100644 001750 001750 0000000003614775415623 0021215xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/agent-pkcs11-restrict.sh010064400017500001750000000131351477541562300176030ustar00djmdjm# $OpenBSD: agent-pkcs11-restrict.sh,v 1.1 2023/12/18 14:49:39 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent constraint test" p11_setup || skip "No PKCS#11 library found" rm -f $SSH_AUTH_SOCK $OBJ/agent.log $OBJ/host_[abcx]* $OBJ/user_[abcx]* rm -f $OBJ/sshd_proxy_host* $OBJ/ssh_output* $OBJ/expect_* rm -f $OBJ/ssh_proxy[._]* $OBJ/command $OBJ/authorized_keys_* trace "generate host keys" for h in a b x ca ; do $SSHKEYGEN -q -t ed25519 -C host_$h -N '' -f $OBJ/host_$h || \ fatal "ssh-keygen hostkey failed" done # XXX test CA hostcerts too. key_for() { case $h in a) K="${SSH_SOFTHSM_DIR}/RSA.pub" ;; b) K="${SSH_SOFTHSM_DIR}/EC.pub" ;; *) K="" ;; esac export K } SSH_AUTH_SOCK="$OBJ/agent.sock" export SSH_AUTH_SOCK rm -f $SSH_AUTH_SOCK trace "start agent" ${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & AGENT_PID=$! trap "kill $AGENT_PID" EXIT for x in 0 1 2 3 4 ; do # Give it a chance to start ${SSHADD} -l > /dev/null 2>&1 r=$? test $r -eq 1 && break sleep 1 done if [ $r -ne 1 ]; then fatal "ssh-add -l did not fail with exit code 1 (got $r)" fi # XXX a lot of this is a copy of agent-restrict.sh, but I couldn't see a nice # way to factor it out -djm trace "prepare client config" egrep -vi '(identityfile|hostname|hostkeyalias|proxycommand)' \ $OBJ/ssh_proxy > $OBJ/ssh_proxy.bak cat << _EOF > $OBJ/ssh_proxy IdentitiesOnly yes ForwardAgent yes ExitOnForwardFailure yes _EOF cp $OBJ/ssh_proxy $OBJ/ssh_proxy_noid for h in a b ; do key_for $h cat << _EOF >> $OBJ/ssh_proxy Host host_$h Hostname host_$h HostkeyAlias host_$h IdentityFile $K ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h _EOF # Variant with no specified keys. cat << _EOF >> $OBJ/ssh_proxy_noid Host host_$h Hostname host_$h HostkeyAlias host_$h ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h _EOF done cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy_noid LC_ALL=C export LC_ALL echo "SetEnv LC_ALL=${LC_ALL}" >> sshd_proxy trace "prepare known_hosts" rm -f $OBJ/known_hosts for h in a b x ; do (printf "host_$h " ; cat $OBJ/host_${h}.pub) >> $OBJ/known_hosts done trace "prepare server configs" egrep -vi '(hostkey|pidfile)' $OBJ/sshd_proxy \ > $OBJ/sshd_proxy.bak for h in a b ; do cp $OBJ/sshd_proxy.bak $OBJ/sshd_proxy_host_$h cat << _EOF >> $OBJ/sshd_proxy_host_$h ExposeAuthInfo yes Hostkey $OBJ/host_$h _EOF cp $OBJ/sshd_proxy_host_$h $OBJ/sshd_proxy_host_${h}.bak done trace "prepare authorized_keys" cat >> $OBJ/command << EOF #!/bin/sh echo USERAUTH cat \$SSH_USER_AUTH echo AGENT if $SSHADD -ql >/dev/null 2>&1 ; then $SSHADD -L | cut -d' ' -f1-2 | sort else echo NONE fi EOF chmod a+x $OBJ/command >$OBJ/authorized_keys_$USER for h in a b ; do key_for $h (printf "%s" "restrict,agent-forwarding,command=\"$OBJ/command\" "; cat $K) >> $OBJ/authorized_keys_$USER done trace "unrestricted keys" $SSHADD -qD >/dev/null || fatal "clear agent failed" p11_ssh_add -qs ${TEST_SSH_PKCS11} || fatal "failed to add keys" for h in a b ; do key_for $h echo USERAUTH > $OBJ/expect_$h printf "publickey " >> $OBJ/expect_$h cat $K >> $OBJ/expect_$h echo AGENT >> $OBJ/expect_$h $SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_$h ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" done trace "restricted to different host" $SSHADD -qD >/dev/null || fatal "clear agent failed" p11_ssh_add -q -h host_x -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || fatal "failed to add keys" for h in a b ; do key_for $h ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ host_$h true > $OBJ/ssh_output && fatal "test ssh $h succeeded" done trace "restricted to destination host" $SSHADD -qD >/dev/null || fatal "clear agent failed" p11_ssh_add -q -h host_a -h host_b -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || fatal "failed to add keys" for h in a b ; do key_for $h echo USERAUTH > $OBJ/expect_$h printf "publickey " >> $OBJ/expect_$h cat $K >> $OBJ/expect_$h echo AGENT >> $OBJ/expect_$h echo NONE >> $OBJ/expect_$h ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" done trace "restricted multihop" $SSHADD -qD >/dev/null || fatal "clear agent failed" p11_ssh_add -q -h host_a -h "host_a>host_b" \ -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || fatal "failed to add keys" key_for a AK=$K key_for b BK=$K # Prepare authorized_keys file to additionally ssh to host_b _command="echo LOCAL ; ${OBJ}/command ; echo REMOTE; ${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$BK host_b" (printf "%s" "restrict,agent-forwarding,command=\"$_command\" "; cat $BK) > $OBJ/authorized_keys_a grep -vi AuthorizedKeysFile $OBJ/sshd_proxy_host_a.bak > $OBJ/sshd_proxy_host_a echo "AuthorizedKeysFile $OBJ/authorized_keys_a" >> $OBJ/sshd_proxy_host_a # Prepare expected output from both hosts. echo LOCAL > $OBJ/expect_a echo USERAUTH >> $OBJ/expect_a printf "publickey " >> $OBJ/expect_a cat $AK >> $OBJ/expect_a echo AGENT >> $OBJ/expect_a $SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_a echo REMOTE >> $OBJ/expect_a echo USERAUTH >> $OBJ/expect_a printf "publickey " >> $OBJ/expect_a cat $BK >> $OBJ/expect_a echo AGENT >> $OBJ/expect_a echo NONE >> $OBJ/expect_a ${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$AK \ host_a whatever > $OBJ/ssh_output || fatal "test ssh $h failed" cmp $OBJ/expect_a $OBJ/ssh_output || fatal "unexpected output" openssh-10.0p1/regress/PaxHeaders.10889/agent-pkcs11.sh100644 001750 001750 0000000003614775415623 0017360xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/agent-pkcs11.sh010064400017500001750000000023571477541562300157520ustar00djmdjm# $OpenBSD: agent-pkcs11.sh,v 1.13 2023/10/30 23:00:25 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent test" p11_setup || skip "No PKCS#11 library found" trace "start agent" eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" else trace "add pkcs11 key to agent" p11_ssh_add -s ${TEST_SSH_PKCS11} > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -s failed: exit code $r" fi trace "pkcs11 list via agent" ${SSHADD} -l > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -l failed: exit code $r" fi for k in $RSA $EC; do trace "testing $k" pub=$(cat $k.pub) ${SSHADD} -L | grep -q "$pub" || \ fail "key $k missing in ssh-add -L" ${SSHADD} -T $k.pub || fail "ssh-add -T with $k failed" # add to authorized keys cat $k.pub > $OBJ/authorized_keys_$USER trace "pkcs11 connect via agent ($k)" ${SSH} -F $OBJ/ssh_proxy somehost exit 5 r=$? if [ $r -ne 5 ]; then fail "ssh connect failed (exit code $r)" fi done trace "remove pkcs11 keys" p11_ssh_add -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -e failed: exit code $r" fi trace "kill agent" ${SSHAGENT} -k > /dev/null fi openssh-10.0p1/regress/PaxHeaders.10889/agent-ptrace.sh100644 001750 001750 0000000003614775415623 0017534xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/agent-ptrace.sh010064400017500001750000000025771477541562300161320ustar00djmdjm# $OpenBSD: agent-ptrace.sh,v 1.5 2022/04/22 05:08:43 anton 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} trap "$SUDO chown ${USER} ${SSHAGENT}; $SUDO chmod 755 ${SSHAGENT}" 0 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 'Operation not permitted.|Permission denied.|Invalid argument.|Unable to access task|Inappropriate ioctl for device.' >/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 openssh-10.0p1/regress/PaxHeaders.10889/agent-restrict.sh100644 001750 001750 0000000003614775415623 0020115xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/agent-restrict.sh010064400017500001750000000352611477541562300165070ustar00djmdjm# $OpenBSD: agent-restrict.sh,v 1.7 2025/03/28 21:45:55 dtucker Exp $ # Placed in the Public Domain. tid="agent restrictions" SSH_AUTH_SOCK="$OBJ/agent.sock" export SSH_AUTH_SOCK rm -f $SSH_AUTH_SOCK $OBJ/agent.log $OBJ/host_[abcdex]* $OBJ/user_[abcdex]* rm -f $OBJ/sshd_proxy_host* $OBJ/ssh_output* $OBJ/expect_* rm -f $OBJ/ssh_proxy[._]* $OBJ/command verbose "generate keys" for h in a b c d e x ca ; do $SSHKEYGEN -q -t ed25519 -C host_$h -N '' -f $OBJ/host_$h || \ fatal "ssh-keygen hostkey failed" $SSHKEYGEN -q -t ed25519 -C user_$h -N '' -f $OBJ/user_$h || \ fatal "ssh-keygen userkey failed" done # Make some hostcerts for h in d e ; do id="host_$h" $SSHKEYGEN -q -s $OBJ/host_ca -I $id -n $id -h $OBJ/host_${h}.pub || \ fatal "ssh-keygen certify failed" done verbose "prepare client config" egrep -vi '(identityfile|hostname|hostkeyalias|proxycommand)' \ $OBJ/ssh_proxy > $OBJ/ssh_proxy.bak cat << _EOF > $OBJ/ssh_proxy IdentitiesOnly yes ForwardAgent yes ExitOnForwardFailure yes _EOF cp $OBJ/ssh_proxy $OBJ/ssh_proxy_noid for h in a b c d e ; do cat << _EOF >> $OBJ/ssh_proxy Host host_$h Hostname host_$h HostkeyAlias host_$h IdentityFile $OBJ/user_$h ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${TEST_SSH_SSHD_ENV} ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h _EOF # Variant with no specified keys. cat << _EOF >> $OBJ/ssh_proxy_noid Host host_$h Hostname host_$h HostkeyAlias host_$h ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${TEST_SSH_SSHD_ENV} ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h _EOF done cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy_noid LC_ALL=C export LC_ALL echo "SetEnv LC_ALL=${LC_ALL}" >> sshd_proxy verbose "prepare known_hosts" rm -f $OBJ/known_hosts for h in a b c x ; do (printf "host_$h " ; cat $OBJ/host_${h}.pub) >> $OBJ/known_hosts done (printf "@cert-authority host_* " ; cat $OBJ/host_ca.pub) >> $OBJ/known_hosts verbose "prepare server configs" egrep -vi '(hostkey|pidfile)' $OBJ/sshd_proxy \ > $OBJ/sshd_proxy.bak for h in a b c d e; do cp $OBJ/sshd_proxy.bak $OBJ/sshd_proxy_host_$h cat << _EOF >> $OBJ/sshd_proxy_host_$h ExposeAuthInfo yes PidFile none Hostkey $OBJ/host_$h _EOF done for h in d e ; do echo "HostCertificate $OBJ/host_${h}-cert.pub" \ >> $OBJ/sshd_proxy_host_$h done # Create authorized_keys with canned command. reset_keys() { _whichcmd="$1" _command="" case "$_whichcmd" in authinfo) _command="cat \$SSH_USER_AUTH" ;; keylist) _command="$SSHADD -L | cut -d' ' -f-2 | sort" ;; *) fatal "unsupported command $_whichcmd" ;; esac trace "reset keys" >$OBJ/authorized_keys_$USER for h in e d c b a; do (printf "%s" "restrict,agent-forwarding,command=\"$_command\" "; cat $OBJ/user_$h.pub) >> $OBJ/authorized_keys_$USER done } # Prepare a key for comparison with ExposeAuthInfo/$SSH_USER_AUTH. expect_key() { _key="$OBJ/${1}.pub" _file="$OBJ/$2" (printf "publickey " ; cut -d' ' -f-2 $_key) > $_file } # Prepare expect_* files to compare against authinfo forced command to ensure # keys used for authentication match. reset_expect_keys() { for u in a b c d e; do expect_key user_$u expect_$u done } # ssh to host, expecting success and that output matched expectation for # that host (expect_$h file). expect_succeed() { _id="$1" _case="$2" shift; shift; _extra="$@" _host="host_$_id" trace "connect $_host expect success" rm -f $OBJ/ssh_output ${SSH} $_extra -F $OBJ/ssh_proxy $_host true > $OBJ/ssh_output _s=$? test $_s -eq 0 || fail "host $_host $_case fail, exit status $_s" diff $OBJ/ssh_output $OBJ/expect_${_id} || fail "unexpected ssh output" } # ssh to host using explicit key, expecting success and that the key was # actually used for authentication. expect_succeed_key() { _id="$1" _key="$2" _case="$3" shift; shift; shift; _extra="$@" _host="host_$_id" trace "connect $_host expect success, with key $_key" _keyfile="$OBJ/$_key" rm -f $OBJ/ssh_output ${SSH} $_extra -F $OBJ/ssh_proxy_noid \ -oIdentityFile=$_keyfile $_host true > $OBJ/ssh_output _s=$? test $_s -eq 0 || fail "host $_host $_key $_case fail, exit status $_s" expect_key $_key expect_key diff $OBJ/ssh_output $OBJ/expect_key || fail "incorrect key used for authentication" } # ssh to a host, expecting it to fail. expect_fail() { _host="$1" _case="$2" shift; shift; _extra="$@" trace "connect $_host expect failure" ${SSH} $_extra -F $OBJ/ssh_proxy $_host true >/dev/null && \ fail "host $_host $_case succeeded unexpectedly" } # ssh to a host using an explicit key, expecting it to fail. expect_fail_key() { _id="$1" _key="$2" _case="$3" shift; shift; shift; _extra="$@" _host="host_$_id" trace "connect $_host expect failure, with key $_key" _keyfile="$OBJ/$_key" ${SSH} $_extra -F $OBJ/ssh_proxy_noid -oIdentityFile=$_keyfile \ $_host true > $OBJ/ssh_output && \ fail "host $_host $_key $_case succeeded unexpectedly" } # Move the private key files out of the way to force use of agent-hosted keys. hide_privatekeys() { trace "hide private keys" for u in a b c d e x; do mv $OBJ/user_$u $OBJ/user_x$u || fatal "hide privkey $u" done } # Put the private key files back. restore_privatekeys() { trace "restore private keys" for u in a b c d e x; do mv $OBJ/user_x$u $OBJ/user_$u || fatal "restore privkey $u" done } clear_agent() { ${SSHADD} -D > /dev/null 2>&1 || fatal "clear agent failed" } reset_keys authinfo reset_expect_keys verbose "authentication w/o agent" for h in a b c d e ; do expect_succeed $h "w/o agent" wrongkey=user_e test "$h" = "e" && wrongkey=user_a expect_succeed_key $h $wrongkey "\"wrong\" key w/o agent" done hide_privatekeys for h in a b c d e ; do expect_fail $h "w/o agent" done restore_privatekeys verbose "start agent" ${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & AGENT_PID=$! trap "kill $AGENT_PID" EXIT sleep 4 # Give it a chance to start # Check that it's running. ${SSHADD} -l > /dev/null 2>&1 if [ $? -ne 1 ]; then fail "ssh-add -l did not fail with exit code 1" fi verbose "authentication with agent (no restrict)" for u in a b c d e x; do $SSHADD -q $OBJ/user_$u || fatal "add key $u unrestricted" done hide_privatekeys for h in a b c d e ; do expect_succeed $h "with agent" wrongkey=user_e test "$h" = "e" && wrongkey=user_a expect_succeed_key $h $wrongkey "\"wrong\" key with agent" done verbose "unrestricted keylist" reset_keys keylist rm -f $OBJ/expect_list.pre # List of keys from agent should contain everything. for u in a b c d e x; do cut -d " " -f-2 $OBJ/user_${u}.pub >> $OBJ/expect_list.pre done sort $OBJ/expect_list.pre > $OBJ/expect_list for h in a b c d e; do cp $OBJ/expect_list $OBJ/expect_$h expect_succeed $h "unrestricted keylist" done restore_privatekeys verbose "authentication with agent (basic restrict)" reset_keys authinfo reset_expect_keys for h in a b c d e; do $SSHADD -h host_$h -H $OBJ/known_hosts -q $OBJ/user_$h \ || fatal "add key $u basic restrict" done # One more, unrestricted $SSHADD -q $OBJ/user_x || fatal "add unrestricted key" hide_privatekeys # Authentication to host with expected key should work. for h in a b c d e ; do expect_succeed $h "with agent" done # Authentication to host with incorrect key should fail. verbose "authentication with agent incorrect key (basic restrict)" for h in a b c d e ; do wrongkey=user_e test "$h" = "e" && wrongkey=user_a expect_fail_key $h $wrongkey "wrong key with agent (basic restrict)" done verbose "keylist (basic restrict)" reset_keys keylist # List from forwarded agent should contain only user_x - the unrestricted key. cut -d " " -f-2 $OBJ/user_x.pub > $OBJ/expect_list for h in a b c d e; do cp $OBJ/expect_list $OBJ/expect_$h expect_succeed $h "keylist (basic restrict)" done restore_privatekeys verbose "username" reset_keys authinfo reset_expect_keys for h in a b c d e; do $SSHADD -h "${USER}@host_$h" -H $OBJ/known_hosts -q $OBJ/user_$h \ || fatal "add key $u basic restrict" done hide_privatekeys for h in a b c d e ; do expect_succeed $h "wildcard user" done restore_privatekeys verbose "username wildcard" reset_keys authinfo reset_expect_keys for h in a b c d e; do $SSHADD -h "*@host_$h" -H $OBJ/known_hosts -q $OBJ/user_$h \ || fatal "add key $u basic restrict" done hide_privatekeys for h in a b c d e ; do expect_succeed $h "wildcard user" done restore_privatekeys verbose "username incorrect" reset_keys authinfo reset_expect_keys for h in a b c d e; do $SSHADD -h "--BADUSER@host_$h" -H $OBJ/known_hosts -q $OBJ/user_$h \ || fatal "add key $u basic restrict" done hide_privatekeys for h in a b c d e ; do expect_fail $h "incorrect user" done restore_privatekeys verbose "agent restriction honours certificate principal" reset_keys authinfo reset_expect_keys clear_agent $SSHADD -h host_e -H $OBJ/known_hosts -q $OBJ/user_d || fatal "add key" hide_privatekeys expect_fail d "restricted agent w/ incorrect cert principal" restore_privatekeys # Prepares the script used to drive chained ssh connections for the # multihop tests. Believe me, this is easier than getting the escaping # right for 5 hops on the command-line... prepare_multihop_script() { MULTIHOP_RUN=$OBJ/command cat << _EOF > $MULTIHOP_RUN #!/bin/sh #set -x me="\$1" ; shift next="\$1" if test ! -z "\$me" ; then rm -f $OBJ/done echo "HOSTNAME host_\$me" echo "AUTHINFO" cat \$SSH_USER_AUTH fi echo AGENT $SSHADD -L | egrep "^ssh" | cut -d" " -f-2 | sort if test -z "\$next" ; then touch $OBJ/done echo "FINISH" e=0 else echo NEXT ${SSH} -F $OBJ/ssh_proxy_noid -oIdentityFile=$OBJ/user_a \ host_\$next $MULTIHOP_RUN "\$@" e=\$? fi echo "COMPLETE \"\$me\"" if test ! -z "\$me" ; then if test ! -f $OBJ/done ; then echo "DONE MARKER MISSING" test \$e -eq 0 && e=63 fi fi exit \$e _EOF chmod u+x $MULTIHOP_RUN } # Prepare expected output for multihop tests at expect_a prepare_multihop_expected() { _keys="$1" _hops="a b c d e" test -z "$2" || _hops="$2" _revhops=$(echo "$_hops" | rev) _lasthop=$(echo "$_hops" | sed 's/.* //') rm -f $OBJ/expect_keys for h in a b c d e; do cut -d" " -f-2 $OBJ/user_${h}.pub >> $OBJ/expect_keys done rm -f $OBJ/expect_a echo "AGENT" >> $OBJ/expect_a test "x$_keys" = "xnone" || sort $OBJ/expect_keys >> $OBJ/expect_a echo "NEXT" >> $OBJ/expect_a for h in $_hops ; do echo "HOSTNAME host_$h" >> $OBJ/expect_a echo "AUTHINFO" >> $OBJ/expect_a (printf "publickey " ; cut -d" " -f-2 $OBJ/user_a.pub) >> $OBJ/expect_a echo "AGENT" >> $OBJ/expect_a if test "x$_keys" = "xall" ; then sort $OBJ/expect_keys >> $OBJ/expect_a fi if test "x$h" != "x$_lasthop" ; then if test "x$_keys" = "xfiltered" ; then cut -d" " -f-2 $OBJ/user_a.pub >> $OBJ/expect_a fi echo "NEXT" >> $OBJ/expect_a fi done echo "FINISH" >> $OBJ/expect_a for h in $_revhops "" ; do echo "COMPLETE \"$h\"" >> $OBJ/expect_a done } prepare_multihop_script cp $OBJ/user_a.pub $OBJ/authorized_keys_$USER # only one key used. verbose "multihop without agent" clear_agent prepare_multihop_expected none $MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop no agent ssh failed" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" verbose "multihop agent unrestricted" clear_agent $SSHADD -q $OBJ/user_[abcde] prepare_multihop_expected all $MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop no agent ssh failed" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" verbose "multihop restricted" clear_agent prepare_multihop_expected filtered # Add user_a, with permission to connect through the whole chain. $SSHADD -h host_a -h "host_a>host_b" -h "host_b>host_c" \ -h "host_c>host_d" -h "host_d>host_e" \ -H $OBJ/known_hosts -q $OBJ/user_a \ || fatal "add key user_a multihop" # Add the other keys, bound to a unused host. $SSHADD -q -h host_x -H $OBJ/known_hosts $OBJ/user_[bcde] || fail "add keys" hide_privatekeys $MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop ssh failed" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" restore_privatekeys verbose "multihop username" $SSHADD -h host_a -h "host_a>${USER}@host_b" -h "host_b>${USER}@host_c" \ -h "host_c>${USER}@host_d" -h "host_d>${USER}@host_e" \ -H $OBJ/known_hosts -q $OBJ/user_a || fatal "add key user_a multihop" hide_privatekeys $MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop w/ user ssh failed" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" restore_privatekeys verbose "multihop wildcard username" $SSHADD -h host_a -h "host_a>*@host_b" -h "host_b>*@host_c" \ -h "host_c>*@host_d" -h "host_d>*@host_e" \ -H $OBJ/known_hosts -q $OBJ/user_a || fatal "add key user_a multihop" hide_privatekeys $MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop w/ user ssh failed" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" restore_privatekeys verbose "multihop wrong username" $SSHADD -h host_a -h "host_a>*@host_b" -h "host_b>*@host_c" \ -h "host_c>--BADUSER@host_d" -h "host_d>*@host_e" \ -H $OBJ/known_hosts -q $OBJ/user_a || fatal "add key user_a multihop" hide_privatekeys $MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output && \ fail "multihop with wrong user succeeded unexpectedly" restore_privatekeys verbose "multihop cycle no agent" clear_agent prepare_multihop_expected none "a b a a c d e" $MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output || \ fail "multihop cycle no-agent fail" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" verbose "multihop cycle agent unrestricted" clear_agent $SSHADD -q $OBJ/user_[abcde] || fail "add keys" prepare_multihop_expected all "a b a a c d e" $MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output || \ fail "multihop cycle agent ssh failed" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" verbose "multihop cycle restricted deny" clear_agent $SSHADD -q -h host_x -H $OBJ/known_hosts $OBJ/user_[bcde] || fail "add keys" $SSHADD -h host_a -h "host_a>host_b" -h "host_b>host_c" \ -h "host_c>host_d" -h "host_d>host_e" \ -H $OBJ/known_hosts -q $OBJ/user_a \ || fatal "add key user_a multihop" prepare_multihop_expected filtered "a b a a c d e" hide_privatekeys $MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output && \ fail "multihop cycle restricted deny succeded unexpectedly" restore_privatekeys verbose "multihop cycle restricted allow" clear_agent $SSHADD -q -h host_x -H $OBJ/known_hosts $OBJ/user_[bcde] || fail "add keys" $SSHADD -h host_a -h "host_a>host_b" -h "host_b>host_c" \ -h "host_c>host_d" -h "host_d>host_e" \ -h "host_b>host_a" -h "host_a>host_a" -h "host_a>host_c" \ -H $OBJ/known_hosts -q $OBJ/user_a \ || fatal "add key user_a multihop" prepare_multihop_expected filtered "a b a a c d e" hide_privatekeys $MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output || \ fail "multihop cycle restricted allow failed" diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" restore_privatekeys openssh-10.0p1/regress/PaxHeaders.10889/agent-subprocess.sh100644 001750 001750 0000000003614775415623 0020446xustar0030 atime=1744182234.688305743 openssh-10.0p1/regress/agent-subprocess.sh010064400017500001750000000010051477541562300170250ustar00djmdjm# $OpenBSD: agent-subprocess.sh,v 1.1 2020/06/19 05:07:09 dtucker Exp $ # Placed in the Public Domain. tid="agent subprocess" trace "ensure agent exits when run as subprocess" ${SSHAGENT} sh -c "echo \$SSH_AGENT_PID >$OBJ/pidfile; sleep 1" pid=`cat $OBJ/pidfile` # Currently ssh-agent polls every 10s so we need to wait at least that long. n=12 while kill -0 $pid >/dev/null 2>&1 && test "$n" -gt "0"; do n=$(($n - 1)) sleep 1 done if test "$n" -eq "0"; then fail "agent still running" fi rm -f $OBJ/pidfile openssh-10.0p1/regress/PaxHeaders.10889/agent-timeout.sh100644 001750 001750 0000000003614775415623 0017744xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/agent-timeout.sh010064400017500001750000000017321477541562300163320ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/agent.sh100644 001750 001750 0000000003614775415623 0016260xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/agent.sh010064400017500001750000000162561477541562300146550ustar00djmdjm# $OpenBSD: agent.sh,v 1.22 2024/10/24 03:28:34 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` >`ssh_logfile ssh-agent` 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 # Move private key to ensure that we aren't accidentally using it. # Keep the corresponding public keys/certs around for later use. mv -f $OBJ/$t-agent $OBJ/$t-agent-private cp -f $OBJ/$t-agent.pub $OBJ/$t-agent-private.pub cp -f $OBJ/$t-agent-cert.pub $OBJ/$t-agent-private-cert.pub done # Remove explicit identity directives from ssh_proxy 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 "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/ssh_proxy echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/sshd_proxy fi ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \ somehost exit 52 r=$? 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 ## Deletion tests. trace "delete all agent keys using -D" ${SSHADD} -D > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -D failed: exit code $r" fi # make sure they're gone ${SSHADD} -l > /dev/null 2>&1 r=$? if [ $r -ne 1 ]; then fail "ssh-add -l returned unexpected exit code: $r" fi trace "readd keys" # re-add keys/certs to agent for t in ${SSH_KEYTYPES}; do ${SSHADD} $OBJ/$t-agent-private >/dev/null 2>&1 || \ fail "ssh-add failed exit code $?" done # make sure they are there ${SSHADD} -l > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -l failed: exit code $r" fi trace "delete all agent keys using SIGUSR1" kill -s USR1 $SSH_AGENT_PID r=$? if [ $r -ne 0 ]; then fail "kill -s USR1 failed: exit code $r" fi # make sure they're gone ${SSHADD} -l > /dev/null 2>&1 r=$? if [ $r -ne 1 ]; then fail "ssh-add -l returned unexpected exit code: $r" fi # re-add keys/certs to agent for t in ${SSH_KEYTYPES}; do ${SSHADD} $OBJ/$t-agent-private >/dev/null 2>&1 || \ fail "ssh-add failed exit code $?" done # make sure they are there ${SSHADD} -l > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -l failed: exit code $r" fi check_key_absent() { ${SSHADD} -L | grep "^$1 " >/dev/null if [ $? -eq 0 ]; then fail "$1 key unexpectedly present" fi } check_key_present() { ${SSHADD} -L | grep "^$1 " >/dev/null if [ $? -ne 0 ]; then fail "$1 key missing from agent" fi } # delete the ed25519 key trace "delete single key by file" ${SSHADD} -qdk $OBJ/ssh-ed25519-agent || fail "ssh-add -d ed25519 failed" check_key_absent ssh-ed25519 check_key_present ssh-ed25519-cert-v01@openssh.com # Put key/cert back. ${SSHADD} $OBJ/ssh-ed25519-agent-private >/dev/null 2>&1 || \ fail "ssh-add failed exit code $?" check_key_present ssh-ed25519 # Delete both key and certificate. trace "delete key/cert by file" ${SSHADD} -qd $OBJ/ssh-ed25519-agent || fail "ssh-add -d ed25519 failed" check_key_absent ssh-ed25519 check_key_absent ssh-ed25519-cert-v01@openssh.com # Put key/cert back. ${SSHADD} $OBJ/ssh-ed25519-agent-private >/dev/null 2>&1 || \ fail "ssh-add failed exit code $?" check_key_present ssh-ed25519 # Delete certificate via stdin ${SSHADD} -qd - < $OBJ/ssh-ed25519-agent-cert.pub || fail "ssh-add -d - failed" check_key_present ssh-ed25519 check_key_absent ssh-ed25519-cert-v01@openssh.com # Delete key via stdin ${SSHADD} -qd - < $OBJ/ssh-ed25519-agent.pub || fail "ssh-add -d - failed" check_key_absent ssh-ed25519 check_key_absent ssh-ed25519-cert-v01@openssh.com trace "kill agent" ${SSHAGENT} -k > /dev/null SSH_AGENT_PID=$FW_SSH_AGENT_PID ${SSHAGENT} -k > /dev/null openssh-10.0p1/regress/PaxHeaders.10889/allow-deny-users.sh100644 001750 001750 0000000003614775415623 0020374xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/allow-deny-users.sh010064400017500001750000000026701477541562300167640ustar00djmdjm# Public Domain # Zev Weiss, 2016 # $OpenBSD: allow-deny-users.sh,v 1.6 2021/06/07 00:00: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 test -z "$deny" || echo DenyUsers="$deny" >> $OBJ/sshd_proxy test -z "$allow" || echo AllowUsers="$allow" >> $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy "$me@somehost" true status=$? 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" openssh-10.0p1/regress/PaxHeaders.10889/authinfo.sh100644 001750 001750 0000000003614775415623 0016777xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/authinfo.sh010064400017500001750000000010761477541562300153660ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/banner.sh100644 001750 001750 0000000003614775415623 0016427xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/banner.sh010064400017500001750000000025341477541562300150160ustar00djmdjm# $OpenBSD: banner.sh,v 1.4 2021/08/08 06:38:33 dtucker 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-log-wrapper drops "-q" to preserve debug output so use ssh directly # for just this test. ( ${REAL_SSH} -q -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ cmp $OBJ/empty.in $OBJ/banner.out ) || \ fail "suppress banner (-q)" rm -f $OBJ/banner.out $OBJ/banner.in $OBJ/empty.in openssh-10.0p1/regress/PaxHeaders.10889/broken-pipe.sh100644 001750 001750 0000000003614775415623 0017375xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/broken-pipe.sh010064400017500001750000000004311477541562300157560ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/brokenkeys.sh100644 001750 001750 0000000003614775415623 0017336xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/brokenkeys.sh010064400017500001750000000007161477541562300157250ustar00djmdjm# $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} openssh-10.0p1/regress/PaxHeaders.10889/cert-file.sh100644 001750 001750 0000000003614775415623 0017034xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cert-file.sh010064400017500001750000000124201477541562300154160ustar00djmdjm# $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* openssh-10.0p1/regress/PaxHeaders.10889/cert-hostkey.sh100644 001750 001750 0000000003614775415623 0017603xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cert-hostkey.sh010064400017500001750000000250011477541562300161640ustar00djmdjm# $OpenBSD: cert-hostkey.sh,v 1.27 2021/09/30 05:26:26 dtucker 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 "PubkeyAcceptedAlgorithms *" ) >> $OBJ/ssh_proxy cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak ( echo "HostKeyAlgorithms *" echo "PubkeyAcceptedAlgorithms *" ) >> $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 ktype in $PLAIN_TYPES ; do verbose "$tid: host ${ktype} cert connect" ( cat $OBJ/sshd_proxy_bak echo HostKey $OBJ/cert_host_key_${ktype} echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub ) > $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 # 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 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 # 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=none -F $OBJ/ssh_proxy somehost true if [ $? -ne 0 ]; then fail "ssh cert connect failed" fi # Also check that it works when the known_hosts file is not in the # first array position. ${SSH} -oUserKnownHostsFile="/dev/null $OBJ/known_hosts-cert" \ -oGlobalKnownHostsFile=none -F $OBJ/ssh_proxy somehost true if [ $? -ne 0 ]; then fail "ssh cert connect failed known_hosts 2nd" fi done # Wrong certificate 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* openssh-10.0p1/regress/PaxHeaders.10889/cert-userkey.sh100644 001750 001750 0000000003614775415623 0017604xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cert-userkey.sh010064400017500001750000000304321477541562300161710ustar00djmdjm# $OpenBSD: cert-userkey.sh,v 1.29 2024/12/06 16:25:58 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* rm -f $OBJ/authorized_principals* cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak grep -v AuthorizedKeysFile $OBJ/sshd_proxy > $OBJ/sshd_proxy_bak echo "AuthorizedKeysFile $OBJ/authorized_keys_%u_*" >> $OBJ/sshd_proxy_bak PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` 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) _prefix="${ktype}" # Setup for AuthorizedPrincipalsFile rm -f $OBJ/authorized_keys_${USER}* $OBJ/authorized_principals_${USER}* touch $OBJ/authorized_keys_${USER}_A touch $OBJ/authorized_keys_${USER}_Z touch $OBJ/authorized_principals_${USER}_A touch $OBJ/authorized_principals_${USER}_Z ( cat $OBJ/sshd_proxy_bak echo "AuthorizedPrincipalsFile " \ "$OBJ/authorized_principals_%u_*" echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/sshd_proxy ( cat $OBJ/ssh_proxy_bak echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/ssh_proxy # Missing authorized_principals verbose "$tid: ${_prefix} missing authorized_principals" rm -f $OBJ/authorized_principals_${USER}_X ${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}_X ${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}_X ${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}_X ${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}_X ${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}_X ${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}_X ${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}_X ( cat $OBJ/sshd_proxy_bak echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/sshd_proxy ( cat $OBJ/ssh_proxy_bak echo "PubkeyAcceptedAlgorithms ${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}_X ${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}_X ${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 basic_tests() { auth=$1 rm -f $OBJ/authorized_keys_${USER}* touch $OBJ/authorized_keys_${USER}_A touch $OBJ/authorized_keys_${USER}_Z 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}_X else echo > $OBJ/authorized_keys_${USER}_X extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub" fi for ktype in $PLAIN_TYPES ; do t=$(kname $ktype) _prefix="${ktype} $auth" # Simple connect verbose "$tid: ${_prefix} connect" ( cat $OBJ/sshd_proxy_bak echo "PubkeyAcceptedAlgorithms ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy ( cat $OBJ/ssh_proxy_bak echo "PubkeyAcceptedAlgorithms ${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 "RevokedKeys $OBJ/cert_user_key_revoked" echo "PubkeyAcceptedAlgorithms ${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 "PubkeyAcceptedAlgorithms ${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 verbose "$tid: $auth CA does not authenticate" ( cat $OBJ/sshd_proxy_bak echo "PubkeyAcceptedAlgorithms ${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}_X else echo > $OBJ/authorized_keys_${USER}_X echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \ >> $OBJ/sshd_proxy echo "PubkeyAcceptedAlgorithms ${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}_X echo mekmitasdigoat > $OBJ/authorized_principals_${USER}_X 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}_X 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* openssh-10.0p1/regress/PaxHeaders.10889/cfginclude.sh100644 001750 001750 0000000003614775415623 0017265xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cfginclude.sh010064400017500001750000000117021477541562300156510ustar00djmdjm# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm 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 # comment Hostname bb Include $OBJ/ssh_config.i.* Match host c Include $OBJ/ssh_config.i.* Hostname cc Match host=m !user xxxyfake Include $OBJ/ssh_config.i.* # comment Host d Hostname dd # comment 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 # comment Hostname ccc Host d # comment Hostname ddd Host e Hostname eee Host f Hostname fff # comment _EOF cat > $OBJ/ssh_config.i.2 << _EOF Match host a Hostname aaaa Match host=b !user blahblahfake 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.5 2024/09/27 01:05:54 djm 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 # comment Hostname bbb Match host c Hostname ccc # comment 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 # comment Hostname xxxx # comment _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... # Environment variable expansion cat > $OBJ/ssh_config.i << _EOF Include $OBJ/ssh_config.\${REAL_FILE} _EOF cat > $OBJ/ssh_config.i.x << _EOF Hostname xyzzy _EOF REAL_FILE=i.x export REAL_FILE trial a xyzzy # Environment variable expansion cat > $OBJ/ssh_config.i << _EOF Include $OBJ/ssh_config.i.%h%h _EOF cat > $OBJ/ssh_config.i.blahblah << _EOF Hostname mekmitastdigoat _EOF REAL_FILE=i.x export REAL_FILE trial blah mekmitastdigoat # cleanup rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out openssh-10.0p1/regress/PaxHeaders.10889/cfgmatch.sh100644 001750 001750 0000000003614775415623 0016736xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cfgmatch.sh010064400017500001750000000116711477541562300153270ustar00djmdjm# $OpenBSD: cfgmatch.sh,v 1.14 2024/09/27 01:05:54 djm 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 # comment" >>$OBJ/sshd_config echo "Match Address 127.0.0.1" >>$OBJ/sshd_config echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_config grep -v AuthorizedKeysFile $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy echo "AuthorizedKeysFile /dev/null # comment" >>$OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1" >>$OBJ/sshd_proxy echo "Match user $USER" >>$OBJ/sshd_proxy echo "AuthorizedKeysFile /dev/null $OBJ/authorized_keys_%u" >>$OBJ/sshd_proxy echo "Match Address 127.0.0.1 # comment" >>$OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_proxy ${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \ 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" for separator in " " "=" ; do 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 </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 done openssh-10.0p1/regress/PaxHeaders.10889/cfgmatchlisten.sh100644 001750 001750 0000000003614775415623 0020155xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cfgmatchlisten.sh010064400017500001750000000145401477541562300165440ustar00djmdjm# $OpenBSD: cfgmatchlisten.sh,v 1.4 2024/03/25 01:40:47 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 openssh-10.0p1/regress/PaxHeaders.10889/cfgparse.sh100644 001750 001750 0000000003614775415623 0016754xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cfgparse.sh010064400017500001750000000042531477541562300153430ustar00djmdjm# $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 <> $OBJ/sshd_config.0 < $OBJ/sshd_config.1 <> $OBJ/sshd_config.1 <$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 <> $OBJ/sshd_config.1 <$OBJ/sshd_config.2 && diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ fail "listenaddress order 2" # cleanup rm -f $OBJ/sshd_config.[012] openssh-10.0p1/regress/PaxHeaders.10889/channel-timeout.sh100644 001750 001750 0000000003614775415623 0020256xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/channel-timeout.sh010064400017500001750000000105131477541562300166410ustar00djmdjm# $OpenBSD: channel-timeout.sh,v 1.2 2024/01/09 22:19:36 djm Exp $ # Placed in the Public Domain. tid="channel timeout" # XXX not comprehensive. Still need -R -L agent X11 forwarding + interactive rm -f $OBJ/finished.* $OBJ/mux.* MUXPATH=$OBJ/mux.$$ open_mux() { ${SSH} -nNfM -oControlPath=$MUXPATH -F $OBJ/ssh_proxy "$@" somehost || fatal "open mux failed" test -e $MUXPATH || fatal "mux socket $MUXPATH not established" } close_mux() { test -e $MUXPATH || fatal "mux socket $MUXPATH missing" ${SSH} -qF $OBJ/ssh_proxy -oControlPath=$MUXPATH -O exit somehost || fatal "could not terminate mux process" for x in 1 2 3 4 5 6 7 8 9 10 ; do test -e $OBJ/mux && break sleep 1 done test -e $MUXPATH && fatal "mux did not clean up" } mux_client() { ${SSH} -F $OBJ/ssh_proxy -oControlPath=$MUXPATH somehost "$@" } rm -f $OBJ/sshd_proxy.orig cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig verbose "no timeout" ${SSH} -F $OBJ/ssh_proxy somehost "sleep 5 ; exit 23" r=$? if [ $r -ne 23 ]; then fail "ssh failed" fi verbose "command timeout" (cat $OBJ/sshd_proxy.orig ; echo "ChannelTimeout session:command=1") \ > $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy somehost "sleep 5 ; exit 23" r=$? if [ $r -ne 255 ]; then fail "ssh returned unexpected error code $r" fi verbose "command long timeout" (cat $OBJ/sshd_proxy.orig ; echo "ChannelTimeout session:command=60") \ > $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy somehost "exit 23" r=$? if [ $r -ne 23 ]; then fail "ssh returned unexpected error code $r" fi verbose "command wildcard timeout" (cat $OBJ/sshd_proxy.orig ; echo "ChannelTimeout session:*=1") \ > $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy somehost "sleep 5 ; exit 23" r=$? if [ $r -ne 255 ]; then fail "ssh returned unexpected error code $r" fi verbose "command irrelevant timeout" (cat $OBJ/sshd_proxy.orig ; echo "ChannelTimeout session:shell=1") \ > $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy somehost "sleep 5 ; exit 23" r=$? if [ $r -ne 23 ]; then fail "ssh failed" fi if config_defined DISABLE_FD_PASSING ; then verbose "skipping multiplexing tests" else verbose "multiplexed command timeout" (cat $OBJ/sshd_proxy.orig ; echo "ChannelTimeout session:command=1") \ > $OBJ/sshd_proxy open_mux mux_client "sleep 5 ; exit 23" r=$? if [ $r -ne 255 ]; then fail "ssh returned unexpected error code $r" fi close_mux verbose "irrelevant multiplexed command timeout" (cat $OBJ/sshd_proxy.orig ; echo "ChannelTimeout session:shell=1") \ > $OBJ/sshd_proxy open_mux mux_client "sleep 5 ; exit 23" r=$? if [ $r -ne 23 ]; then fail "ssh returned unexpected error code $r" fi close_mux verbose "global command timeout" (cat $OBJ/sshd_proxy.orig ; echo "ChannelTimeout global=10") \ > $OBJ/sshd_proxy open_mux mux_client "sleep 1 ; echo ok ; sleep 1; echo ok; sleep 60; touch $OBJ/finished.1" >/dev/null & mux_client "sleep 60 ; touch $OBJ/finished.2" >/dev/null & mux_client "sleep 2 ; touch $OBJ/finished.3" >/dev/null & wait test -f $OBJ/finished.1 && fail "first mux process completed" test -f $OBJ/finished.2 && fail "second mux process completed" test -f $OBJ/finished.3 || fail "third mux process did not complete" close_mux fi # Set up a "slow sftp server" that sleeps before executing the real one. cat > $OBJ/slow-sftp-server.sh << _EOF #!/bin/sh sleep 5 $SFTPSERVER _EOF chmod a+x $OBJ/slow-sftp-server.sh verbose "sftp no timeout" (grep -vi subsystem.*sftp $OBJ/sshd_proxy.orig; echo "Subsystem sftp $OBJ/slow-sftp-server.sh" ) > $OBJ/sshd_proxy rm -f ${COPY} $SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY r=$? if [ $r -ne 0 ]; then fail "sftp failed" fi cmp $DATA $COPY || fail "corrupted copy" verbose "sftp timeout" (grep -vi subsystem.*sftp $OBJ/sshd_proxy.orig; echo "ChannelTimeout session:subsystem:sftp=1" ; echo "Subsystem sftp $OBJ/slow-sftp-server.sh" ) > $OBJ/sshd_proxy rm -f ${COPY} $SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY r=$? if [ $r -eq 0 ]; then fail "sftp succeeded unexpectedly" fi test -f $COPY && cmp $DATA $COPY && fail "intact copy" verbose "sftp irrelevant timeout" (grep -vi subsystem.*sftp $OBJ/sshd_proxy.orig; echo "ChannelTimeout session:subsystem:command=1" ; echo "Subsystem sftp $OBJ/slow-sftp-server.sh" ) > $OBJ/sshd_proxy rm -f ${COPY} $SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY r=$? if [ $r -ne 0 ]; then fail "sftp failed" fi cmp $DATA $COPY || fail "corrupted copy" openssh-10.0p1/regress/PaxHeaders.10889/check-perm.c100644 001750 001750 0000000003614775415623 0017010xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/check-perm.c010064400017500001750000000105231477541562300153740ustar00djmdjm/* * Placed in the public domain */ /* $OpenBSD: modpipe.c,v 1.6 2013/11/21 03:16:47 djm Exp $ */ #include "includes.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBGEN_H #include #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; } openssh-10.0p1/regress/PaxHeaders.10889/cipher-speed.sh100644 001750 001750 0000000003614775415623 0017532xustar0030 atime=1744182234.689281639 openssh-10.0p1/regress/cipher-speed.sh010064400017500001750000000020221477541562300161110ustar00djmdjm# $OpenBSD: cipher-speed.sh,v 1.14 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="cipher speed" # Enable all supported ciphers and macs. ciphers=`${SSH} -Q Ciphers | tr '\n' , | sed 's/,$//'` macs=`${SSH} -Q MACs | tr '\n' , | sed 's/,$//'` cat >>$OBJ/sshd_proxy <&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 openssh-10.0p1/regress/PaxHeaders.10889/conch-ciphers.sh100644 001750 001750 0000000003614775415623 0017707xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/conch-ciphers.sh010064400017500001750000000015571477541562300163020ustar00djmdjm# $OpenBSD: conch-ciphers.sh,v 1.7 2023/10/26 12:44:07 dtucker Exp $ # Placed in the Public Domain. tid="conch ciphers" if test "x$REGRESS_INTEROP_CONCH" != "xyes" ; then skip "conch interop tests not enabled" fi if ! [ -t 0 ]; then skip "conch interop tests requires a controlling terminal" fi start_sshd for c in aes256-ctr aes256-cbc aes192-ctr aes192-cbc aes128-ctr aes128-cbc \ cast128-cbc blowfish 3des-cbc ; do verbose "$tid: cipher $c" rm -f ${COPY} # XXX the 2nd "cat" seems to be needed because of buggy FD handling # in conch ${CONCH} --identity $OBJ/ssh-ed25519 --port $PORT --user $USER -e none \ --known-hosts $OBJ/known_hosts --notty --noagent --nox11 -n \ 127.0.0.1 "cat ${DATA}" 2>/dev/null | cat > ${COPY} if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" fi cmp ${DATA} ${COPY} || fail "corrupted copy" done rm -f ${COPY} openssh-10.0p1/regress/PaxHeaders.10889/connect-privsep.sh100644 001750 001750 0000000003614775415623 0020301xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/connect-privsep.sh010064400017500001750000000017401477541562300166660ustar00djmdjm# $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 fail "ssh privsep/sandbox+proxyconnect failed" fi # Because sandbox is sensitive to changes in libc, especially malloc, retest # with every malloc.conf option (and none). if [ -z "$TEST_MALLOC_OPTIONS" ]; then 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 openssh-10.0p1/regress/PaxHeaders.10889/connect-uri.sh100644 001750 001750 0000000003614775415623 0017410xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/connect-uri.sh010064400017500001750000000014601477541562300157740ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/connect.sh100644 001750 001750 0000000003614775415623 0016613xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/connect.sh010064400017500001750000000006271477541562300152030ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/connection-timeout.sh100644 001750 001750 0000000003614775415623 0021005xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/connection-timeout.sh010064400017500001750000000040611477541562300173710ustar00djmdjm# $OpenBSD: connection-timeout.sh,v 1.2 2023/01/17 10:15:10 djm Exp $ # Placed in the Public Domain. tid="unused connection timeout" if config_defined DISABLE_FD_PASSING ; then skip "not supported on this platform" fi CTL=$OBJ/ctl-sock cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig check_ssh() { test -S $CTL || return 1 if ! ${REAL_SSH} -qF$OBJ/ssh_proxy -O check \ -oControlPath=$CTL somehost >/dev/null 2>&1 ; then return 1 fi return 0 } start_ssh() { trace "start ssh" ${SSH} -nNfF $OBJ/ssh_proxy "$@" -oExitOnForwardFailure=yes \ -oControlMaster=yes -oControlPath=$CTL somehost r=$? test $r -eq 0 || fatal "failed to start ssh $r" check_ssh || fatal "ssh process unresponsive" } stop_ssh() { test -S $CTL || return check_ssh || fatal "ssh process is unresponsive: cannot close" if ! ${REAL_SSH} -qF$OBJ/ssh_proxy -O exit \ -oControlPath=$CTL >/dev/null somehost >/dev/null ; then fatal "ssh process did not respond to close" fi n=0 while [ "$n" -lt 20 ] ; do test -S $CTL || break sleep 1 n=`expr $n + 1` done if test -S $CTL ; then fatal "ssh process did not exit" fi } trap "stop_ssh" EXIT verbose "no timeout" start_ssh sleep 5 check_ssh || fatal "ssh unexpectedly missing" stop_ssh (cat $OBJ/sshd_proxy.orig ; echo "UnusedConnectionTimeout 2") > $OBJ/sshd_proxy verbose "timeout" start_ssh sleep 8 check_ssh && fail "ssh unexpectedly present" stop_ssh verbose "session inhibits timeout" rm -f $OBJ/copy.1 start_ssh ${REAL_SSH} -qoControlPath=$CTL -oControlMaster=no -Fnone somehost \ "sleep 8; touch $OBJ/copy.1" & check_ssh || fail "ssh unexpectedly missing" wait test -f $OBJ/copy.1 || fail "missing result file" verbose "timeout after session" # Session should still be running from previous sleep 8 check_ssh && fail "ssh unexpectedly present" stop_ssh LPORT=`expr $PORT + 1` RPORT=`expr $LPORT + 1` DPORT=`expr $RPORT + 1` RDPORT=`expr $DPORT + 1` verbose "timeout with listeners" start_ssh -L$LPORT:127.0.0.1:$PORT -R$RPORT:127.0.0.1:$PORT -D$DPORT -R$RDPORT sleep 8 check_ssh && fail "ssh unexpectedly present" stop_ssh openssh-10.0p1/regress/PaxHeaders.10889/dhgex.sh100644 001750 001750 0000000003614775415623 0016261xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/dhgex.sh010064400017500001750000000027771477541562300146610ustar00djmdjm# $OpenBSD: dhgex.sh,v 1.8 2023/03/02 08:14:52 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 chacha20-poly1305@openssh.com openssh-10.0p1/regress/PaxHeaders.10889/dropbear-ciphers.sh100644 001750 001750 0000000003614775415623 0020413xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/dropbear-ciphers.sh010064400017500001750000000021221477541562300167730ustar00djmdjm# $OpenBSD: dropbear-ciphers.sh,v 1.4 2025/03/11 07:43:03 dtucker Exp $ # Placed in the Public Domain. tid="dropbear ciphers" if test "x$REGRESS_INTEROP_DROPBEAR" != "xyes" ; then skip "dropbear interop tests not enabled" fi # Enable all support algorithms algs=`$SSH -Q key-sig | tr '\n' ,` cat >>$OBJ/sshd_proxy <&1 | awk '/ ciphers: /{print $4}' | tr ',' ' '` macs=`$DBCLIENT -m help hst 2>&1 | awk '/ MACs: /{print $4}' | tr ',' ' '` if [ -z "$macs" ] || [ -z "$ciphers" ]; then skip "dbclient query ciphers '$ciphers' or macs '$macs' failed" fi keytype=`(cd $OBJ/.dropbear && ls id_*)` for c in $ciphers ; do for m in $macs; do for kt in $keytype; do verbose "$tid: cipher $c mac $m kt $kt" rm -f ${COPY} env HOME=$OBJ ${DBCLIENT} -y -i $OBJ/.dropbear/$kt 2>$OBJ/dbclient.log \ -c $c -m $m -J "$OBJ/ssh_proxy.sh" somehost cat ${DATA} > ${COPY} if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" fi cmp ${DATA} ${COPY} || fail "corrupted copy" done done done rm -f ${COPY} openssh-10.0p1/regress/PaxHeaders.10889/dropbear-kex.sh100644 001750 001750 0000000003614775415623 0017545xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/dropbear-kex.sh010064400017500001750000000022371477541562300161340ustar00djmdjm# $OpenBSD: dropbear-kex.sh,v 1.4 2025/03/11 07:42:08 dtucker Exp $ # Placed in the Public Domain. tid="dropbear kex" if test "x$REGRESS_INTEROP_DROPBEAR" != "xyes" ; then skip "dropbear interop tests not enabled" fi cp $OBJ/sshd_proxy $OBJ/sshd_proxy.bak kex="curve25519-sha256 curve25519-sha256@libssh.org" if $SSH -Q kex | grep 'diffie-hellman-group14-sha256' >/dev/null; then kex="$kex diffie-hellman-group14-sha256" fi # There's no flag to query KEX, so if MACs does not contain SHA1, assume # there's also SHA1-based KEX methods either. if $SSH -Q kex | grep 'diffie-hellman-group14-sha1' >/dev/null && \ $DBCLIENT -m help hst 2>&1 | grep -- '-sha1' >/dev/null ; then kex="$kex diffie-hellman-group14-sha1" fi for k in $kex; do verbose "$tid: kex $k" rm -f ${COPY} # dbclient doesn't have switch for kex, so force in server (cat $OBJ/sshd_proxy.bak; echo "KexAlgorithms $k") >$OBJ/sshd_proxy env HOME=$OBJ \ ${DBCLIENT} -y -i $OBJ/.dropbear/id_ed25519 2>$OBJ/dbclient.log \ -J "$OBJ/ssh_proxy.sh" somehost cat ${DATA} > ${COPY} if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" fi cmp ${DATA} ${COPY} || fail "corrupted copy" done rm -f ${COPY} openssh-10.0p1/regress/PaxHeaders.10889/dsa_ssh2.prv100644 001750 001750 0000000003614775415623 0017065xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/dsa_ssh2.prv010064400017500001750000000015371477541562300154560ustar00djmdjm---- 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 ---- openssh-10.0p1/regress/PaxHeaders.10889/dsa_ssh2.pub100644 001750 001750 0000000003614775415623 0017044xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/dsa_ssh2.pub010064400017500001750000000013341477541562300154300ustar00djmdjm---- 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 ---- openssh-10.0p1/regress/PaxHeaders.10889/dynamic-forward.sh100644 001750 001750 0000000003614775415623 0020250xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/dynamic-forward.sh010064400017500001750000000055371477541562300166450ustar00djmdjm# $OpenBSD: dynamic-forward.sh,v 1.17 2024/03/08 11:34:10 dtucker Exp $ # Placed in the Public Domain. tid="dynamic forwarding" # This is a reasonable proxy for IPv6 support. if ! config_defined HAVE_STRUCT_IN6_ADDR ; then SKIP_IPV6=yes fi FWDPORT=`expr $PORT + 1` make_tmpdir CTL=${SSH_REGRESS_TMP}/ctl-sock cp $OBJ/ssh_config $OBJ/ssh_config.orig proxycmd="$OBJ/netcat -x 127.0.0.1:$FWDPORT -X" trace "will use ProxyCommand $proxycmd" start_ssh() { direction="$1" arg="$2" n=0 error="1" # Use a multiplexed ssh so we can control its lifecycle. trace "start dynamic -$direction forwarding, fork to background" (cat $OBJ/ssh_config.orig ; echo "$arg") > $OBJ/ssh_config ${REAL_SSH} -vvvnNfF $OBJ/ssh_config -E$TEST_SSH_LOGFILE \ -$direction $FWDPORT -oExitOnForwardFailure=yes \ -oControlMaster=yes -oControlPath=$CTL somehost r=$? test $r -eq 0 || fatal "failed to start dynamic forwarding $r" if ! ${REAL_SSH} -qF$OBJ/ssh_config -O check \ -oControlPath=$CTL somehost >/dev/null 2>&1 ; then fatal "forwarding ssh process unresponsive" fi } stop_ssh() { test -S $CTL || return if ! ${REAL_SSH} -qF$OBJ/ssh_config -O exit \ -oControlPath=$CTL >/dev/null somehost >/dev/null ; then fatal "forwarding ssh process did not respond to close" fi n=0 while [ "$n" -lt 20 ] ; do test -S $CTL || break sleep 1 n=`expr $n + 1` done if test -S $CTL ; then fatal "forwarding ssh process did not exit" fi } check_socks() { direction=$1 expect_success=$2 for s in 4 5; do for h in 127.0.0.1 localhost; do trace "testing ssh socks version $s host $h (-$direction)" ${REAL_SSH} -q -F $OBJ/ssh_config -o \ "ProxyCommand ${TEST_SHELL} -c '${proxycmd}${s} $h $PORT 2>/dev/null'" \ somehost cat ${DATA} > ${COPY} r=$? if [ "x$expect_success" = "xY" ] ; then if [ $r -ne 0 ] ; then fail "ssh failed with exit status $r" fi test -f ${COPY} || fail "failed copy ${DATA}" cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" elif [ $r -eq 0 ] ; then fail "ssh unexpectedly succeeded" fi done done } start_sshd trap "stop_ssh" EXIT for d in D R; do verbose "test -$d forwarding" start_ssh $d check_socks $d Y stop_ssh test "x$d" = "xR" || continue # Test PermitRemoteOpen verbose "PermitRemoteOpen=any" start_ssh $d PermitRemoteOpen=any check_socks $d Y stop_ssh verbose "PermitRemoteOpen=none" start_ssh $d PermitRemoteOpen=none check_socks $d N stop_ssh verbose "PermitRemoteOpen=explicit" permit="127.0.0.1:$PORT [::1]:$PORT localhost:$PORT" test -z "$SKIP_IPV6" || permit="127.0.0.1:$PORT localhost:$PORT" start_ssh $d PermitRemoteOpen="$permit" check_socks $d Y stop_ssh verbose "PermitRemoteOpen=disallowed" permit="127.0.0.1:1 [::1]:1 localhost:1" test -z "$SKIP_IPV6" || permit="127.0.0.1:1 localhost:1" start_ssh $d PermitRemoteOpen="$permit" check_socks $d N stop_ssh done openssh-10.0p1/regress/PaxHeaders.10889/ed25519_openssh.prv100644 001750 001750 0000000003614775415623 0020114xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/ed25519_openssh.prv010064400017500001750000000006431477541562300165020ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACDE8/0FM7Yw6xc53QpiZUQAh/LK2mEAwNDNYdSR6GIGIwAAAKC+Cfdzvgn3 cwAAAAtzc2gtZWQyNTUxOQAAACDE8/0FM7Yw6xc53QpiZUQAh/LK2mEAwNDNYdSR6GIGIw AAAEBm+60DgH0WMW7Z5oyvu1dxo7MaXe5RRMWTMJCfLkHexMTz/QUztjDrFzndCmJlRACH 8sraYQDA0M1h1JHoYgYjAAAAGWR0dWNrZXJAcXVvbGwuZHR1Y2tlci5uZXQBAgME -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/PaxHeaders.10889/ed25519_openssh.pub100644 001750 001750 0000000003614775415623 0020073xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/ed25519_openssh.pub010064400017500001750000000001211477541562300164500ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMTz/QUztjDrFzndCmJlRACH8sraYQDA0M1h1JHoYgYj openssh-10.0p1/regress/PaxHeaders.10889/envpass.sh100644 001750 001750 0000000003614775415623 0016641xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/envpass.sh010064400017500001750000000062721477541562300152330ustar00djmdjm# $OpenBSD: envpass.sh,v 1.5 2022/06/03 04:31:54 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 cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak 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 "setenv, don't accept" verbose "test $tid: setenv, don't accept" ${SSH} -oSendEnv="*" -F $OBJ/ssh_proxy_envpass -oSetEnv="_TEST_ENV=blah" \ 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 trace "setenv, accept" verbose "test $tid: setenv, accept" ${SSH} -F $OBJ/ssh_proxy_envpass \ -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_B=2" 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 trace "setenv, first match wins" verbose "test $tid: setenv, first match wins" ${SSH} -F $OBJ/ssh_proxy_envpass \ -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_A=11 _XXX_TEST_B=2" 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 trace "server setenv wins" verbose "test $tid: server setenv wins" cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "SetEnv _XXX_TEST_A=23" >> $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy_envpass \ -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_B=2" otherhost \ sh << 'EOF' test X"$_XXX_TEST_A" = X"23" -a X"$_XXX_TEST_B" = X"2" EOF r=$? if [ $r -ne 0 ]; then fail "environment not found" fi trace "server setenv first match wins" verbose "test $tid: server setenv wins" cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "SetEnv _XXX_TEST_A=23 _XXX_TEST_A=42" >> $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy_envpass \ -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_B=2" otherhost \ sh << 'EOF' test X"$_XXX_TEST_A" = X"23" -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 openssh-10.0p1/regress/PaxHeaders.10889/exit-status-signal.sh100644 001750 001750 0000000003614775415623 0020727xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/exit-status-signal.sh010064400017500001750000000007411477541562300173140ustar00djmdjm# This test performs validation that ssh client is not successive on being terminated tid="exit status on signal" # spawn client in background rm -f $OBJ/remote_pid ${SSH} -F $OBJ/ssh_proxy somehost 'echo $$ >'$OBJ'/remote_pid; sleep 444' & ssh_pid=$! # wait for it to start n=20 while [ ! -f $OBJ/remote_pid ] && [ $n -gt 0 ]; do n=$(($n - 1)) sleep 1 done kill $ssh_pid wait $ssh_pid exit_code=$? if [ $exit_code -eq 0 ]; then fail "ssh client should fail on signal" fi openssh-10.0p1/regress/PaxHeaders.10889/exit-status.sh100644 001750 001750 0000000003614775415623 0017454xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/exit-status.sh010064400017500001750000000010621477541562300160360ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/forcecommand.sh100644 001750 001750 0000000003614775415623 0017617xustar0030 atime=1744182234.690258337 openssh-10.0p1/regress/forcecommand.sh010064400017500001750000000042401477541562300162020ustar00djmdjm# $OpenBSD: forcecommand.sh,v 1.7 2023/11/01 02:08:38 dtucker Exp $ # Placed in the Public Domain. tid="forced command" cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak authorized_keys() { cmd=$1 cp /dev/null $OBJ/authorized_keys_$USER for t in ${SSH_KEYTYPES}; do test -z "$cmd" || \ printf "command=\"$cmd\" " >>$OBJ/authorized_keys_$USER cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER done } trace "test config with sftp" authorized_keys rm -f $OBJ/ssh_proxy.tmp echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ ${SFTP} -S ${SSH} -b - -qF $OBJ/ssh_proxy somehost 2>/dev/null || \ fail "sftp failed" test -f "$OBJ/ssh_proxy.tmp" || fail "sftp did not download file" rm -f $OBJ/ssh_proxy.tmp trace "forced command in key option" authorized_keys true ${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key option" authorized_keys false cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "ForceCommand true" >> $OBJ/sshd_proxy trace "forced command in sshd_config overrides key option" ${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command config" authorized_keys cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "ForceCommand false" >> $OBJ/sshd_proxy trace "force command overriding subsystem" echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ ${SFTP} -S ${SSH} -F $OBJ/ssh_proxy -oLoglevel=quiet somehost && \ fail "sftp succeeded" echo "Match User $USER" >> $OBJ/sshd_proxy echo " ForceCommand true" >> $OBJ/sshd_proxy trace "forced command with match" ${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command match" trace "force command in match overriding subsystem" echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ ${SFTP} -S ${SSH} -F $OBJ/ssh_proxy -oLoglevel=quiet somehost && \ fail "sftp succeeded" trace "force command to sftpserver" grep -vi subsystem $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy echo "Subsystem sftp /bin/false" >> $OBJ/sshd_proxy echo "ForceCommand ${SFTPSERVER}" >> $OBJ/sshd_proxy rm -f $OBJ/ssh_proxy.tmp echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ ${SFTP} -S ${SSH} -b - -qF $OBJ/ssh_proxy somehost 2>/dev/null || \ fail "sftp failed" test -f "$OBJ/ssh_proxy.tmp" || fail "sftp did not download file" rm -f $OBJ/ssh_proxy.tmp openssh-10.0p1/regress/PaxHeaders.10889/forward-control.sh100644 001750 001750 0000000003614775415623 0020304xustar0030 atime=1744182234.691234022 openssh-10.0p1/regress/forward-control.sh010064400017500001750000000170361477541562300166760ustar00djmdjm# $OpenBSD: forward-control.sh,v 1.12 2023/07/28 05:33:15 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 WAIT_SECONDS=20 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 $WAIT_SECONDS && return 1 sleep 1 done return 0 } mux_cmd() { ${SSH} -F $OBJ/ssh_proxy -S $CTL -O $1 host 2>&1 } controlmaster_pid() { mux_cmd check | cut -f2 -d= | cut -f1 -d')' } # usage: check_lfwd Y|N message check_lfwd() { _expected=$1 _message=$2 ${SSH} -F $OBJ/ssh_proxy \ -L$LFWD_PORT:127.0.0.1:$PORT \ -o ExitOnForwardFailure=yes \ -MS $CTL -o ControlPersist=yes \ -Nf host mux_cmd check >/dev/null || fatal "check_lfwd ssh fail: $_message" ${SSH} -F $OBJ/ssh_config -p $LFWD_PORT \ -oConnectionAttempts=10 host true >/dev/null 2>&1 _result=$? _sshpid=`controlmaster_pid` mux_cmd exit >/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 ${SSH} -F $OBJ/ssh_proxy \ -R127.0.0.1:$RFWD_PORT:127.0.0.1:$PORT \ -o ExitOnForwardFailure=yes \ -MS $CTL -o ControlPersist=yes \ -Nf host mux_cmd check >/dev/null _result=$? _sshpid=`controlmaster_pid` if test $_result -eq 0; then ${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \ -oConnectionAttempts=10 host true >/dev/null 2>&1 _result=$? mux_cmd exit >/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 openssh-10.0p1/regress/PaxHeaders.10889/forwarding.sh100644 001750 001750 0000000003614775415623 0017324xustar0030 atime=1744182234.691234022 openssh-10.0p1/regress/forwarding.sh010064400017500001750000000104251477541562300157110ustar00djmdjm# $OpenBSD: forwarding.sh,v 1.24 2021/05/07 09:23:40 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=10' \ 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=10' \ 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=10' \ 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 openssh-10.0p1/regress/PaxHeaders.10889/host-expand.sh100644 001750 001750 0000000003614775415623 0017414xustar0030 atime=1744182234.691234022 openssh-10.0p1/regress/host-expand.sh010064400017500001750000000006001477541562300157730ustar00djmdjm# $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 <$OBJ/actual diff $OBJ/expect $OBJ/actual || fail "$tid" openssh-10.0p1/regress/PaxHeaders.10889/hostbased.sh100644 001750 001750 0000000003614775415623 0017136xustar0030 atime=1744182234.691234022 openssh-10.0p1/regress/hostbased.sh010064400017500001750000000041661477541562300155300ustar00djmdjm# $OpenBSD: hostbased.sh,v 1.4 2022/12/07 11:45:43 dtucker Exp $ # Placed in the Public Domain. # This test requires external setup and thus is skipped unless # TEST_SSH_HOSTBASED_AUTH and SUDO are set to "yes". # Since ssh-keysign has key paths hard coded, unlike the other tests it # needs to use the real host keys. It requires: # - ssh-keysign must be installed and setuid. # - "EnableSSHKeysign yes" must be in the system ssh_config. # - the system's own real FQDN the system-wide shosts.equiv. # - the system's real public key fingerprints must be in global ssh_known_hosts. # tid="hostbased" if [ -z "${TEST_SSH_HOSTBASED_AUTH}" ]; then skip "TEST_SSH_HOSTBASED_AUTH not set." elif [ -z "${SUDO}" ]; then skip "SUDO not set" fi # Enable all supported hostkey algos (but no others) hostkeyalgos=`${SSH} -Q HostKeyAlgorithms | tr '\n' , | sed 's/,$//'` cat >>$OBJ/sshd_proxy <>$OBJ/ssh_proxy < /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 "make CA key" ${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA" trace "load hostkeys" for k in $SSH_KEYTYPES ; do ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k" ${SSHKEYGEN} -s $OBJ/agent-ca -qh -n localhost-with-alias \ -I localhost-with-alias $OBJ/agent-key.$k.pub || \ fatal "sign $k" ${SSHADD} -k $OBJ/agent-key.$k >/dev/null 2>&1 || \ fatal "couldn't load key $OBJ/agent-key.$k" # Remove private key so the server can't use it. rm $OBJ/agent-key.$k || fatal "couldn't rm $OBJ/agent-key.$k" done rm $OBJ/agent-ca # Don't need CA private any more either unset SSH_AUTH_SOCK for k in $SSH_KEYTYPES ; do verbose "key type $k" cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" ( printf 'localhost-with-alias,127.0.0.1,::1 ' ; cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then fail "keytype $k failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then fail "bad SSH_CONNECTION key type $k" fi done SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com' | maybe_filter_sk` # Prepare sshd_proxy for certificates. cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy HOSTKEYALGS="" for k in $SSH_CERTTYPES ; do test -z "$HOSTKEYALGS" || HOSTKEYALGS="${HOSTKEYALGS}," HOSTKEYALGS="${HOSTKEYALGS}${k}" done for k in $SSH_KEYTYPES ; do echo "Hostkey $OBJ/agent-key.${k}.pub" >> $OBJ/sshd_proxy echo "HostCertificate $OBJ/agent-key.${k}-cert.pub" >> $OBJ/sshd_proxy test -f $OBJ/agent-key.${k}.pub || fatal "no $k key" test -f $OBJ/agent-key.${k}-cert.pub || fatal "no $k cert" done echo "HostKeyAlgorithms $HOSTKEYALGS" >> $OBJ/sshd_proxy # Add only CA trust anchor to known_hosts. ( printf '@cert-authority localhost-with-alias ' ; cat $OBJ/agent-ca.pub) > $OBJ/known_hosts for k in $SSH_CERTTYPES ; do verbose "cert type $k" opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then fail "cert type $k failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then fail "bad SSH_CONNECTION key type $k" fi done verbose "multiple hostkeys" cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy cp $OBJ/ssh_proxy $OBJ/ssh_proxy.orig grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy echo "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy for k in $SSH_KEYTYPES ; do verbose "Addkey type $k" echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy ( printf 'localhost-with-alias ' ; cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts done opts="-oStrictHostKeyChecking=yes -F $OBJ/ssh_proxy" SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then fail "connection to server with multiple hostkeys failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then fail "bad SSH_CONNECTION key while using multiple hostkeys" fi trace "kill agent" ${SSHAGENT} -k > /dev/null openssh-10.0p1/regress/PaxHeaders.10889/hostkey-rotate.sh100644 001750 001750 0000000003614775415623 0020144xustar0030 atime=1744182234.691234022 openssh-10.0p1/regress/hostkey-rotate.sh010064400017500001750000000121121477541562300165240ustar00djmdjm# $OpenBSD: hostkey-rotate.sh,v 1.10 2022/01/05 08:25:05 djm Exp $ # Placed in the Public Domain. tid="hostkey rotate" # # GNU (f)grep <=2.18, as shipped by FreeBSD<=12 and NetBSD<=9 will occasionally # fail to find ssh host keys in the hostkey-rotate test. If we have those # versions, use awk instead. # See # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=258616 # case `grep --version 2>&1 | awk '/GNU grep/{print $4}'` in 2.19) fgrep=good ;; 1.*|2.?|2.?.?|2.1?) fgrep=bad ;; # stock GNU grep 2.5.1*) fgrep=bad ;; # FreeBSD and NetBSD *) fgrep=good ;; esac if test "x$fgrep" = "xbad"; then fgrep() { awk 'BEGIN{e=1} {if (index($0,"'$1'")>0){e=0;print}} END{exit e}' $2 } fi rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig $OBJ/ssh_proxy.orig grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy echo "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy rm $OBJ/known_hosts # The "primary" key type is ed25519 since it's supported even when built # 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}," case "$k" in ssh-rsa) secondary="ssh-rsa" all_algs="${all_algs}rsa-sha2-256,rsa-sha2-512,$k" ;; *) all_algs="${all_algs}$k" ;; 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 case "$k" in ssh-rsa) alg="rsa-sha2-256,rsa-sha2-512,ssh-rsa" ;; *) alg="$k" ;; esac verbose "learn additional hostkeys, type=$k" dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$alg,$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" openssh-10.0p1/regress/PaxHeaders.10889/integrity.sh100644 001750 001750 0000000003614775415623 0017200xustar0030 atime=1744182234.691234022 openssh-10.0p1/regress/integrity.sh010064400017500001750000000045001477541562300155620ustar00djmdjm# $OpenBSD: integrity.sh,v 1.25 2023/03/01 09:29:32 dtucker 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 ${OBJ}/sshd-log-wrapper.sh -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 openssh-10.0p1/regress/PaxHeaders.10889/kextype.sh100644 001750 001750 0000000003514775415623 0016652xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/kextype.sh010064400017500001750000000011131477541562300152320ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/key-options.sh100644 001750 001750 0000000003514775415623 0017442xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/key-options.sh010064400017500001750000000070241477541562300160310ustar00djmdjm# $OpenBSD: key-options.sh,v 1.11 2024/12/05 14:28:39 dtucker 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" if config_defined "SIZEOF_TIME_T 4"; then check_valid_before "valid" 'expiry-time="20380101"' "pass" else check_valid_before "valid-64b" 'expiry-time="25250101"' "pass" fi openssh-10.0p1/regress/PaxHeaders.10889/keygen-change.sh100644 001750 001750 0000000003514775415623 0017666xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keygen-change.sh010064400017500001750000000010121477541562300162440ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/keygen-comment.sh100644 001750 001750 0000000003514775415623 0020103xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keygen-comment.sh010064400017500001750000000026511477541562300164730ustar00djmdjm#    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 openssh-10.0p1/regress/PaxHeaders.10889/keygen-convert.sh100644 001750 001750 0000000003514775415623 0020121xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keygen-convert.sh010064400017500001750000000033301477541562300165040ustar00djmdjm# $OpenBSD: keygen-convert.sh,v 1.6 2021/07/24 02:57:28 dtucker Exp $ # Placed in the Public Domain. tid="convert keys" cat > $OBJ/askpass <&1 | grep "ssh-keygen -e" >/dev/null; then test_import_export=1 fi for t in ${SSH_KEYTYPES}; do # generate user key for agent trace "generating $t key" rm -f $OBJ/$t-key ${SSHKEYGEN} -q -N "" -t $t -f $OBJ/$t-key if test "x$test_import_export" = "x1"; then trace "export $t private to rfc4716 public" ${SSHKEYGEN} -q -e -f $OBJ/$t-key >$OBJ/$t-key-rfc || \ fail "export $t private to rfc4716 public" trace "export $t public to rfc4716 public" ${SSHKEYGEN} -q -e -f $OBJ/$t-key.pub >$OBJ/$t-key-rfc.pub || \ fail "$t public to rfc4716 public" cmp $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub || \ fail "$t rfc4716 exports differ between public and private" trace "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" fi trace "set passphrase $t" ${SSHKEYGEN} -q -p -P '' -N 'hunter2' -f $OBJ/$t-key >/dev/null || \ fail "$t set passphrase failed" trace "export $t to public with passphrase" SSH_ASKPASS=$OBJ/askpass SSH_ASKPASS_REQUIRE=force \ ${SSHKEYGEN} -y -f $OBJ/$t-key >$OBJ/$t-key-nocomment.pub cmp $OBJ/$t-key.pub $OBJ/$t-key-nocomment.pub || \ fail "$t exported pubkey differs from generated" rm -f $OBJ/$t-key $OBJ/$t-key.pub $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub \ $OBJ/$t-rfc-imported $OBJ/$t-key-nocomment.pub done openssh-10.0p1/regress/PaxHeaders.10889/keygen-knownhosts.sh100644 001750 001750 0000000003514775415623 0020656xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keygen-knownhosts.sh010064400017500001750000000146541477541562300172540ustar00djmdjm# $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" openssh-10.0p1/regress/PaxHeaders.10889/keygen-moduli.sh100644 001750 001750 0000000003514775415623 0017732xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keygen-moduli.sh010064400017500001750000000016041477541562300163170ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/krl.sh100644 001750 001750 0000000003514775415623 0015751xustar0029 atime=1744182234.71271861 openssh-10.0p1/regress/krl.sh010064400017500001750000000157241477541562300143460ustar00djmdjm# $OpenBSD: krl.sh,v 1.12 2023/01/16 04:11:29 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 || 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 openssh-10.0p1/regress/PaxHeaders.10889/keygen-sshfp.sh100644 001750 001750 0000000003514775415623 0017564xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keygen-sshfp.sh010064400017500001750000000032541477541562300161540ustar00djmdjm# $OpenBSD: keygen-sshfp.sh,v 1.3 2023/02/10 05:06:03 djm Exp $ # Placed in the Public Domain. tid="keygen-sshfp" trace "keygen fingerprints" fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | \ awk '$5=="1"{print $6}'` if [ "$fp" != "8a8647a7567e202ce317e62606c799c53d4c121f" ]; then fail "keygen fingerprint sha1" fi fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | \ awk '$5=="2"{print $6}'` if [ "$fp" != \ "54a506fb849aafb9f229cf78a94436c281efcb4ae67c8a430e8c06afcb5ee18f" ]; then fail "keygen fingerprint sha256" fi # Expect two lines of output without an explicit algorithm fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | wc -l` if [ $(($fp + 0)) -ne 2 ] ; then fail "incorrect number of SSHFP records $fp (expected 2)" fi # Test explicit algorithm selection exp="test IN SSHFP 4 1 8a8647a7567e202ce317e62606c799c53d4c121f" fp=`${SSHKEYGEN} -Ohashalg=sha1 -r test -f ${SRC}/ed25519_openssh.pub` if [ "x$exp" != "x$fp" ] ; then fail "incorrect SHA1 SSHFP output" fi exp="test IN SSHFP 4 2 54a506fb849aafb9f229cf78a94436c281efcb4ae67c8a430e8c06afcb5ee18f" fp=`${SSHKEYGEN} -Ohashalg=sha256 -r test -f ${SRC}/ed25519_openssh.pub` if [ "x$exp" != "x$fp" ] ; then fail "incorrect SHA256 SSHFP output" fi if ${SSH} -Q key-plain | grep ssh-rsa >/dev/null; then fp=`${SSHKEYGEN} -r test -f ${SRC}/rsa_openssh.pub | awk '$5=="1"{print $6}'` if [ "$fp" != "99c79cc09f5f81069cc017cdf9552cfc94b3b929" ]; then fail "keygen fingerprint sha1" fi fp=`${SSHKEYGEN} -r test -f ${SRC}/rsa_openssh.pub | awk '$5=="2"{print $6}'` if [ "$fp" != \ "e30d6b9eb7a4de495324e4d5870b8220577993ea6af417e8e4a4f1c5bf01a9b6" ]; then fail "keygen fingerprint sha256" fi fi openssh-10.0p1/regress/PaxHeaders.10889/keys-command.sh100644 001750 001750 0000000003514775415623 0017550xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keys-command.sh010064400017500001750000000045771477541562300161510ustar00djmdjm# $OpenBSD: keys-command.sh,v 1.8 2021/09/30 04:22:50 dtucker Exp $ # Placed in the Public Domain. tid="authorized keys from command" if [ -z "$SUDO" -a ! -w /var/run ]; then skip "need SUDO to create file in /var/run, test won't work without" 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 skip "$KEY_COMMAND not executable (/var/run mounted noexec?)" fi openssh-10.0p1/regress/PaxHeaders.10889/keyscan.sh100644 001750 001750 0000000003514775415623 0016616xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keyscan.sh010064400017500001750000000007541477541562300152100ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/keytype.sh100644 001750 001750 0000000003514775415623 0016653xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/keytype.sh010064400017500001750000000046131477541562300152430ustar00djmdjm# $OpenBSD: keytype.sh,v 1.11 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="login with different key types" 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 PubkeyAcceptedAlgorithms $user_type echo HostKeyAlgorithms $host_type ) > $OBJ/sshd_proxy ( grep -v IdentityFile $OBJ/ssh_proxy_bak echo IdentityFile $OBJ/key.$ut echo PubkeyAcceptedAlgorithms $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 openssh-10.0p1/regress/PaxHeaders.10889/knownhosts-command.sh100644 001750 001750 0000000003514775415623 0021012xustar0029 atime=1744182234.69221116 openssh-10.0p1/regress/knownhosts-command.sh010064400017500001750000000031751477541562300174040ustar00djmdjm# $OpenBSD: knownhosts-command.sh,v 1.3 2021/08/30 01:15:45 djm Exp $ # Placed in the Public Domain. tid="known hosts command " rm -f $OBJ/knownhosts_command $OBJ/ssh_proxy_khc cp $OBJ/ssh_proxy $OBJ/ssh_proxy_orig ( grep -vi GlobalKnownHostsFile $OBJ/ssh_proxy_orig | \ grep -vi UserKnownHostsFile; echo "GlobalKnownHostsFile none" ; echo "UserKnownHostsFile none" ; echo "KnownHostsCommand $OBJ/knownhosts_command '%t' '%K' '%u'" ; ) > $OBJ/ssh_proxy verbose "simple connection" cat > $OBJ/knownhosts_command << _EOF #!/bin/sh cat $OBJ/known_hosts _EOF chmod a+x $OBJ/knownhosts_command ${SSH} -F $OBJ/ssh_proxy x true || fail "ssh connect failed" verbose "no keys" cat > $OBJ/knownhosts_command << _EOF #!/bin/sh exit 0 _EOF chmod a+x $OBJ/knownhosts_command ${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with no keys" verbose "bad exit status" cat > $OBJ/knownhosts_command << _EOF #!/bin/sh cat $OBJ/known_hosts exit 1 _EOF chmod a+x $OBJ/knownhosts_command ${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with bad exit" for keytype in ${SSH_HOSTKEY_TYPES} ; do algs=$keytype test "x$keytype" = "xssh-dss" && continue test "x$keytype" = "xssh-rsa" && algs=ssh-rsa,rsa-sha2-256,rsa-sha2-512 verbose "keytype $keytype" cat > $OBJ/knownhosts_command << _EOF #!/bin/sh die() { echo "\$@" 1>&2 ; exit 1; } test "x\$1" = "x$keytype" || die "wrong keytype \$1 (expected $keytype)" test "x\$3" = "x$LOGNAME" || die "wrong username \$3 (expected $LOGNAME)" grep -- "\$1.*\$2" $OBJ/known_hosts _EOF ${SSH} -F $OBJ/ssh_proxy -oHostKeyAlgorithms=$algs x true || fail "ssh connect failed for keytype $x" done openssh-10.0p1/regress/PaxHeaders.10889/knownhosts.sh100644 001750 001750 0000000003514775415623 0017376xustar0029 atime=1744182234.71271861 openssh-10.0p1/regress/knownhosts.sh010064400017500001750000000023111477541562300157570ustar00djmdjm# $OpenBSD: knownhosts.sh,v 1.2 2023/02/09 09:55:33 dtucker Exp $ # Placed in the Public Domain. tid="known hosts" opts="-F $OBJ/ssh_proxy" trace "test initial connection" ${SSH} $opts somehost true || fail "initial connection" trace "learn hashed known host" >$OBJ/known_hosts ${SSH} -ohashknownhosts=yes -o stricthostkeychecking=no $opts somehost true \ || fail "learn hashed known_hosts" trace "test hashed known hosts" ${SSH} $opts somehost true || fail "reconnect with hashed known hosts" trace "no newline at end of known_hosts" printf "something" >$OBJ/known_hosts ${SSH} $opts -ostricthostkeychecking=no somehost true \ || fail "hostkey update, missing newline, no strict" ${SSH} $opts -ostricthostkeychecking=yes somehost true \ || fail "reconnect after adding with missing newline" trace "newline at end of known_hosts" printf "something\n" >$OBJ/known_hosts ${SSH} $opts -ostricthostkeychecking=no somehost true \ || fail "hostkey update, newline, no strict" ${SSH} $opts -ostricthostkeychecking=yes somehost true \ || fail "reconnect after adding without missing newline" lines=`wc -l <$OBJ/known_hosts` if [ $lines -ne 2 ]; then fail "expected 2 lines in known_hosts, found $lines" fi openssh-10.0p1/regress/PaxHeaders.10889/limit-keytype.sh100644 001750 001750 0000000003514775415623 0017767xustar0029 atime=1744182234.71271861 openssh-10.0p1/regress/limit-keytype.sh010064400017500001750000000112551477541562300163570ustar00djmdjm# $OpenBSD: limit-keytype.sh,v 1.10 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="restrict pubkey type" # XXX sk-* keys aren't actually tested ATM. rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key* rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key* mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig ktype1=ed25519; ktype2=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 PubkeyAcceptedAlgorithms 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 \ "PubkeyAcceptedAlgorithms `keytype $ktype2`,`keytype $ktype1`" ${SSH} $certopts proxy true && fatal "cert succeeded" ${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed" # Allow Ed25519 only. verbose "allow $ktype1" prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype1`" ${SSH} $certopts proxy true && fatal "cert succeeded" ${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" if [ "$ktype1" != "$ktype2" ]; then ${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 "PubkeyAcceptedAlgorithms *-cert-v01@openssh.com" ${SSH} $certopts proxy true || fatal "cert failed" ${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded" ${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded" # Allow RSA in main config, Ed25519 for non-existent user. verbose "match w/ no match" prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype2`" \ "Match user x$USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`" ${SSH} $certopts proxy true && fatal "cert succeeded" if [ "$ktype1" != "$ktype2" ]; then ${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded" 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 "PubkeyAcceptedAlgorithms `keytype $ktype4`" \ "Match user $USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`" ${SSH} $certopts proxy true || fatal "cert failed" ${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" ${SSH} $opts -i $OBJ/user_key4 proxy true && fatal "key4 succeeded" openssh-10.0p1/regress/PaxHeaders.10889/localcommand.sh100644 001750 001750 0000000003514775415623 0017612xustar0029 atime=1744182234.71271861 openssh-10.0p1/regress/localcommand.sh010064400017500001750000000005371477541562300162030ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/login-timeout.sh100644 001750 001750 0000000003514775415623 0017755xustar0029 atime=1744182234.71271861 openssh-10.0p1/regress/login-timeout.sh010064400017500001750000000011051477541562300163360ustar00djmdjm# $OpenBSD: login-timeout.sh,v 1.10 2021/09/30 05:20:08 dtucker Exp $ # Placed in the Public Domain. tid="connect after login grace timeout" trace "test login grace time" 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 openssh-10.0p1/regress/PaxHeaders.10889/match-subsystem.sh100644 001750 001750 0000000003514775415623 0020311xustar0029 atime=1744182234.71271861 openssh-10.0p1/regress/match-subsystem.sh010064400017500001750000000043221477541562300166760ustar00djmdjm# $OpenBSD: match-subsystem.sh,v 1.1 2023/09/06 23:36:09 djm Exp $ # Placed in the Public Domain. tid="sshd_config match subsystem" cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak try_subsystem() { _id=$1 _subsystem=$2 _expect=$3 ${SSHD} -tf $OBJ/sshd_proxy || fatal "$_id: bad config" ${SSH} -sF $OBJ/ssh_proxy somehost $_subsystem _exit=$? trace "$_id subsystem $_subsystem" if [ $_exit -ne $_expect ] ; then fail "$_id: subsystem $_subsystem exit $_exit expected $_expect" fi return $? } # Simple case: subsystem in main config. cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Subsystem xxx /bin/sh -c "exit 23" _EOF try_subsystem "main config" xxx 23 # No clobber in main config. cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Subsystem xxx /bin/sh -c "exit 23" Subsystem xxx /bin/sh -c "exit 24" _EOF try_subsystem "main config no clobber" xxx 23 # Subsystem in match all block cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Match all Subsystem xxx /bin/sh -c "exit 21" _EOF try_subsystem "match all" xxx 21 # No clobber in match all block cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Match all Subsystem xxx /bin/sh -c "exit 21" Subsystem xxx /bin/sh -c "exit 24" _EOF try_subsystem "match all no clobber" xxx 21 # Subsystem in match user block cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Match user * Subsystem xxx /bin/sh -c "exit 20" _EOF try_subsystem "match user" xxx 20 # No clobber in match user block cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Match user * Subsystem xxx /bin/sh -c "exit 20" Subsystem xxx /bin/sh -c "exit 24" Match all Subsystem xxx /bin/sh -c "exit 24" _EOF try_subsystem "match user no clobber" xxx 20 # Override main with match all cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Subsystem xxx /bin/sh -c "exit 23" Match all Subsystem xxx /bin/sh -c "exit 19" _EOF try_subsystem "match all override" xxx 19 # Override main with match user cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy cat >> $OBJ/sshd_proxy << _EOF Subsystem xxx /bin/sh -c "exit 23" Match user * Subsystem xxx /bin/sh -c "exit 18" _EOF try_subsystem "match user override" xxx 18 openssh-10.0p1/regress/PaxHeaders.10889/misc040755 001750 001750 0000000003614775415623 0015512xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc004075500017500001750000000000001477541562300140705ustar00djmdjmopenssh-10.0p1/regress/misc/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0017221xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/Makefile010064400017500001750000000000541477541562300156030ustar00djmdjmSUBDIR= sk-dummy .include openssh-10.0p1/regress/misc/PaxHeaders.10889/fuzz-harness040755 001750 001750 0000000003614775415623 0020151xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness004075500017500001750000000000001477541562300165275ustar00djmdjmopenssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021660xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness/Makefile010064400017500001750000000053641477541562300202530ustar00djmdjm# NB. libssh and libopenbsd-compat should be built with the same sanitizer opts. CC=clang-16 CXX=clang++-16 FUZZ_FLAGS=-fsanitize=address,fuzzer -fno-omit-frame-pointer FUZZ_LIBS=-L/usr/lib/llvm-16/lib -lFuzzer CFLAGS=-D_GNU_SOURCE=1 -O2 -g -Wall -Wextra -Wno-unused-parameter -Wno-exceptions -Wno-deprecated -I ../../.. CXXFLAGS=$(CFLAGS) $(FUZZ_FLAGS) LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g LIBS=-lssh -lopenbsd-compat -lmd -lcrypto -lfido2 -lcbor $(FUZZ_LIBS) SK_NULL_OBJS=ssh-sk-null.o COMMON_DEPS=../../../libssh.a TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz authkeys_fuzz sshsig_fuzz \ sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz \ mkcorpus_sntrup761 sntrup761_enc_fuzz sntrup761_dec_fuzz all: $(TARGETS) .cc.o: $(CXX) $(CXXFLAGS) -c $< -o $@ .c.o: $(CC) $(CFLAGS) -c $< -o $@ pubkey_fuzz: pubkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ pubkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) sig_fuzz: sig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ sig_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) authopt_fuzz: authopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ authopt_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) authkeys_fuzz: authkeys_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ authkeys_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o ../../../auth2-pubkeyfile.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) sshsig_fuzz: sshsig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ sshsig_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) sshsigopt_fuzz: sshsigopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ sshsigopt_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) privkey_fuzz: privkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ privkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) kex_fuzz: kex_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) $(CXX) -o $@ kex_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) -lz agent_fuzz: agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(COMMON_DEPS) $(CXX) -o $@ agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) -lz agent_fuzz_helper.o: agent_fuzz_helper.c ../../../ssh-agent.c sk-dummy.o: ../sk-dummy/sk-dummy.c $(CC) $(CFLAGS) -c -o $@ ../sk-dummy/sk-dummy.c -DSK_DUMMY_INTEGRATE=1 $(LDFLAGS) $(FUZZ_FLAGS) mkcorpus_sntrup761: mkcorpus_sntrup761.o $(CC) -o $@ mkcorpus_sntrup761.o $(LDFLAGS) -lcrypto sntrup761_dec_fuzz: sntrup761_dec_fuzz.o $(CXX) -o $@ sntrup761_dec_fuzz.o $(LDFLAGS) $(FUZZ_FLAGS) $(FUZZ_LIBS) -lcrypto sntrup761_enc_fuzz: sntrup761_enc_fuzz.o $(CXX) -o $@ sntrup761_enc_fuzz.o $(LDFLAGS) $(FUZZ_FLAGS) $(FUZZ_LIBS) -lcrypto clean: -rm -f *.o $(TARGETS) cleandir: clean openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0021100xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness/README010064400017500001750000000001121477541562300174550ustar00djmdjmThis directory contains fuzzing harnesses for use with clang's libfuzzer. openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/agent_fuzz.cc100644 001750 001750 0000000003614775415623 0022703xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness/agent_fuzz.cc010064400017500001750000000004001477541562300212600ustar00djmdjm// cc_fuzz_target test for ssh-agent. extern "C" { #include #include extern void test_one(const uint8_t* s, size_t slen); int LLVMFuzzerTestOneInput(const uint8_t* s, size_t slen) { test_one(s, slen); return 0; } } // extern openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/agent_fuzz_helper.c100644 001750 001750 0000000003614775415623 0024077xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness/agent_fuzz_helper.c010064400017500001750000000071721477541562300224710ustar00djmdjm#include "fixed-keys.h" #include #define main(ac, av) xxxmain(ac, av) #include "../../../ssh-agent.c" void test_one(const uint8_t* s, size_t slen); static int devnull_or_die(void) { int fd; if ((fd = open("/dev/null", O_RDWR)) == -1) { error_f("open /dev/null: %s", strerror(errno)); abort(); } return fd; } static struct sshkey * pubkey_or_die(const char *s) { char *tmp, *cp; struct sshkey *pubkey; int r; tmp = cp = xstrdup(s); if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL) abort(); if ((r = sshkey_read(pubkey, &cp)) != 0) { error_fr(r, "parse"); abort(); } free(tmp); return pubkey; } static struct sshkey * privkey_or_die(const char *s) { int r; struct sshbuf *b; struct sshkey *privkey; if ((b = sshbuf_from(s, strlen(s))) == NULL) { error_f("sshbuf_from failed"); abort(); } if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) { error_fr(r, "parse"); abort(); } sshbuf_free(b); return privkey; } static void add_key(const char *privkey, const char *certpath) { Identity *id; int r; struct sshkey *cert; id = xcalloc(1, sizeof(Identity)); TAILQ_INSERT_TAIL(&idtab->idlist, id, next); idtab->nentries++; id->key = privkey_or_die(privkey); id->comment = xstrdup("rhododaktulos Eos"); if (sshkey_is_sk(id->key)) id->sk_provider = xstrdup("internal"); /* Now the cert too */ id = xcalloc(1, sizeof(Identity)); TAILQ_INSERT_TAIL(&idtab->idlist, id, next); idtab->nentries++; id->key = privkey_or_die(privkey); cert = pubkey_or_die(certpath); if ((r = sshkey_to_certified(id->key)) != 0) { error_fr(r, "sshkey_to_certified"); abort(); } if ((r = sshkey_cert_copy(cert, id->key)) != 0) { error_fr(r, "sshkey_cert_copy"); abort(); } sshkey_free(cert); id->comment = xstrdup("outis"); if (sshkey_is_sk(id->key)) id->sk_provider = xstrdup("internal"); } static void cleanup_idtab(void) { Identity *id; if (idtab == NULL) return; for (id = TAILQ_FIRST(&idtab->idlist); id; id = TAILQ_FIRST(&idtab->idlist)) { TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); } free(idtab); idtab = NULL; } static void reset_idtab(void) { cleanup_idtab(); idtab_init(); // Load keys. add_key(PRIV_RSA, CERT_RSA); add_key(PRIV_ECDSA, CERT_ECDSA); add_key(PRIV_ED25519, CERT_ED25519); add_key(PRIV_ECDSA_SK, CERT_ECDSA_SK); add_key(PRIV_ED25519_SK, CERT_ED25519_SK); } static void cleanup_sockettab(void) { u_int i; for (i = 0; i < sockets_alloc; i++) { if (sockets[i].type != AUTH_UNUSED) close_socket(sockets + i); } free(sockets); sockets = NULL; sockets_alloc = 0; } static void reset_sockettab(int devnull) { int fd; cleanup_sockettab(); if ((fd = dup(devnull)) == -1) { error_f("dup: %s", strerror(errno)); abort(); } new_socket(AUTH_CONNECTION, fd); assert(sockets[0].type == AUTH_CONNECTION); assert(sockets[0].fd == fd); } #define MAX_MESSAGES 256 void test_one(const uint8_t* s, size_t slen) { static int devnull = -1; size_t i, olen, nlen; if (devnull == -1) { log_init(__progname, SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); devnull = devnull_or_die(); allowed_providers = xstrdup(""); websafe_allowlist = xstrdup("*"); setenv("DISPLAY", "", 1); /* ban askpass */ } reset_idtab(); reset_sockettab(devnull); (void)sshbuf_put(sockets[0].input, s, slen); for (i = 0; i < MAX_MESSAGES; i++) { olen = sshbuf_len(sockets[0].input); process_message(0); nlen = sshbuf_len(sockets[0].input); if (nlen == 0 || nlen == olen) break; } cleanup_idtab(); cleanup_sockettab(); } int pkcs11_make_cert(const struct sshkey *priv, const struct sshkey *certpub, struct sshkey **certprivp) { return -1; /* XXX */ } openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/authkeys_fuzz.cc100644 001750 001750 0000000003614775415623 0023442xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness/authkeys_fuzz.cc010064400017500001750000000047671477541562300220430ustar00djmdjm#include #include #include #include #include #include #include extern "C" { #include "hostfile.h" #include "auth.h" #include "auth-options.h" #include "sshkey.h" // testdata/id_ed25519.pub and testdata/id_ed25519-cert.pub const char *pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD"; const char *certtext = "ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub"; // stubs void auth_debug_add(const char *fmt,...) { } void auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) { } int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { char *tmp, *o, *cp = (char *)malloc(size + 1 + strlen(pubkey) + 1); struct sshauthopt *opts = NULL; struct passwd *pw = getpwuid(getuid()); static struct sshkey *key, *cert; if (key == NULL) { if ((key = sshkey_new(KEY_UNSPEC)) == NULL || (cert = sshkey_new(KEY_UNSPEC)) == NULL) abort(); if ((o = tmp = strdup(pubkey)) == NULL || sshkey_read(key, &tmp) != 0) abort(); free(o); if ((o = tmp = strdup(certtext)) == NULL || sshkey_read(cert, &tmp) != 0) abort(); free(o); } if (cp == NULL || pw == NULL || key == NULL || cert == NULL) abort(); // Cleanup whitespace at input EOL. for (; size > 0 && strchr(" \t\r\n", data[size - 1]) != NULL; size--) ; // Append a pubkey that will match. memcpy(cp, data, size); cp[size] = ' '; memcpy(cp + size + 1, pubkey, strlen(pubkey) + 1); // Try key. if ((tmp = strdup(cp)) == NULL) abort(); (void) auth_check_authkey_line(pw, key, tmp, "127.0.0.1", "localhost", "fuzz", &opts); free(tmp); sshauthopt_free(opts); // Try cert. if ((tmp = strdup(cp)) == NULL) abort(); (void) auth_check_authkey_line(pw, cert, tmp, "127.0.0.1", "localhost", "fuzz", &opts); free(tmp); sshauthopt_free(opts); free(cp); return 0; } } // extern "C" openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/authopt_fuzz.cc100644 001750 001750 0000000003614775415623 0023271xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness/authopt_fuzz.cc010064400017500001750000000012171477541562300216550ustar00djmdjm#include #include #include #include #include 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" openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/fixed-keys.h100644 001750 001750 0000000003614775415623 0022441xustar0030 atime=1744182234.713695919 openssh-10.0p1/regress/misc/fuzz-harness/fixed-keys.h010064400017500001750000000307031477541562300210270ustar00djmdjm/* * Some keys used by fuzzers */ #define PRIV_RSA \ "-----BEGIN OPENSSH PRIVATE KEY-----\n"\ "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n"\ "NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5\n"\ "thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU\n"\ "d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW\n"\ "3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt\n"\ "iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I\n"\ "8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK\n"\ "6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm\n"\ "DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml\n"\ "MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T\n"\ "t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v\n"\ "/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM\n"\ "SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB\n"\ "ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx\n"\ "jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4\n"\ "JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg\n"\ "YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh\n"\ "VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h\n"\ "Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU\n"\ "0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt\n"\ "7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+\n"\ "ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9\n"\ "jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl\n"\ "t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW\n"\ "I79JhtGkh+GtcnkEfwAAAAAB\n"\ "-----END OPENSSH PRIVATE KEY-----\n" #define PUB_RSA \ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT" #define CERT_RSA \ "ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub" #define PRIV_DSA \ "-----BEGIN OPENSSH PRIVATE KEY-----\n"\ "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH\n"\ "NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm\n"\ "xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA\n"\ "3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q\n"\ "d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP\n"\ "44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW\n"\ "THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O\n"\ "kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ\n"\ "ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs\n"\ "h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT\n"\ "R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B\n"\ "mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r\n"\ "VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS\n"\ "4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb\n"\ "oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc\n"\ "WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL\n"\ "ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ\n"\ "z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE\n"\ "lq8AAAAAAQI=\n"\ "-----END OPENSSH PRIVATE KEY-----\n" #define PUB_DSA \ "ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8=" #define CERT_DSA \ "ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub" #define PRIV_ECDSA \ "-----BEGIN OPENSSH PRIVATE KEY-----\n"\ "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS\n"\ "1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ\n"\ "6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW\n"\ "6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N\n"\ "onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ\n"\ "sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc=\n"\ "-----END OPENSSH PRIVATE KEY-----\n" #define PUB_ECDSA \ "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs=" #define CERT_ECDSA \ "ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub" #define PRIV_ED25519 \ "-----BEGIN OPENSSH PRIVATE KEY-----\n"\ "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n"\ "QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/\n"\ "fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw\n"\ "AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP\n"\ "Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF\n"\ "-----END OPENSSH PRIVATE KEY-----\n" #define PUB_ED25519 \ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD" #define CERT_ED25519 \ "ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub" #define PRIV_ECDSA_SK \ "-----BEGIN OPENSSH PRIVATE KEY-----\n"\ "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2\n"\ "RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1\n"\ "VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB\n"\ "X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv\n"\ "cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm\n"\ "wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt\n"\ "LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn\n"\ "dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn\n"\ "QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW\n"\ "hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ\n"\ "UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ\n"\ "IDBAUG\n"\ "-----END OPENSSH PRIVATE KEY-----\n" #define PUB_ECDSA_SK \ "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg==" #define CERT_ECDSA_SK \ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E" #define PRIV_ED25519_SK \ "-----BEGIN OPENSSH PRIVATE KEY-----\n"\ "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2\n"\ "gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je\n"\ "RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2\n"\ "9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS\n"\ "xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq\n"\ "mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg==\n"\ "-----END OPENSSH PRIVATE KEY-----\n" #define PUB_ED25519_SK \ "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo=" #define CERT_ED25519_SK \ "sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA==" openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/kex_fuzz.cc100644 001750 001750 0000000003614775415623 0022374xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/kex_fuzz.cc010064400017500001750000000267311477541562300207700ustar00djmdjm// libfuzzer driver for key exchange fuzzing. #include #include #include #include #include extern "C" { #include "includes.h" #include "ssherr.h" #include "ssh_api.h" #include "sshbuf.h" #include "packet.h" #include "myproposal.h" #include "xmalloc.h" #include "authfile.h" #include "log.h" #include "fixed-keys.h" // Define if you want to generate traces. /* #define STANDALONE 1 */ static int prepare_key(struct shared_state *st, int keytype, int bits); struct shared_state { size_t nkeys; struct sshkey **privkeys, **pubkeys; }; struct test_state { struct sshbuf *smsgs, *cmsgs; /* output, for standalone mode */ struct sshbuf *sin, *cin; /* input; setup per-test in do_kex_with_key */ struct sshbuf *s_template, *c_template; /* main copy of input */ }; static int do_send_and_receive(struct ssh *from, struct ssh *to, struct sshbuf *store, int clobber, size_t *n) { u_char type; size_t len; const u_char *buf; int r; for (*n = 0;; (*n)++) { if ((r = ssh_packet_next(from, &type)) != 0) { debug_fr(r, "ssh_packet_next"); return r; } if (type != 0) return 0; buf = ssh_output_ptr(from, &len); debug_f("%zu%s", len, clobber ? " ignore" : ""); if (len == 0) return 0; if ((r = ssh_output_consume(from, len)) != 0) { debug_fr(r, "ssh_output_consume"); return r; } if (store != NULL && (r = sshbuf_put(store, buf, len)) != 0) { debug_fr(r, "sshbuf_put"); return r; } if (!clobber && (r = ssh_input_append(to, buf, len)) != 0) { debug_fr(r, "ssh_input_append"); return r; } } } static int run_kex(struct test_state *ts, struct ssh *client, struct ssh *server) { int r = 0; size_t cn, sn; /* If fuzzing, replace server/client input */ if (ts->sin != NULL) { if ((r = ssh_input_append(server, sshbuf_ptr(ts->sin), sshbuf_len(ts->sin))) != 0) { error_fr(r, "ssh_input_append"); return r; } sshbuf_reset(ts->sin); } if (ts->cin != NULL) { if ((r = ssh_input_append(client, sshbuf_ptr(ts->cin), sshbuf_len(ts->cin))) != 0) { error_fr(r, "ssh_input_append"); return r; } sshbuf_reset(ts->cin); } while (!server->kex->done || !client->kex->done) { cn = sn = 0; debug_f("S:"); if ((r = do_send_and_receive(server, client, ts->smsgs, ts->cin != NULL, &sn)) != 0) { debug_fr(r, "S->C"); break; } debug_f("C:"); if ((r = do_send_and_receive(client, server, ts->cmsgs, ts->sin != NULL, &cn)) != 0) { debug_fr(r, "C->S"); break; } if (cn == 0 && sn == 0) { debug_f("kex stalled"); r = SSH_ERR_PROTOCOL_ERROR; break; } } debug_fr(r, "done"); return r; } static void store_key(struct shared_state *st, struct sshkey *pubkey, struct sshkey *privkey) { if (st == NULL || pubkey->type < 0 || pubkey->type > INT_MAX || privkey->type != pubkey->type || ((size_t)pubkey->type < st->nkeys && st->pubkeys[pubkey->type] != NULL)) abort(); if ((size_t)pubkey->type >= st->nkeys) { st->pubkeys = (struct sshkey **)xrecallocarray(st->pubkeys, st->nkeys, pubkey->type + 1, sizeof(*st->pubkeys)); st->privkeys = (struct sshkey **)xrecallocarray(st->privkeys, st->nkeys, privkey->type + 1, sizeof(*st->privkeys)); st->nkeys = privkey->type + 1; } debug_f("store %s at %d", sshkey_ssh_name(pubkey), pubkey->type); st->pubkeys[pubkey->type] = pubkey; st->privkeys[privkey->type] = privkey; } static int prepare_keys(struct shared_state *st) { if (prepare_key(st, KEY_RSA, 2048) != 0 || prepare_key(st, KEY_ECDSA, 256) != 0 || prepare_key(st, KEY_ED25519, 256) != 0) { error_f("key prepare failed"); return -1; } return 0; } static struct sshkey * get_pubkey(struct shared_state *st, int keytype) { if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys || st->pubkeys == NULL || st->pubkeys[keytype] == NULL) abort(); return st->pubkeys[keytype]; } static struct sshkey * get_privkey(struct shared_state *st, int keytype) { if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys || st->privkeys == NULL || st->privkeys[keytype] == NULL) abort(); return st->privkeys[keytype]; } static int do_kex_with_key(struct shared_state *st, struct test_state *ts, const char *kex, int keytype) { struct ssh *client = NULL, *server = NULL; struct sshkey *privkey = NULL, *pubkey = NULL; struct sshbuf *state = NULL; struct kex_params kex_params; const char *ccp, *proposal[PROPOSAL_MAX] = { KEX_CLIENT }; char *myproposal[PROPOSAL_MAX] = {0}, *keyname = NULL; int i, r; ts->cin = ts->sin = NULL; if (ts->c_template != NULL && (ts->cin = sshbuf_fromb(ts->c_template)) == NULL) abort(); if (ts->s_template != NULL && (ts->sin = sshbuf_fromb(ts->s_template)) == NULL) abort(); pubkey = get_pubkey(st, keytype); privkey = get_privkey(st, keytype); keyname = xstrdup(sshkey_ssh_name(privkey)); if (ts->cin != NULL) { debug_f("%s %s clobber client %zu", kex, keyname, sshbuf_len(ts->cin)); } else if (ts->sin != NULL) { debug_f("%s %s clobber server %zu", kex, keyname, sshbuf_len(ts->sin)); } else debug_f("%s %s noclobber", kex, keyname); for (i = 0; i < PROPOSAL_MAX; i++) { ccp = proposal[i]; #ifdef CIPHER_NONE_AVAIL if (i == PROPOSAL_ENC_ALGS_CTOS || i == PROPOSAL_ENC_ALGS_STOC) ccp = "none"; #endif if (i == PROPOSAL_SERVER_HOST_KEY_ALGS) ccp = keyname; else if (i == PROPOSAL_KEX_ALGS && kex != NULL) ccp = kex; if ((myproposal[i] = strdup(ccp)) == NULL) { error_f("strdup prop %d", i); goto fail; } } memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); if ((r = ssh_init(&client, 0, &kex_params)) != 0) { error_fr(r, "init client"); goto fail; } if ((r = ssh_init(&server, 1, &kex_params)) != 0) { error_fr(r, "init server"); goto fail; } if ((r = ssh_add_hostkey(server, privkey)) != 0 || (r = ssh_add_hostkey(client, pubkey)) != 0) { error_fr(r, "add hostkeys"); goto fail; } if ((r = run_kex(ts, client, server)) != 0) { error_fr(r, "kex"); goto fail; } /* XXX rekex, set_state, etc */ fail: for (i = 0; i < PROPOSAL_MAX; i++) free(myproposal[i]); sshbuf_free(ts->sin); sshbuf_free(ts->cin); sshbuf_free(state); ssh_free(client); ssh_free(server); free(keyname); return r; } static int prepare_key(struct shared_state *st, int kt, int bits) { const char *pubstr = NULL; const char *privstr = NULL; char *tmp, *cp; struct sshkey *privkey = NULL, *pubkey = NULL; struct sshbuf *b = NULL; int r; switch (kt) { case KEY_RSA: pubstr = PUB_RSA; privstr = PRIV_RSA; break; case KEY_ECDSA: pubstr = PUB_ECDSA; privstr = PRIV_ECDSA; break; case KEY_ED25519: pubstr = PUB_ED25519; privstr = PRIV_ED25519; break; default: abort(); } if ((b = sshbuf_from(privstr, strlen(privstr))) == NULL) abort(); if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) { error_fr(r, "priv %d", kt); abort(); } sshbuf_free(b); tmp = cp = xstrdup(pubstr); if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL) abort(); if ((r = sshkey_read(pubkey, &cp)) != 0) { error_fr(r, "pub %d", kt); abort(); } free(tmp); store_key(st, pubkey, privkey); return 0; } #if defined(STANDALONE) #if 0 /* use this if generating new keys to embed above */ static int prepare_key(struct shared_state *st, int keytype, int bits) { struct sshkey *privkey = NULL, *pubkey = NULL; int r; if ((r = sshkey_generate(keytype, bits, &privkey)) != 0) { error_fr(r, "generate"); abort(); } if ((r = sshkey_from_private(privkey, &pubkey)) != 0) { error_fr(r, "make pubkey"); abort(); } store_key(st, pubkey, privkey); return 0; } #endif int main(void) { static struct shared_state *st; struct test_state *ts; const int keytypes[] = { KEY_RSA, KEY_ECDSA, KEY_ED25519, -1 }; static const char * const kextypes[] = { "sntrup761x25519-sha512@openssh.com", "curve25519-sha256@libssh.org", "ecdh-sha2-nistp256", "diffie-hellman-group1-sha1", "diffie-hellman-group-exchange-sha1", NULL, }; int i, j; char *path; FILE *f; log_init("kex_fuzz", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); if (st == NULL) { st = (struct shared_state *)xcalloc(1, sizeof(*st)); prepare_keys(st); } /* Run each kex method for each key and save client/server packets */ for (i = 0; keytypes[i] != -1; i++) { for (j = 0; kextypes[j] != NULL; j++) { ts = (struct test_state *)xcalloc(1, sizeof(*ts)); ts->smsgs = sshbuf_new(); ts->cmsgs = sshbuf_new(); do_kex_with_key(st, ts, kextypes[j], keytypes[i]); xasprintf(&path, "S2C-%s-%s", kextypes[j], sshkey_type(st->pubkeys[keytypes[i]])); debug_f("%s", path); if ((f = fopen(path, "wb+")) == NULL) abort(); if (fwrite(sshbuf_ptr(ts->smsgs), 1, sshbuf_len(ts->smsgs), f) != sshbuf_len(ts->smsgs)) abort(); fclose(f); free(path); //sshbuf_dump(ts->smsgs, stderr); xasprintf(&path, "C2S-%s-%s", kextypes[j], sshkey_type(st->pubkeys[keytypes[i]])); debug_f("%s", path); if ((f = fopen(path, "wb+")) == NULL) abort(); if (fwrite(sshbuf_ptr(ts->cmsgs), 1, sshbuf_len(ts->cmsgs), f) != sshbuf_len(ts->cmsgs)) abort(); fclose(f); free(path); //sshbuf_dump(ts->cmsgs, stderr); sshbuf_free(ts->smsgs); sshbuf_free(ts->cmsgs); free(ts); } } for (i = 0; keytypes[i] != -1; i++) { xasprintf(&path, "%s.priv", sshkey_type(st->privkeys[keytypes[i]])); debug_f("%s", path); if (sshkey_save_private(st->privkeys[keytypes[i]], path, "", "", SSHKEY_PRIVATE_OPENSSH, NULL, 0) != 0) abort(); free(path); xasprintf(&path, "%s.pub", sshkey_type(st->pubkeys[keytypes[i]])); debug_f("%s", path); if (sshkey_save_public(st->pubkeys[keytypes[i]], path, "") != 0) abort(); free(path); } } #else /* !STANDALONE */ static void do_kex(struct shared_state *st, struct test_state *ts, const char *kex) { do_kex_with_key(st, ts, kex, KEY_RSA); do_kex_with_key(st, ts, kex, KEY_ECDSA); do_kex_with_key(st, ts, kex, KEY_ED25519); } static void kex_tests(struct shared_state *st, struct test_state *ts) { do_kex(st, ts, "sntrup761x25519-sha512@openssh.com"); do_kex(st, ts, "curve25519-sha256@libssh.org"); do_kex(st, ts, "ecdh-sha2-nistp256"); do_kex(st, ts, "diffie-hellman-group1-sha1"); do_kex(st, ts, "diffie-hellman-group-exchange-sha1"); } int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static struct shared_state *st; struct test_state *ts; u_char crbuf[SSH_MAX_PRE_BANNER_LINES * 4]; u_char zbuf[4096] = {0}; static LogLevel loglevel = SYSLOG_LEVEL_INFO; if (st == NULL) { if (getenv("DEBUG") != NULL || getenv("KEX_FUZZ_DEBUG") != NULL) loglevel = SYSLOG_LEVEL_DEBUG3; log_init("kex_fuzz", loglevel, SYSLOG_FACILITY_AUTH, 1); st = (struct shared_state *)xcalloc(1, sizeof(*st)); prepare_keys(st); } /* Ensure that we can complete (fail) banner exchange at least */ memset(crbuf, '\n', sizeof(crbuf)); ts = (struct test_state *)xcalloc(1, sizeof(*ts)); if ((ts->s_template = sshbuf_new()) == NULL || sshbuf_put(ts->s_template, data, size) != 0 || sshbuf_put(ts->s_template, crbuf, sizeof(crbuf)) != 0 || sshbuf_put(ts->s_template, zbuf, sizeof(zbuf)) != 0) abort(); kex_tests(st, ts); sshbuf_free(ts->s_template); free(ts); ts = (struct test_state *)xcalloc(1, sizeof(*ts)); if ((ts->c_template = sshbuf_new()) == NULL || sshbuf_put(ts->c_template, data, size) != 0 || sshbuf_put(ts->c_template, crbuf, sizeof(crbuf)) != 0 || sshbuf_put(ts->c_template, zbuf, sizeof(zbuf)) != 0) abort(); kex_tests(st, ts); sshbuf_free(ts->c_template); free(ts); return 0; } #endif /* STANDALONE */ } /* extern "C" */ openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/mkcorpus_sntrup761.c100644 001750 001750 0000000003614775415623 0024100xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/mkcorpus_sntrup761.c010064400017500001750000000042241477541562300224650ustar00djmdjm// Makes basic seed corpora for other fuzzers // // Will write to ./sntrup761_pubkey_corpus (for sntrup761_enc_fuzz) and // to ./sntrup761_ciphertext_corpus (for sntrup761_dec_fuzz) #include #include #include #include #include #include #include #include #include #include "crypto_api.h" #include "hash.c" #undef randombytes #define USE_SNTRUP761X25519 1 void randombytes(unsigned char *ptr, size_t l); volatile crypto_int16 crypto_int16_optblocker = 0; volatile crypto_int32 crypto_int32_optblocker = 0; volatile crypto_int64 crypto_int64_optblocker = 0; #include "sntrup761.c" #define NSEEDS 1000 static int real_random; void randombytes(unsigned char *ptr, size_t l) { if (real_random) arc4random_buf(ptr, l); else memset(ptr, 0, l); } void write_blob(const char *path, int n, const char *suffix, const void *ptr, size_t l) { char name[256]; FILE *f; snprintf(name, sizeof(name), "%s/%06d.%s", path, n, suffix); if ((f = fopen(name, "wb+")) == NULL) err(1, "fopen %s", name); if (fwrite(ptr, l, 1, f) != 1) err(1, "write %s", name); fclose(f); } int main(void) { int i; unsigned char pk[crypto_kem_sntrup761_PUBLICKEYBYTES]; unsigned char sk[crypto_kem_sntrup761_SECRETKEYBYTES]; unsigned char ciphertext[crypto_kem_sntrup761_CIPHERTEXTBYTES]; unsigned char secret[crypto_kem_sntrup761_BYTES]; if (mkdir("sntrup761_pubkey_corpus", 0777) != 0 && errno != EEXIST) err(1, "mkdir sntrup761_pubkey_corpus"); if (mkdir("sntrup761_ciphertext_corpus", 0777) != 0 && errno != EEXIST) err(1, "mkdir sntrup761_ciphertext_corpus"); fprintf(stderr, "making: "); for (i = 0; i < NSEEDS; i++) { real_random = i != 0; if (crypto_kem_sntrup761_keypair(pk, sk) != 0) errx(1, "crypto_kem_sntrup761_keypair failed"); write_blob("sntrup761_pubkey_corpus", i, "pk", pk, sizeof(pk)); if (crypto_kem_sntrup761_enc(ciphertext, secret, pk) != 0) errx(1, "crypto_kem_sntrup761_enc failed"); write_blob("sntrup761_ciphertext_corpus", i, "ct", ciphertext, sizeof(ciphertext)); if (i % 20 == 0) fprintf(stderr, "."); } fprintf(stderr, "\n"); return 0; } openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/privkey_fuzz.cc100644 001750 001750 0000000003614775415623 0023276xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/privkey_fuzz.cc010064400017500001750000000005561477541562300216670ustar00djmdjm#include #include #include extern "C" { #include "sshkey.h" #include "sshbuf.h" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { struct sshkey *k = NULL; struct sshbuf *b = sshbuf_from(data, size); int r = sshkey_private_deserialize(b, &k); if (r == 0) sshkey_free(k); sshbuf_free(b); return 0; } } // extern openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/pubkey_fuzz.cc100644 001750 001750 0000000003614775415623 0023104xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/pubkey_fuzz.cc010064400017500001750000000004331477541562300214670ustar00djmdjm#include #include #include 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 openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/sig_fuzz.cc100644 001750 001750 0000000003614775415623 0022367xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/sig_fuzz.cc010064400017500001750000000034701477541562300207560ustar00djmdjm// cc_fuzz_target test for public key parsing. #include #include #include #include #include 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 *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(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 openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/sntrup761_dec_fuzz.cc100644 001750 001750 0000000003614775415623 0024211xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/sntrup761_dec_fuzz.cc010064400017500001750000000033441477541562300226000ustar00djmdjm// Basic fuzz test for depcapsulate operation, #include #include #include #include #include #include #include extern "C" { #include "crypto_api.h" #include "hash.c" #undef randombytes #define USE_SNTRUP761X25519 1 #ifdef SNTRUP761_NO_ASM # undef __GNUC__ #endif void randombytes(unsigned char *ptr, size_t l); volatile crypto_int16 crypto_int16_optblocker = 0; volatile crypto_int32 crypto_int32_optblocker = 0; volatile crypto_int64 crypto_int64_optblocker = 0; #include "sntrup761.c" static int real_random; void randombytes(unsigned char *ptr, size_t l) { if (real_random) arc4random_buf(ptr, l); else memset(ptr, 0, l); } void privkeys(unsigned char *zero_sk, unsigned char *rnd_sk) { unsigned char pk[crypto_kem_sntrup761_PUBLICKEYBYTES]; real_random = 0; if (crypto_kem_sntrup761_keypair(pk, zero_sk) != 0) errx(1, "crypto_kem_sntrup761_keypair failed"); real_random = 1; if (crypto_kem_sntrup761_keypair(pk, rnd_sk) != 0) errx(1, "crypto_kem_sntrup761_keypair failed"); } int LLVMFuzzerTestOneInput(const uint8_t* input, size_t len) { static bool once; static unsigned char zero_sk[crypto_kem_sntrup761_SECRETKEYBYTES]; static unsigned char rnd_sk[crypto_kem_sntrup761_SECRETKEYBYTES]; unsigned char ciphertext[crypto_kem_sntrup761_CIPHERTEXTBYTES]; unsigned char secret[crypto_kem_sntrup761_BYTES]; if (!once) { privkeys(zero_sk, rnd_sk); once = true; } memset(&ciphertext, 0, sizeof(ciphertext)); if (len > sizeof(ciphertext)) { len = sizeof(ciphertext); } memcpy(ciphertext, input, len); (void)crypto_kem_sntrup761_dec(secret, ciphertext, zero_sk); (void)crypto_kem_sntrup761_dec(secret, ciphertext, rnd_sk); return 0; } } // extern openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/sntrup761_enc_fuzz.cc100644 001750 001750 0000000003614775415623 0024223xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/sntrup761_enc_fuzz.cc010064400017500001750000000023121477541562300226040ustar00djmdjm// Basic fuzz test for encapsulate operation. #include #include #include #include #include #include #include extern "C" { #include "crypto_api.h" #include "hash.c" #undef randombytes #define USE_SNTRUP761X25519 1 #ifdef SNTRUP761_NO_ASM # undef __GNUC__ #endif void randombytes(unsigned char *ptr, size_t l); volatile crypto_int16 crypto_int16_optblocker = 0; volatile crypto_int32 crypto_int32_optblocker = 0; volatile crypto_int64 crypto_int64_optblocker = 0; #include "sntrup761.c" static int real_random; void randombytes(unsigned char *ptr, size_t l) { if (real_random) arc4random_buf(ptr, l); else memset(ptr, 0, l); } int LLVMFuzzerTestOneInput(const uint8_t* input, size_t len) { unsigned char pk[crypto_kem_sntrup761_PUBLICKEYBYTES]; unsigned char ciphertext[crypto_kem_sntrup761_CIPHERTEXTBYTES]; unsigned char secret[crypto_kem_sntrup761_BYTES]; memset(&pk, 0, sizeof(pk)); if (len > sizeof(pk)) { len = sizeof(pk); } memcpy(pk, input, len); real_random = 0; (void)crypto_kem_sntrup761_enc(ciphertext, secret, pk); real_random = 1; (void)crypto_kem_sntrup761_enc(ciphertext, secret, pk); return 0; } } // extern openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/ssh-sk-null.cc100644 001750 001750 0000000003614775415623 0022707xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/ssh-sk-null.cc010064400017500001750000000030561477541562300212760ustar00djmdjm/* $OpenBSD$ */ /* * Copyright (c) 2019 Google LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ extern "C" { #include "includes.h" #include #include "ssherr.h" #include "ssh-sk.h" int sshsk_enroll(int type, const char *provider_path, const char *device, const char *application, const char *userid, uint8_t flags, const char *pin, struct sshbuf *challenge_buf, struct sshkey **keyp, struct sshbuf *attest) { return SSH_ERR_FEATURE_UNSUPPORTED; } int sshsk_sign(const char *provider_path, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat, const char *pin) { return SSH_ERR_FEATURE_UNSUPPORTED; } int sshsk_load_resident(const char *provider_path, const char *device, const char *pin, u_int flags, struct sshsk_resident_key ***srksp, size_t *nsrksp) { return SSH_ERR_FEATURE_UNSUPPORTED; } }; openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/sshsig_fuzz.cc100644 001750 001750 0000000003614775415623 0023105xustar0030 atime=1744182234.714672566 openssh-10.0p1/regress/misc/fuzz-harness/sshsig_fuzz.cc010064400017500001750000000016661477541562300215010ustar00djmdjm// cc_fuzz_target test for sshsig verification. #include #include #include #include #include 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 openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/sshsigopt_fuzz.cc100644 001750 001750 0000000003614775415623 0023630xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/sshsigopt_fuzz.cc010064400017500001750000000007511477541562300222160ustar00djmdjm#include #include #include #include #include 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" openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/testdata040755 001750 001750 0000000003614775415623 0021762xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata004075500017500001750000000000001477541562300203405ustar00djmdjmopenssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/README100644 001750 001750 0000000003614775415623 0022711xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/README010064400017500001750000000004041477541562300212720ustar00djmdjmThis is preparatory data for fuzzing testing including scripts and test keys, corresponding to ../fixed-keys that are used in the fuzz tests and consequent fuzzing seed corpora. They should not be changed unless the affected seed corpora are also regenerated. openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/create-agent-corpus.sh100755 001750 001750 0000000003614775415623 0026240xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh010075500017500001750000000013441477541562300246250ustar00djmdjm#!/bin/sh # Exercise ssh-agent to generate fuzzing corpus # XXX assumes agent hacked up with sk-dummy.o and ssh-sk.o linked directly # and dumping of e->request for each message. set -xe SSH_AUTH_SOCK=$PWD/sock rm -f agent-[0-9]* $SSH_AUTH_SOCK export SSH_AUTH_SOCK ../../../../ssh-agent -D -a $SSH_AUTH_SOCK & sleep 1 AGENT_PID=$! trap "kill $AGENT_PID" EXIT PRIV="id_dsa id_ecdsa id_ecdsa_sk id_ed25519 id_ed25519_sk id_rsa" # add keys ssh-add $PRIV # sign ssh-add -T *.pub # list ssh-add -l # remove individually ssh-add -d $PRIV # re-add with constraints ssh-add -c -t 3h $PRIV # delete all ssh-add -D # attempt to add a PKCS#11 token ssh-add -s /fake || : # attempt to delete PKCS#11 ssh-add -e /fake || : ssh-add -L openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_dsa100644 001750 001750 0000000003614775415623 0023177xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_dsa010064400017500001750000000025211477541562300215620ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA 3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP 44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS 4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE lq8AAAAAAQI= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_dsa-cert.pub100644 001750 001750 0000000003614775415623 0024717xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub010064400017500001750000000022151477541562300233020ustar00djmdjmssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_dsa.pub100644 001750 001750 0000000003614775415623 0023764xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_dsa.pub010064400017500001750000000011151477541562300223450ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8= openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ecdsa100644 001750 001750 0000000003614775415623 0023507xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ecdsa010064400017500001750000000007541477541562300221000ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS 1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ 6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW 6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ecdsa-cert.pub100644 001750 001750 0000000003614775415623 0025227xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub010064400017500001750000000013431477541562300236130ustar00djmdjmecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ecdsa.pub100644 001750 001750 0000000003614775415623 0024274xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ecdsa.pub010064400017500001750000000002411477541562300226540ustar00djmdjmecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs= openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ecdsa_sk100644 001750 001750 0000000003614775415623 0024204xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk010064400017500001750000000015321477541562300225700ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1 VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ IDBAUG -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ecdsa_sk-cert.pub100644 001750 001750 0000000003614775415623 0025724xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub010064400017500001750000000014011477541562300243030ustar00djmdjmsk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E djm@djm.syd.corp.google.com openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ecdsa_sk.pub100644 001750 001750 0000000003614775415623 0024771xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub010064400017500001750000000003541477541562300233560ustar00djmdjmsk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg== djm@djm.syd.corp.google.com openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ed25519100644 001750 001750 0000000003614775415623 0023426xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ed25519010064400017500001750000000006031477541562300220100ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/ fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ed25519-cert.pub100644 001750 001750 0000000003614775415623 0025146xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub010064400017500001750000000012251477541562300235310ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ed25519.pub100644 001750 001750 0000000003614775415623 0024213xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ed25519.pub010064400017500001750000000001221477541562300225710ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ed25519_sk100644 001750 001750 0000000003614775415623 0024123xustar0030 atime=1744182234.715648402 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk010064400017500001750000000007601477541562300225110ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg== -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ed25519_sk-cert.pub100644 001750 001750 0000000003514775415623 0025642xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub010064400017500001750000000012651477541562300242320ustar00djmdjmsk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA== djm@djm.syd.corp.google.com openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_ed25519_sk.pub100644 001750 001750 0000000003514775415623 0024707xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub010064400017500001750000000002341477541562300232720ustar00djmdjmsk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo= djm@djm.syd.corp.google.com openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_rsa100644 001750 001750 0000000003514775415623 0023214xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_rsa010064400017500001750000000034071477541562300216040ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5 thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW 3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I 8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK 6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v /W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4 JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU 0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt 7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+ ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9 jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW I79JhtGkh+GtcnkEfwAAAAAB -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_rsa-cert.pub100644 001750 001750 0000000003514775415623 0024734xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub010064400017500001750000000016751477541562300233310ustar00djmdjmssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub openssh-10.0p1/regress/misc/fuzz-harness/testdata/PaxHeaders.10889/id_rsa.pub100644 001750 001750 0000000003514775415623 0024001xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/fuzz-harness/testdata/id_rsa.pub010064400017500001750000000005751477541562300223740ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT openssh-10.0p1/regress/misc/fuzz-harness/PaxHeaders.10889/watch-sntrup761.sh100755 001750 001750 0000000003514775415623 0023453xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/fuzz-harness/watch-sntrup761.sh010075500017500001750000000010601477541562300220340ustar00djmdjm#!/bin/sh set -e mkdir -p sntrup761_dec_fuzzing sntrup761_enc_fuzzing (cd sntrup761_enc_fuzzing ; ../sntrup761_enc_fuzz -jobs=48 ../sntrup761_pubkey_corpus &) (cd sntrup761_dec_fuzzing ; ../sntrup761_dec_fuzz -jobs=48 ../sntrup761_ciphertext_corpus &) while true ; do clear uptime echo echo "Findings" ls -1 sntrup761_dec_fuzzing sntrup761_enc_fuzzing | grep -v '^fuzz-.*log$' printf "\n\n" printf "ciphertext_corpus: " ; ls -1 sntrup761_ciphertext_corpus | wc -l printf " pubkey_corpus: "; ls -1 sntrup761_pubkey_corpus | wc -l sleep 10; done openssh-10.0p1/regress/misc/PaxHeaders.10889/sk-dummy040755 001750 001750 0000000003514775415623 0017257xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/sk-dummy004075500017500001750000000000001477541562300156365ustar00djmdjmopenssh-10.0p1/regress/misc/sk-dummy/PaxHeaders.10889/Makefile100644 001750 001750 0000000003514775415623 0020766xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/sk-dummy/Makefile010064400017500001750000000024271477541562300173570ustar00djmdjm# $OpenBSD: Makefile,v 1.3 2023/01/15 23:35:10 djm Exp $ .include .include 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 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 openssh-10.0p1/regress/misc/sk-dummy/PaxHeaders.10889/fatal.c100644 001750 001750 0000000003514775415623 0020561xustar0029 atime=1744182234.71662524 openssh-10.0p1/regress/misc/sk-dummy/fatal.c010064400017500001750000000007561477541562300171550ustar00djmdjm/* public domain */ #include "includes.h" #include #include #include #include #include "log.h" void sshfatal(const char *file, const char *func, int line, int showfunc, LogLevel level, const char *suffix, const char *fmt, ...) { va_list ap; if (showfunc) fprintf(stderr, "%s: ", func); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (suffix != NULL) fprintf(stderr, ": %s", suffix); fputc('\n', stderr); _exit(1); } openssh-10.0p1/regress/misc/sk-dummy/PaxHeaders.10889/sk-dummy.c100644 001750 001750 0000000003614775415623 0021241xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/misc/sk-dummy/sk-dummy.c010064400017500001750000000346441477541562300176370ustar00djmdjm/* * Copyright (c) 2019 Markus Friedl * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef HAVE_STDINT_H #include #endif #include #include #include #include #include #include "crypto_api.h" #include "sk-api.h" #ifdef WITH_OPENSSL #include #include #include #include #include #include #include #include /* Use OpenSSL SHA256 instead of libc */ #define SHA256Init(x) SHA256_Init(x) #define SHA256Update(x, y, z) SHA256_Update(x, y, z) #define SHA256Final(x, y) SHA256_Final(x, y) #define SHA2_CTX SHA256_CTX #elif defined(HAVE_SHA2_H) #include #endif /* WITH_OPENSSL */ /* #define SK_DEBUG 1 */ #if SSH_SK_VERSION_MAJOR != 0x000a0000 # error SK API has changed, sk-dummy.c needs an update #endif #ifdef SK_DUMMY_INTEGRATE # define sk_api_version ssh_sk_api_version # define sk_enroll ssh_sk_enroll # define sk_sign ssh_sk_sign # define sk_load_resident_keys ssh_sk_load_resident_keys #endif /* !SK_STANDALONE */ static void skdebug(const char *func, const char *fmt, ...) __attribute__((__format__ (printf, 2, 3))); static void skdebug(const char *func, const char *fmt, ...) { #if defined(SK_DEBUG) va_list ap; va_start(ap, fmt); fprintf(stderr, "sk-dummy %s: ", func); vfprintf(stderr, fmt, ap); fputc('\n', stderr); va_end(ap); #else (void)func; /* XXX */ (void)fmt; /* XXX */ #endif } uint32_t sk_api_version(void) { return SSH_SK_VERSION_MAJOR; } static int pack_key_ecdsa(struct sk_enroll_response *response) { #ifdef OPENSSL_HAS_ECC EC_KEY *key = NULL; const EC_GROUP *g; const EC_POINT *q; int ret = -1; long privlen; BIO *bio = NULL; char *privptr; response->public_key = NULL; response->public_key_len = 0; response->key_handle = NULL; response->key_handle_len = 0; if ((key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) { skdebug(__func__, "EC_KEY_new_by_curve_name"); goto out; } if (EC_KEY_generate_key(key) != 1) { skdebug(__func__, "EC_KEY_generate_key"); goto out; } EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE); if ((bio = BIO_new(BIO_s_mem())) == NULL || (g = EC_KEY_get0_group(key)) == NULL || (q = EC_KEY_get0_public_key(key)) == NULL) { skdebug(__func__, "couldn't get key parameters"); goto out; } response->public_key_len = EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); if (response->public_key_len == 0 || response->public_key_len > 2048) { skdebug(__func__, "bad pubkey length %zu", response->public_key_len); goto out; } if ((response->public_key = malloc(response->public_key_len)) == NULL) { skdebug(__func__, "malloc pubkey failed"); goto out; } if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, response->public_key, response->public_key_len, NULL) == 0) { skdebug(__func__, "EC_POINT_point2oct failed"); goto out; } /* Key handle contains PEM encoded private key */ if (!PEM_write_bio_ECPrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) { skdebug(__func__, "PEM_write_bio_ECPrivateKey failed"); goto out; } if ((privlen = BIO_get_mem_data(bio, &privptr)) <= 0) { skdebug(__func__, "BIO_get_mem_data failed"); goto out; } if ((response->key_handle = malloc(privlen)) == NULL) { skdebug(__func__, "malloc key_handle failed"); goto out; } response->key_handle_len = (size_t)privlen; memcpy(response->key_handle, privptr, response->key_handle_len); /* success */ ret = 0; out: if (ret != 0) { if (response->public_key != NULL) { memset(response->public_key, 0, response->public_key_len); free(response->public_key); response->public_key = NULL; } if (response->key_handle != NULL) { memset(response->key_handle, 0, response->key_handle_len); free(response->key_handle); response->key_handle = NULL; } } BIO_free(bio); EC_KEY_free(key); return ret; #else return -1; #endif } static int pack_key_ed25519(struct sk_enroll_response *response) { int ret = -1; u_char pk[crypto_sign_ed25519_PUBLICKEYBYTES]; u_char sk[crypto_sign_ed25519_SECRETKEYBYTES]; response->public_key = NULL; response->public_key_len = 0; response->key_handle = NULL; response->key_handle_len = 0; memset(pk, 0, sizeof(pk)); memset(sk, 0, sizeof(sk)); crypto_sign_ed25519_keypair(pk, sk); response->public_key_len = sizeof(pk); if ((response->public_key = malloc(response->public_key_len)) == NULL) { skdebug(__func__, "malloc pubkey failed"); goto out; } memcpy(response->public_key, pk, sizeof(pk)); /* Key handle contains sk */ response->key_handle_len = sizeof(sk); if ((response->key_handle = malloc(response->key_handle_len)) == NULL) { skdebug(__func__, "malloc key_handle failed"); goto out; } memcpy(response->key_handle, sk, sizeof(sk)); /* success */ ret = 0; out: if (ret != 0) free(response->public_key); return ret; } static int check_options(struct sk_option **options) { size_t i; if (options == NULL) return 0; for (i = 0; options[i] != NULL; i++) { skdebug(__func__, "requested unsupported option %s", options[i]->name); if (options[i]->required) { skdebug(__func__, "unknown required option"); return -1; } } return 0; } int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **options, struct sk_enroll_response **enroll_response) { struct sk_enroll_response *response = NULL; int ret = SSH_SK_ERR_GENERAL; (void)flags; /* XXX; unused */ if (enroll_response == NULL) { skdebug(__func__, "enroll_response == NULL"); goto out; } *enroll_response = NULL; if (check_options(options) != 0) goto out; /* error already logged */ if ((response = calloc(1, sizeof(*response))) == NULL) { skdebug(__func__, "calloc response failed"); goto out; } response->flags = flags; 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; SHA2_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); SHA256Init(&ctx); SHA256Update(&ctx, (const u_char *)application, strlen(application)); SHA256Final(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)); SHA256Init(&ctx); SHA256Update(&ctx, apphash, sizeof(apphash)); SHA256Update(&ctx, &flags, sizeof(flags)); SHA256Update(&ctx, countbuf, sizeof(countbuf)); SHA256Update(&ctx, message, message_len); SHA256Final(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; SHA2_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); SHA256Init(&ctx); SHA256Update(&ctx, (const u_char *)application, strlen(application)); SHA256Final(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; SHA2_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; } SHA256Init(&ctx); SHA256Update(&ctx, data, datalen); SHA256Final(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; } openssh-10.0p1/regress/misc/PaxHeaders.10889/ssh-verify-attestation040755 001750 001750 0000000003614775415623 0022146xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/misc/ssh-verify-attestation004075500017500001750000000000001477541562300205245ustar00djmdjmopenssh-10.0p1/regress/misc/ssh-verify-attestation/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0023655xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/misc/ssh-verify-attestation/Makefile010064400017500001750000000034431477541562300222440ustar00djmdjm# $OpenBSD: Makefile,v 1.1 2024/12/04 16:42:49 djm Exp $ .include .include PROG= ssh-verify-attestation NOMAN= SSHREL=../../../../../usr.bin/ssh .PATH: ${.CURDIR}/${SSHREL} SRCS=ssh-verify-attestation.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c SRCS+=ssh-ed25519-sk.c sk-usbhid.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c SRCS+=utf8.c 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 CFLAGS+=-I${.CURDIR}/${SSHREL} .if (${OPENSSL:L} == "yes") LDADD+= -lcrypto DPADD+= ${LIBCRYPTO} .endif LDADD+= -lfido2 -lcbor DPADD+= ${LIBFIDO2} ${LIBCBOR} LDADD+= -lutil DPADD+= ${LIBUTIL} .include openssh-10.0p1/regress/misc/ssh-verify-attestation/PaxHeaders.10889/ssh-verify-attestation.c100644 001750 001750 0000000003614775415623 0027015xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c010064400017500001750000000272051477541562300254060ustar00djmdjm/* $OpenBSD: ssh-verify-attestation.c,v 1.2 2024/12/06 10:37:42 djm Exp $ */ /* * Copyright (c) 2022-2024 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. */ /* * This is a small program to verify FIDO attestation objects that * ssh-keygen(1) can record when enrolling a FIDO key. It requires that * the attestation object and challenge used when creating the key be * recorded. * * Example usage: * * $ # Generate a random challenge. * $ dd if=/dev/urandom of=key_ecdsa_sk.challenge bs=32 count=1 * $ # Generate a key, record the attestation blob. * $ ssh-keygen -f key_ecdsa_sk -t ecdsa-sk \ * -Ochallenge=key_ecdsa_sk.challenge \ * -Owrite-attestation=key_ecdsa_sk.attest -N '' * $ # Validate the challenge (-A = print attestation CA cert) * $ ./obj/ssh-verify-attestation -A key_ecdsa_sk key_ecdsa_sk.challenge \ * key_ecdsa_sk.attest * * Limitations/TODO: * * 1) It doesn't automatically detect the attestation statement format. It * assumes the "packed" format used by FIDO2 keys. If that doesn't work, * then try using the -U option to select the "fido-u2f" format. * 2) It makes assumptions about RK, UV, etc status of the key/cred. * 3) Probably bugs. * * Thanks to Markus Friedl and Pedro Martelletto for help getting this * working. */ #include "includes.h" #include #include #include #include #include #include #include "xmalloc.h" #include "log.h" #include "sshbuf.h" #include "sshkey.h" #include "authfile.h" #include "ssherr.h" #include "misc.h" #include "digest.h" #include "crypto_api.h" #include #include #include #include #include #include extern char *__progname; #define ATTEST_MAGIC "ssh-sk-attest-v01" static int prepare_fido_cred(fido_cred_t *cred, int credtype, const char *attfmt, const char *rp_id, struct sshbuf *b, const struct sshbuf *challenge, struct sshbuf **attestation_certp) { struct sshbuf *attestation_cert = NULL, *sig = NULL, *authdata = NULL; char *magic = NULL; int r = SSH_ERR_INTERNAL_ERROR; *attestation_certp = NULL; /* Make sure it's the format we're expecting */ if ((r = sshbuf_get_cstring(b, &magic, NULL)) != 0) { error_fr(r, "parse header"); goto out; } if (strcmp(magic, ATTEST_MAGIC) != 0) { error_f("unsupported format"); r = SSH_ERR_INVALID_FORMAT; goto out; } /* Parse the remaining fields */ if ((r = sshbuf_froms(b, &attestation_cert)) != 0 || (r = sshbuf_froms(b, &sig)) != 0 || (r = sshbuf_froms(b, &authdata)) != 0 || (r = sshbuf_get_u32(b, NULL)) != 0 || /* reserved flags */ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) { /* reserved */ error_fr(r, "parse body"); goto out; } debug3_f("attestation cert len=%zu, sig len=%zu, " "authdata len=%zu challenge len=%zu", sshbuf_len(attestation_cert), sshbuf_len(sig), sshbuf_len(authdata), sshbuf_len(challenge)); fido_cred_set_type(cred, credtype); fido_cred_set_fmt(cred, attfmt); fido_cred_set_clientdata(cred, sshbuf_ptr(challenge), sshbuf_len(challenge)); fido_cred_set_rp(cred, rp_id, NULL); fido_cred_set_authdata(cred, sshbuf_ptr(authdata), sshbuf_len(authdata)); /* XXX set_extensions, set_rk, set_uv */ fido_cred_set_x509(cred, sshbuf_ptr(attestation_cert), sshbuf_len(attestation_cert)); fido_cred_set_sig(cred, sshbuf_ptr(sig), sshbuf_len(sig)); /* success */ *attestation_certp = attestation_cert; attestation_cert = NULL; r = 0; out: free(magic); sshbuf_free(attestation_cert); sshbuf_free(sig); sshbuf_free(authdata); return r; } static uint8_t * get_pubkey_from_cred_ecdsa(const fido_cred_t *cred, size_t *pubkey_len) { const uint8_t *ptr; uint8_t *pubkey = NULL, *ret = NULL; BIGNUM *x = NULL, *y = NULL; EC_POINT *q = NULL; EC_GROUP *g = NULL; 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) { error_f("libcrypto setup failed"); goto out; } if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { error_f("fido_cred_pubkey_ptr failed"); goto out; } if (fido_cred_pubkey_len(cred) != 64) { error_f("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) { error_f("BN_bin2bn failed"); goto out; } if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) { error_f("EC_POINT_set_affine_coordinates_GFp failed"); goto out; } *pubkey_len = EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); if (*pubkey_len == 0 || *pubkey_len > 2048) { error_f("bad pubkey length %zu", *pubkey_len); goto out; } if ((pubkey = malloc(*pubkey_len)) == NULL) { error_f("malloc pubkey failed"); goto out; } if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, pubkey, *pubkey_len, NULL) == 0) { error_f("EC_POINT_point2oct failed"); goto out; } /* success */ ret = pubkey; pubkey = NULL; out: free(pubkey); EC_POINT_free(q); EC_GROUP_free(g); BN_clear_free(x); BN_clear_free(y); return ret; } /* copied from sshsk_ecdsa_assemble() */ static int cred_matches_key_ecdsa(const fido_cred_t *cred, const struct sshkey *k) { struct sshkey *key = NULL; struct sshbuf *b = NULL; EC_KEY *ec = NULL; uint8_t *pubkey = NULL; size_t pubkey_len; int r; if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) { error_f("sshkey_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } key->ecdsa_nid = NID_X9_62_prime256v1; if ((key->pkey = EVP_PKEY_new()) == NULL || (ec = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL || (b = sshbuf_new()) == NULL) { error_f("allocation failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((pubkey = get_pubkey_from_cred_ecdsa(cred, &pubkey_len)) == NULL) { error_f("get_pubkey_from_cred_ecdsa failed"); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_put_string(b, pubkey, pubkey_len)) != 0) { error_fr(r, "sshbuf_put_string"); goto out; } if ((r = sshbuf_get_eckey(b, ec)) != 0) { error_fr(r, "parse"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshkey_ec_validate_public(EC_KEY_get0_group(ec), EC_KEY_get0_public_key(ec)) != 0) { error("Authenticator returned invalid ECDSA key"); r = SSH_ERR_KEY_INVALID_EC_VALUE; goto out; } if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) { /* XXX assume it is a allocation error */ error_f("allocation failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } key->sk_application = xstrdup(k->sk_application); /* XXX */ if (!sshkey_equal_public(key, k)) { error("sshkey_equal_public failed"); r = SSH_ERR_INVALID_ARGUMENT; goto out; } r = 0; /* success */ out: EC_KEY_free(ec); free(pubkey); sshkey_free(key); sshbuf_free(b); return r; } /* copied from sshsk_ed25519_assemble() */ static int cred_matches_key_ed25519(const fido_cred_t *cred, const struct sshkey *k) { struct sshkey *key = NULL; const uint8_t *ptr; int r = -1; if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { error_f("fido_cred_pubkey_ptr failed"); goto out; } if (fido_cred_pubkey_len(cred) != ED25519_PK_SZ) { error_f("bad fido_cred_pubkey_len %zu", fido_cred_pubkey_len(cred)); goto out; } if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) { error_f("sshkey_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { error_f("malloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(key->ed25519_pk, ptr, ED25519_PK_SZ); key->sk_application = xstrdup(k->sk_application); /* XXX */ if (!sshkey_equal_public(key, k)) { error("sshkey_equal_public failed"); r = SSH_ERR_INVALID_ARGUMENT; goto out; } r = 0; /* success */ out: sshkey_free(key); return r; } static int cred_matches_key(const fido_cred_t *cred, const struct sshkey *k) { switch (sshkey_type_plain(k->type)) { case KEY_ECDSA_SK: switch (k->ecdsa_nid) { case NID_X9_62_prime256v1: return cred_matches_key_ecdsa(cred, k); break; default: fatal("Unsupported ECDSA key size"); } break; case KEY_ED25519_SK: return cred_matches_key_ed25519(cred, k); default: error_f("key type %s not supported", sshkey_type(k)); return -1; } } int main(int argc, char **argv) { LogLevel log_level = SYSLOG_LEVEL_INFO; int r, ch, credtype = -1; struct sshkey *k = NULL; struct sshbuf *attestation = NULL, *challenge = NULL; struct sshbuf *attestation_cert = NULL; char *fp; const char *attfmt = "packed", *style = NULL; fido_cred_t *cred = NULL; int write_attestation_cert = 0; extern int optind; /* extern char *optarg; */ ERR_load_crypto_strings(); sanitise_stdfd(); log_init(__progname, log_level, SYSLOG_FACILITY_AUTH, 1); while ((ch = getopt(argc, argv, "UAv")) != -1) { switch (ch) { case 'U': attfmt = "fido-u2f"; break; case 'A': write_attestation_cert = 1; break; case 'v': if (log_level == SYSLOG_LEVEL_ERROR) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; break; default: goto usage; } } log_init(__progname, log_level, SYSLOG_FACILITY_AUTH, 1); argv += optind; argc -= optind; if (argc < 3) { usage: fprintf(stderr, "usage: %s [-vAU] " "pubkey challenge attestation-blob\n", __progname); exit(1); } if ((r = sshkey_load_public(argv[0], &k, NULL)) != 0) fatal_r(r, "load key %s", argv[0]); if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal("sshkey_fingerprint failed"); debug2("key %s: %s %s", argv[2], sshkey_type(k), fp); free(fp); if ((r = sshbuf_load_file(argv[1], &challenge)) != 0) fatal_r(r, "load challenge %s", argv[1]); if ((r = sshbuf_load_file(argv[2], &attestation)) != 0) fatal_r(r, "load attestation %s", argv[2]); if ((cred = fido_cred_new()) == NULL) fatal("fido_cred_new failed"); switch (sshkey_type_plain(k->type)) { case KEY_ECDSA_SK: switch (k->ecdsa_nid) { case NID_X9_62_prime256v1: credtype = COSE_ES256; break; default: fatal("Unsupported ECDSA key size"); } break; case KEY_ED25519_SK: credtype = COSE_EDDSA; break; default: fatal("unsupported key type %s", sshkey_type(k)); } if ((r = prepare_fido_cred(cred, credtype, attfmt, k->sk_application, attestation, challenge, &attestation_cert)) != 0) fatal_r(r, "prepare_fido_cred %s", argv[2]); if (fido_cred_x5c_ptr(cred) != NULL) { debug("basic attestation"); if ((r = fido_cred_verify(cred)) != FIDO_OK) fatal("basic attestation failed"); style = "basic"; } else { debug("self attestation"); if ((r = fido_cred_verify_self(cred)) != FIDO_OK) fatal("self attestation failed"); style = "self"; } if (cred_matches_key(cred, k) != 0) fatal("cred authdata does not match key"); fido_cred_free(&cred); if (write_attestation_cert) { PEM_write(stdout, "CERTIFICATE", NULL, sshbuf_ptr(attestation_cert), sshbuf_len(attestation_cert)); } sshbuf_free(attestation_cert); logit("%s: verified %s attestation", argv[2], style); return (0); } openssh-10.0p1/regress/PaxHeaders.10889/mkdtemp.c100644 001750 001750 0000000003614775415623 0016433xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/mkdtemp.c010064400017500001750000000030331477541562300150150ustar00djmdjm/* * Copyright (c) 2017 Colin Watson * * 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 #include #include #include #include #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; } openssh-10.0p1/regress/PaxHeaders.10889/modpipe.c100644 001750 001750 0000000003614775415623 0016427xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/modpipe.c010064400017500001750000000074751477541562300150270ustar00djmdjm/* * Copyright (c) 2012 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* $OpenBSD: modpipe.c,v 1.6 2013/11/21 03:16:47 djm Exp $ */ #include "includes.h" #include #include #include #include #include #include #include #ifdef HAVE_ERR_H # include #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; } openssh-10.0p1/regress/PaxHeaders.10889/moduli.in100644 001750 001750 0000000003614775415623 0016447xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/moduli.in010064400017500001750000000031351477541562300150340ustar00djmdjm20160301052556 2 6 100 2047 5 DA57B18976E9C55CEAC3BFFF70419A1550258EA7359400BD4FAC8F4203B73E0BC54D62C0A2D9AA9B543FACA0290514EA426DE6FEF897CB858243511DCE5170420C799D888DCFDC4502FF49B66F34E75C00E98A55408A791FF5CFEA7C288F8E6664226A6A90BE237D2E40C207B5AD0CAEDFDA4946E63AEA351A09EF462515FED4098694241CD07E2CB7727B39B8B1B9467D72DFB908D8169F5DB3CD5A6BEBE1344C585A882508B760402E86EB9B5548A7B98635ECFCDC02FF62B29C53847142FC598ADC66F622F6E9F73BDF02B3D795C0DF23D00E5A3A7748F3E1D5B06F46D4568CE3F4CC57E67D4C36DF5C12800620698C727CC5F5BCACF3B7E17E37D19F4647 20160301052601 2 6 100 2047 2 DA57B18976E9C55CEAC3BFFF70419A1550258EA7359400BD4FAC8F4203B73E0BC54D62C0A2D9AA9B543FACA0290514EA426DE6FEF897CB858243511DCE5170420C799D888DCFDC4502FF49B66F34E75C00E98A55408A791FF5CFEA7C288F8E6664226A6A90BE237D2E40C207B5AD0CAEDFDA4946E63AEA351A09EF462515FED4098694241CD07E2CB7727B39B8B1B9467D72DFB908D8169F5DB3CD5A6BEBE1344C585A882508B760402E86EB9B5548A7B98635ECFCDC02FF62B29C53847142FC598ADC66F622F6E9F73BDF02B3D795C0DF23D00E5A3A7748F3E1D5B06F46D4568CE3F4CC57E67D4C36DF5C12800620698C727CC5F5BCACF3B7E17E37D1A5C13B 20160301052612 2 6 100 2047 5 DA57B18976E9C55CEAC3BFFF70419A1550258EA7359400BD4FAC8F4203B73E0BC54D62C0A2D9AA9B543FACA0290514EA426DE6FEF897CB858243511DCE5170420C799D888DCFDC4502FF49B66F34E75C00E98A55408A791FF5CFEA7C288F8E6664226A6A90BE237D2E40C207B5AD0CAEDFDA4946E63AEA351A09EF462515FED4098694241CD07E2CB7727B39B8B1B9467D72DFB908D8169F5DB3CD5A6BEBE1344C585A882508B760402E86EB9B5548A7B98635ECFCDC02FF62B29C53847142FC598ADC66F622F6E9F73BDF02B3D795C0DF23D00E5A3A7748F3E1D5B06F46D4568CE3F4CC57E67D4C36DF5C12800620698C727CC5F5BCACF3B7E17E37D1B7A3EF openssh-10.0p1/regress/PaxHeaders.10889/multiplex.sh100644 001750 001750 0000000003614775415623 0017205xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/multiplex.sh010064400017500001750000000174001477541562300155720ustar00djmdjm# $OpenBSD: multiplex.sh,v 1.37 2024/07/19 04:33:36 djm 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 skip "not supported on this platform (FD passing disabled)" 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" } maybe_add_scp_path_to_sshd 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: setenv" trace "setenv 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: envpass" trace "env passing over multiplexed connection" ${SSH} -F $OBJ/ssh_config -oSetEnv="_XXX_TEST=foo" -S$CTL otherhost sh << 'EOF' test X"$_XXX_TEST" = X"foo" EOF if [ $? -ne 0 ]; then fail "environment not found" fi for mode in "" "-Oproxy"; do verbose "test $tid: transfer $mode" rm -f ${COPY} trace "ssh transfer over $mode multiplexed connection and check result" ${SSH} $mode -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 $mode multiplexed connection and check result" ${SSH} $mode -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}" done 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} >`ssh_logfile nc` & 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 for mode in "" "-Oproxy"; do trace "exit status $s over multiplexed connection ($mode)" verbose "test $tid: status $s ($mode)" ${SSH} -F $OBJ/ssh_config -S $CTL $mode otherhost exit $s r=$? if [ $r -ne $s ]; then fail "exit code mismatch: $r != $s" fi # same with early close of stdout/err trace "exit status $s with early close over multiplexed connection ($mode)" ${SSH} -F $OBJ/ssh_config -S $CTL -n $mode otherhost \ exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\' r=$? if [ $r -ne $s ]; then fail "exit code (with sleep) mismatch: $r != $s" fi done done verbose "test $tid: cmd check" ${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 openssh-10.0p1/regress/PaxHeaders.10889/multipubkey.sh100644 001750 001750 0000000003614775415623 0017534xustar0030 atime=1744182234.717602388 openssh-10.0p1/regress/multipubkey.sh010064400017500001750000000052461477541562300161260ustar00djmdjm# $OpenBSD: multipubkey.sh,v 1.4 2021/06/07 01:16:34 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 match in no yes ; do ( cat $OBJ/sshd_proxy.orig echo "Protocol 2" echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u" ) > $OBJ/sshd_proxy if test "$match" = "yes" ; then echo "AuthenticationMethods none" >> $OBJ/sshd_proxy echo "PubkeyAuthentication no" >> $OBJ/sshd_proxy echo "Match all" >> $OBJ/sshd_proxy echo "PubkeyAuthentication yes" >> $OBJ/sshd_proxy fi echo "AuthenticationMethods publickey,publickey" >> $OBJ/sshd_proxy # Single key should fail. trace "match $match single key" rm -f $OBJ/authorized_principals_$USER cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER ${SSH} $opts proxy true && fail "ssh succeeded with key" # Single key with same-public cert should fail. trace "match $match pubkey + identical cert" echo mekmitasdigoat > $OBJ/authorized_principals_$USER cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER ${SSH} $opts proxy true && fail "ssh succeeded with key+cert" # Multiple plain keys should succeed. trace "match $match multiple public" rm -f $OBJ/authorized_principals_$USER cat $OBJ/user_key1.pub $OBJ/user_key2.pub > \ $OBJ/authorized_keys_$USER ${SSH} $opts proxy true || fail "ssh failed with multiple keys" # Cert and different key should succeed # Key and different-public cert should succeed. trace "match $match pubkey + different cert" echo mekmitasdigoat > $OBJ/authorized_principals_$USER cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER ${SSH} $opts proxy true || fail "ssh failed with key/cert" done openssh-10.0p1/regress/PaxHeaders.10889/netcat.c100644 001750 001750 0000000003614775415623 0016250xustar0030 atime=1744182234.718578615 openssh-10.0p1/regress/netcat.c010064400017500001750000001206111477541562300146340ustar00djmdjm/* $OpenBSD: netcat.c,v 1.131 2015/09/03 23:06:28 sobrado Exp $ */ /* * Copyright (c) 2001 Eric Jackson * * 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* . */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "atomicio.h" #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #ifdef HAVE_ERR_H # include #endif #ifdef HAVE_SYS_BYTEORDER_H # include #endif /* rename to avoid collision in libssh */ #define timeout_connect netcat_timeout_connect /* Telnet options from arpa/telnet.h */ #define IAC 255 #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); 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; signal(SIGPIPE, SIG_IGN); 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, res0->ai_family); 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, res0->ai_family); 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; pfd.events = POLLOUT; for (;;) { r = sendmsg(STDOUT_FILENO, &msg, 0); if (r == -1) { if (errno == EAGAIN || errno == EINTR) { 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 af) { 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"); } #if defined(IP_TOS) && defined(IPV6_TCLASS) if (Tflag != -1) { int proto, option; if (af == AF_INET6) { proto = IPPROTO_IPV6; option = IPV6_TCLASS; } else { proto = IPPROTO_IP; option = IP_TOS; } if (setsockopt(s, proto, option, &Tflag, sizeof(Tflag)) == -1) err(1, "set IP ToS"); } #endif if (Iflag) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &Iflag, sizeof(Iflag)) == -1) 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 toskeyword]\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 #include #include #include #include #include #include #include #include #include #include #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); } openssh-10.0p1/regress/PaxHeaders.10889/penalty-expire.sh100644 001750 001750 0000000003614775415623 0020130xustar0030 atime=1744182234.718578615 openssh-10.0p1/regress/penalty-expire.sh010064400017500001750000000017251477541562300165200ustar00djmdjm# $OpenBSD # Placed in the Public Domain. tid="penalties" grep -vi PerSourcePenalties $OBJ/sshd_config > $OBJ/sshd_config.bak cp $OBJ/authorized_keys_${USER} $OBJ/authorized_keys_${USER}.bak conf() { test -z "$PIDFILE" || stop_sshd (cat $OBJ/sshd_config.bak ; echo "PerSourcePenalties $@") > $OBJ/sshd_config cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER} start_sshd } conf "noauth:10s authfail:10s max:20s min:1s" verbose "test connect" ${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed" verbose "penalty expiry" # Incur a penalty cat /dev/null > $OBJ/authorized_keys_${USER} ${SSH} -F $OBJ/ssh_config somehost true && fatal "authfail connect succeeded" sleep 2 # Check denied cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER} ${SSH} -F $OBJ/ssh_config somehost true && fatal "authfail not rejected" # Let it expire and try again. sleep 11 ${SSH} -F $OBJ/ssh_config somehost true || fail "authfail not expired" openssh-10.0p1/regress/PaxHeaders.10889/penalty.sh100644 001750 001750 0000000003614775415623 0016636xustar0030 atime=1744182234.718578615 openssh-10.0p1/regress/penalty.sh010064400017500001750000000032741477541562300152270ustar00djmdjm# $OpenBSD # Placed in the Public Domain. tid="penalties" grep -vi PerSourcePenalties $OBJ/sshd_config > $OBJ/sshd_config.bak cp $OBJ/authorized_keys_${USER} $OBJ/authorized_keys_${USER}.bak conf() { test -z "$PIDFILE" || stop_sshd (cat $OBJ/sshd_config.bak ; echo "PerSourcePenalties $@") > $OBJ/sshd_config cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER} start_sshd } conf "authfail:300s min:350s max:900s" verbose "test connect" ${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed" verbose "penalty for authentication failure" # Fail authentication once cat /dev/null > $OBJ/authorized_keys_${USER} ${SSH} -F $OBJ/ssh_config somehost true && fatal "noauth connect succeeded" cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER} sleep 2 # Should be below penalty threshold ${SSH} -F $OBJ/ssh_config somehost true || fatal "authfail not expired" sleep 2 # Fail authentication again; penalty should activate cat /dev/null > $OBJ/authorized_keys_${USER} ${SSH} -F $OBJ/ssh_config somehost true && fatal "noauth connect succeeded" cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER} sleep 2 # These should be refused by the active penalty ${SSH} -F $OBJ/ssh_config somehost true && fail "authfail not rejected" ${SSH} -F $OBJ/ssh_config somehost true && fail "repeat authfail not rejected" conf "noauth:100s" ${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed" verbose "penalty for no authentication" ${SSHKEYSCAN} -t ssh-ed25519 -p $PORT 127.0.0.1 >/dev/null || fatal "keyscan failed" sleep 2 # Repeat attempt should be penalised ${SSHKEYSCAN} -t ssh-ed25519 -p $PORT 127.0.0.1 >/dev/null 2>&1 && fail "keyscan not rejected" openssh-10.0p1/regress/PaxHeaders.10889/percent.sh100644 001750 001750 0000000003614775415623 0016622xustar0030 atime=1744182234.718578615 openssh-10.0p1/regress/percent.sh010064400017500001750000000113241477541562300152060ustar00djmdjm# $OpenBSD: percent.sh,v 1.21 2025/04/08 23:10:46 djm Exp $ # Placed in the Public Domain. tid="percent expansions" USER=`id -u -n` USERID=`id -u` HOST=`hostname | cut -f1 -d.` HOSTNAME=`hostname` HASH="" # 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=`echo "$3" | sed 's|^//|/|'` # approximate realpath trace "test $opt=$arg $expect" rm -f $OBJ/actual got="" case "$opt" in localcommand) ${SSH} -F $OBJ/ssh_proxy -o $opt="echo '$arg' >$OBJ/actual" \ somehost true got=`cat $OBJ/actual` ;; user|user-l|user-at) if [ "$arg" = '%r' ] || [ "$arg" = '%C' ]; then # User does not support %r, ie itself or %C. Skip test. got="$expect" elif [ "$i" = "user" ]; then got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \ remuser@somehost | awk '$1=="'$opt'"{print $2}'` elif [ "$i" = "user-l" ]; then # Also test ssh -l got=`${SSH} -F $OBJ/ssh_proxy -l "$arg" -G \ somehost | awk '$1=="'user'"{print $2}'` elif [ "$i" = "user-at" ]; then # Also test user@host got=`${SSH} -F $OBJ/ssh_proxy -G "$arg@somehost" | \ awk '$1=="'user'"{print $2}'` fi ;; userknownhostsfile) # Move the userknownhosts file to what the expansion says, # make sure ssh works then put it back. mv "$OBJ/known_hosts" "$OBJ/$expect" ${SSH} -F $OBJ/ssh_proxy -o $opt="$OBJ/$arg" somehost true && \ got="$expect" mv "$OBJ/$expect" "$OBJ/known_hosts" ;; matchexec) (cat $OBJ/ssh_proxy && \ echo "Match Exec \"echo '$arg' >$OBJ/actual\"") \ >$OBJ/ssh_proxy_match ${SSH} -F $OBJ/ssh_proxy_match remuser@somehost true || true got=`cat $OBJ/actual` ;; *forward) # LocalForward and RemoteForward take two args and only # operate on Unix domain socket paths got=`${SSH} -F $OBJ/ssh_proxy -o $opt="/$arg /$arg" -G \ remuser@somehost | awk '$1=="'$opt'"{print $2" "$3}'` expect="/$expect /$expect" ;; setenv) # First make sure we don't expand variable names. got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg=TESTVAL" -G \ remuser@somehost | awk '$1=="'$opt'"{print $2}'` if [ "$got" != "$arg=TESTVAL" ]; then fatal "incorrectly expanded setenv variable name" fi # Now check that the value expands as expected. got=`${SSH} -F $OBJ/ssh_proxy -o $opt=TESTVAL="$arg" -G \ remuser@somehost | awk '$1=="'$opt'"{print $2}'` got=`echo "$got" | sed 's/^TESTVAL=//'` ;; *) 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 revokedhostkeys \ user user-l user-at setenv userknownhostsfile; do verbose $tid $i percent case "$i" in localcommand|userknownhostsfile) # Any test that's going to actually make a connection needs # to use the real username. REMUSER=$USER ;; *) REMUSER=remuser ;; esac if [ "$i" = "$localcommand" ]; then trial $i '%T' NONE fi # Matches implementation in readconf.c:ssh_connection_hash() if [ ! -z "${OPENSSL_BIN}" ]; then HASH=`printf "${HOSTNAME}127.0.0.1${PORT}${REMUSER}" | $OPENSSL_BIN sha1 | cut -f2 -d' '` trial $i '%C' $HASH fi trial $i '%%' '%' trial $i '%i' $USERID trial $i '%h' 127.0.0.1 trial $i '%L' $HOST trial $i '%l' $HOSTNAME trial $i '%n' somehost trial $i '%k' localhost-with-alias trial $i '%p' $PORT trial $i '%r' $REMUSER trial $i '%u' $USER # We can't specify a full path outside the regress dir, so skip tests # containing %d for UserKnownHostsFile, and %r can't refer to itself. if [ "$i" != "userknownhostsfile" ] && [ "$i" != "user" ] && \ [ "$i" != "user-l" ] && [ "$i" != "user-at" ]; then trial $i '%d' $HOME in='%%/%i/%h/%d/%L/%l/%n/%p/%r/%u' out="%/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" if [ ! -z "${HASH}" ]; then in="$in/%C" out="$out/$HASH" fi trial $i "$in" "$out" fi done # Subset of above since we don't expand shell-style variables on anything that # runs a command because the shell will expand those. for i in controlpath identityagent forwardagent localforward remoteforward \ user user-l user-at setenv userknownhostsfile; do verbose $tid $i dollar FOO=bar export FOO trial $i '${FOO}' $FOO done # A subset of options support tilde expansion for i in controlpath identityagent forwardagent; do verbose $tid $i tilde trial $i '~' $HOME/ trial $i '~/.ssh' $HOME/.ssh done openssh-10.0p1/regress/PaxHeaders.10889/portnum.sh100644 001750 001750 0000000003614775415623 0016666xustar0030 atime=1744182234.718578615 openssh-10.0p1/regress/portnum.sh010064400017500001750000000011601477541562300152470ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/proto-mismatch.sh100644 001750 001750 0000000003614775415623 0020130xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/proto-mismatch.sh010064400017500001750000000005601477541562300165140ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/principals-command.sh100644 001750 001750 0000000003614775415623 0020742xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/principals-command.sh010064400017500001750000000123211477541562300173240ustar00djmdjm# $OpenBSD: principals-command.sh,v 1.14 2021/09/30 05:26:26 dtucker 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 skip "need SUDO to create file in /var/run, test won't work without" 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 skip "$PRINCIPALS_COMMAND not executable " \ "(/var/run mounted noexec?)" fi # Test explicitly-specified principals # Setup for AuthorizedPrincipalsCommand rm -f $OBJ/authorized_keys_$USER ( cat $OBJ/sshd_proxy_bak 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: 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: 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: 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: 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: 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: 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 # TODO: remove? rm -f $OBJ/authorized_principals_$USER ( cat $OBJ/sshd_proxy_bak ) > $OBJ/sshd_proxy # Wrong principals list verbose "$tid: 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: 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 openssh-10.0p1/regress/PaxHeaders.10889/proto-version.sh100644 001750 001750 0000000003614775415623 0020010xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/proto-version.sh010064400017500001750000000010171477541562300163720ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/proxy-connect.sh100644 001750 001750 0000000003614775415623 0017772xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/proxy-connect.sh010064400017500001750000000013021477541562300163510ustar00djmdjm# $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" openssh-10.0p1/regress/PaxHeaders.10889/putty-ciphers.sh100644 001750 001750 0000000003614775415623 0020002xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/putty-ciphers.sh010064400017500001750000000026421477541562300163710ustar00djmdjm# $OpenBSD: putty-ciphers.sh,v 1.13 2024/02/09 08:56:59 dtucker Exp $ # Placed in the Public Domain. tid="putty ciphers" puttysetup cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy_bak # Since there doesn't seem to be a way to set MACs on the PuTTY client side, # we force each in turn on the server side, omitting the ones PuTTY doesn't # support. Grepping the binary is pretty janky, but AFAIK there's no way to # query for supported algos. macs="" for m in `${SSH} -Q MACs`; do if strings "${PLINK}" | grep -E "^${m}$" >/dev/null; then macs="${macs} ${m}" else trace "omitting unsupported MAC ${m}" fi done ciphers="" for c in `${SSH} -Q Ciphers`; do if strings "${PLINK}" | grep -E "^${c}$" >/dev/null; then ciphers="${ciphers} ${c}" else trace "omitting unsupported cipher ${c}" fi done for c in default $ciphers; do for m in default ${macs}; do verbose "$tid: cipher $c mac $m" cp ${OBJ}/.putty/sessions/localhost_proxy \ ${OBJ}/.putty/sessions/cipher_$c if [ "${c}" != "default" ]; then echo "Cipher=$c" >> ${OBJ}/.putty/sessions/cipher_$c fi cp ${OBJ}/sshd_proxy_bak ${OBJ}/sshd_proxy if [ "${m}" != "default" ]; then echo "MACs $m" >> ${OBJ}/sshd_proxy fi 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 done rm -f ${COPY} openssh-10.0p1/regress/PaxHeaders.10889/putty-kex.sh100644 001750 001750 0000000003614775415623 0017134xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/putty-kex.sh010064400017500001750000000017121477541562300155200ustar00djmdjm# $OpenBSD: putty-kex.sh,v 1.11 2024/02/09 08:56:59 dtucker Exp $ # Placed in the Public Domain. tid="putty KEX" puttysetup cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy_bak # Enable group1, which PuTTY now disables by default echo "KEX=dh-group1-sha1" >>${OBJ}/.putty/sessions/localhost_proxy # Grepping algos out of the binary is pretty janky, but AFAIK there's no way # to query supported algos. kex="" for k in `$SSH -Q kex`; do if strings "${PLINK}" | grep -E "^${k}$" >/dev/null; then kex="${kex} ${k}" else trace "omitting unsupported KEX ${k}" fi done for k in ${kex}; do verbose "$tid: kex $k" cp ${OBJ}/sshd_proxy_bak ${OBJ}/sshd_proxy echo "KexAlgorithms ${k}" >>${OBJ}/sshd_proxy env HOME=$PWD ${PLINK} -v -load localhost_proxy -batch -i ${OBJ}/putty.rsa2 true \ 2>${OBJ}/log/putty-kex-$k.log if [ $? -ne 0 ]; then fail "KEX $k failed" fi kexmsg=`grep -E '^Doing.* key exchange' ${OBJ}/log/putty-kex-$k.log` trace putty: ${kexmsg} done openssh-10.0p1/regress/PaxHeaders.10889/putty-transfer.sh100644 001750 001750 0000000003614775415623 0020171xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/putty-transfer.sh010064400017500001750000000017671477541562300165670ustar00djmdjm# $OpenBSD: putty-transfer.sh,v 1.12 2024/02/09 08:47:42 dtucker Exp $ # Placed in the Public Domain. tid="putty transfer data" puttysetup 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} openssh-10.0p1/regress/PaxHeaders.10889/reconfigure.sh100644 001750 001750 0000000003614775415623 0017472xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/reconfigure.sh010064400017500001750000000026151477541562300160610ustar00djmdjm# $OpenBSD: reconfigure.sh,v 1.9 2021/06/10 09:46:28 dtucker 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 trace "reconfigure with active clients" ${SSH} -F $OBJ/ssh_config somehost sleep 10 # authenticated client ${NC} -d 127.0.0.1 $PORT >/dev/null & # unauthenticated client PID=`$SUDO cat $PIDFILE` rm -f $PIDFILE $SUDO kill -HUP $PID trace "wait for sshd to restart" i=0; while [ ! -f $PIDFILE -a $i -lt 10 ]; do i=`expr $i + 1` sleep $i done test -f $PIDFILE || fatal "sshd did not restart" trace "connect after restart with active clients" ${SSH} -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then fail "ssh connect with failed after reconfigure" fi openssh-10.0p1/regress/PaxHeaders.10889/reexec.sh100644 001750 001750 0000000003614775415623 0016435xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/reexec.sh010064400017500001750000000020661477541562300150240ustar00djmdjm# $OpenBSD: reexec.sh,v 1.13 2023/01/19 07:53:45 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 $SUDO rm -f $SSHD_COPY copy_tests stop_sshd fi openssh-10.0p1/regress/PaxHeaders.10889/rekey.sh100644 001750 001750 0000000003614775415623 0016301xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/rekey.sh010064400017500001750000000122661477541562300146730ustar00djmdjm# $OpenBSD: rekey.sh,v 1.30 2024/08/28 12:08:26 djm Exp $ # Placed in the Public Domain. tid="rekey" LOG=${TEST_SSH_LOGFILE} COPY2=$OBJ/copy2 rm -f ${LOG} cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak echo "Compression no" >> $OBJ/ssh_proxy echo "RekeyLimit 256k" >> $OBJ/ssh_proxy echo "KexAlgorithms curve25519-sha256" >> ssh_proxy # Test rekeying based on data volume only. # Arguments: rekeylimit, kex method, optional remaining opts are passed to ssh. ssh_data_rekeying() { _bytes=$1 ; shift _kexopt=$1 ; shift _opts="$@" if test -z "$_bytes"; then _bytes=32k fi if ! test -z "$_kexopt" ; then cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "$_kexopt" >> $OBJ/sshd_proxy _opts="$_opts -o$_kexopt" fi case "$_kexopt" in MACs=*) # default chacha20-poly1305 cipher has implicit MAC _opts="$_opts -oCiphers=aes128-ctr" ;; esac trace bytes $_bytes kex $_kexopt opts $_opts rm -f ${COPY} ${COPY2} ${LOG} # Create data file just big enough to reach rekey threshold. dd if=${DATA} of=${COPY} bs=$_bytes count=1 2>/dev/null ${SSH} <${COPY} $_opts -vv \ -oRekeyLimit=$_bytes -F $OBJ/ssh_proxy somehost "cat >${COPY2}" if [ $? -ne 0 ]; then fail "ssh failed ($@)" fi cmp ${COPY} ${COPY2} || fail "corrupted copy ($@)" n=`grep 'NEWKEYS sent' ${LOG} | wc -l` n=`expr $n - 1` _want=`echo $_kexopt | cut -f2 -d=` _got="" case "$_kexopt" in KexAlgorithms=*) _got=`awk '/kex: algorithm: /{print $4}' ${LOG} | \ tr -d '\r' | sort -u` ;; Ciphers=*) _got=`awk '/kex: client->server cipher:/{print $5}' ${LOG} | \ tr -d '\r' | sort -u` ;; MACs=*) _got=`awk '/kex: client->server cipher:/{print $7}' ${LOG} | \ tr -d '\r' | sort -u` ;; esac if [ "$_want" != "$_got" ]; then fail "unexpected algorithm, want $_want, got $_got" fi trace "$n rekeying(s)" if [ $n -lt 1 ]; then fail "no rekeying occurred ($@)" fi cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy } increase_datafile_size 300 opts="" # Filter out duplicate curve algo kexs=`${SSH} -Q kex | grep -v curve25519-sha256@libssh.org` ciphers=`${SSH} -Q cipher` macs=`${SSH} -Q mac` for i in $kexs; do opts="$opts KexAlgorithms=$i" done for i in $ciphers; do opts="$opts Ciphers=$i" done for i in $macs; do opts="$opts MACs=$i" done for opt in $opts; do verbose "client rekey $opt" if ${SSH} -Q cipher-auth | sed 's/^/Ciphers=/' | \ grep $opt >/dev/null; then trace AEAD cipher, testing all KexAlgorithms for kex in $kexs; do ssh_data_rekeying "" "KexAlgorithms=$kex" "-o$opt" done else ssh_data_rekeying "" "$opt" fi done for s in 16 1k 128k 256k; do verbose "client rekeylimit ${s}" ssh_data_rekeying "$s" "" done for s in 5 10; do verbose "client rekeylimit default ${s}" rm -f ${COPY} ${LOG} ${SSH} < ${DATA} -oRekeyLimit="default $s" -F \ $OBJ/ssh_proxy somehost "cat >${COPY};sleep $s;sleep 10" 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} -oRekeyLimit="default $s" -F \ $OBJ/ssh_proxy somehost "sleep $s;sleep 10" 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} ${COPY2} ${LOG} dd if=${DATA} of=${COPY} bs=$s count=1 2>/dev/null ${SSH} -F $OBJ/ssh_proxy somehost "cat ${COPY}" >${COPY2} if [ $? -ne 0 ]; then fail "ssh failed" fi cmp ${COPY} ${COPY2} || 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} -F $OBJ/ssh_proxy somehost "sleep $s;sleep 10" 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: bytes" for size in 16 1k 1K 1m 1M 1g 1G 4G 8G; 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 b=`${SSH} -G -o "rekeylimit $size" -F $OBJ/ssh_proxy host | \ awk '/rekeylimit/{print $2}'` if [ "$bytes" != "$b" ]; then fatal "rekeylimit size: expected $bytes bytes got $b" fi done verbose "rekeylimit parsing: time" for time in 1 1m 1M 1h 1H 1d 1D 1w 1W; do case $time in 1) seconds=1 ;; 1m|1M) seconds=60 ;; 1h|1H) seconds=3600 ;; 1d|1D) seconds=86400 ;; 1w|1W) seconds=604800 ;; esac s=`${SSH} -G -o "rekeylimit default $time" -F $OBJ/ssh_proxy host | \ awk '/rekeylimit/{print $3}'` if [ "$seconds" != "$s" ]; then fatal "rekeylimit time: expected $time seconds got $s" fi done rm -f ${COPY} ${COPY2} ${DATA} openssh-10.0p1/regress/PaxHeaders.10889/rsa_openssh.prv100644 001750 001750 0000000003614775415623 0017703xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/rsa_openssh.prv010064400017500001750000000015631477541562300162730ustar00djmdjm-----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----- openssh-10.0p1/regress/PaxHeaders.10889/rsa_openssh.pub100644 001750 001750 0000000003614775415623 0017662xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/rsa_openssh.pub010064400017500001750000000003251477541562300162450ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDsilwKcaKN6wSMNd1WgQ9+HRqQEkD0kCTVttrazGu0OhBU3Uko+dFD1Ip0CxdXmN25JQWxOYF7h/Ocu8P3jzv3RTX87xKR0YzlXTLX+SLtF/ySebS3xWPrlfRUDhh03hR5V+8xxvvy9widPYKw/oItwGSueOsEq1LTczCDv2dAjQ== openssh-10.0p1/regress/PaxHeaders.10889/rsa_ssh2.prv100644 001750 001750 0000000003614775415623 0017103xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/rsa_ssh2.prv010064400017500001750000000016341477541562300154720ustar00djmdjm---- 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 ---- --- openssh-10.0p1/regress/PaxHeaders.10889/scp-ssh-wrapper.sh100644 001750 001750 0000000003614775415623 0020220xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/scp-ssh-wrapper.sh010064400017500001750000000020401477541562300165770ustar00djmdjm#!/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 openssh-10.0p1/regress/PaxHeaders.10889/scp-uri.sh100644 001750 001750 0000000003614775415623 0016544xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/scp-uri.sh010064400017500001750000000043141477541562300151310ustar00djmdjm# $OpenBSD: scp-uri.sh,v 1.5 2023/01/13 04:47:34 dtucker Exp $ # Placed in the Public Domain. tid="scp-uri" #set -x COPY2=${OBJ}/copy2 DIR=${COPY}.dd DIR2=${COPY}.dd2 maybe_add_scp_path_to_sshd SRC=`dirname ${SCRIPT}` cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp chmod 755 ${OBJ}/scp-ssh-wrapper.scp export SCP # used in scp-ssh-wrapper.scp scpclean() { rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2} mkdir ${DIR} ${DIR2} } # 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 for mode in scp sftp ; do tag="$tid: $mode mode" if test $mode = scp ; then scpopts="-O -q -S ${OBJ}/scp-ssh-wrapper.scp" else scpopts="-s -D ${SFTPSERVER}" fi verbose "$tag: simple copy local file to remote file" scpclean $SCP $scpopts ${DATA} "scp://${USER}@somehost:${PORT}/${COPY}" || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: simple copy remote file to local file" scpclean $SCP $scpopts "scp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: simple copy local file to remote dir" scpclean cp ${DATA} ${COPY} $SCP $scpopts ${COPY} "scp://${USER}@somehost:${PORT}/${DIR}" || fail "copy failed" cmp ${COPY} ${DIR}/copy || fail "corrupted copy" verbose "$tag: simple copy remote file to local dir" scpclean cp ${DATA} ${COPY} $SCP $scpopts "scp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed" cmp ${COPY} ${DIR}/copy || fail "corrupted copy" verbose "$tag: recursive local dir to remote dir" scpclean rm -rf ${DIR2} cp ${DATA} ${DIR}/copy $SCP $scpopts -r ${DIR} "scp://${USER}@somehost:${PORT}/${DIR2}" || fail "copy failed" for i in $(cd ${DIR} && echo *); do cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy" done verbose "$tag: recursive remote dir to local dir" scpclean rm -rf ${DIR2} cp ${DATA} ${DIR}/copy $SCP $scpopts -r "scp://${USER}@somehost:${PORT}/${DIR}" ${DIR2} || fail "copy failed" for i in $(cd ${DIR} && echo *); do cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy" done # TODO: scp -3 done scpclean rm -f ${OBJ}/scp-ssh-wrapper.exe openssh-10.0p1/regress/PaxHeaders.10889/scp.sh100644 001750 001750 0000000003614775415623 0015747xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/scp.sh010064400017500001750000000137501477541562300143400ustar00djmdjm# $OpenBSD: scp.sh,v 1.19 2023/09/08 05:50:57 djm Exp $ # Placed in the Public Domain. tid="scp" #set -x COPY2=${OBJ}/copy2 DIR=${COPY}.dd DIR2=${COPY}.dd2 COPY3=${OBJ}/copy.glob[123] DIR3=${COPY}.dd.glob[456] DIFFOPT="-rN" # Figure out if diff does not understand "-N" if ! diff -N ${SRC}/scp.sh ${SRC}/scp.sh 2>/dev/null; then DIFFOPT="-r" fi maybe_add_scp_path_to_sshd SRC=`dirname ${SCRIPT}` cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp chmod 755 ${OBJ}/scp-ssh-wrapper.scp export SCP # used in scp-ssh-wrapper.scp scpclean() { rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2} ${COPY3} ${DIR3} mkdir ${DIR} ${DIR2} ${DIR3} chmod 755 ${DIR} ${DIR2} ${DIR3} } # Create directory structure for recursive copy tests. forest() { scpclean rm -rf ${DIR2} cp ${DATA} ${DIR}/copy ln -s ${DIR}/copy ${DIR}/copy-sym mkdir ${DIR}/subdir cp ${DATA} ${DIR}/subdir/copy ln -s ${DIR}/subdir ${DIR}/subdir-sym } for mode in scp sftp ; do tag="$tid: $mode mode" if test $mode = scp ; then scpopts="-O -q -S ${OBJ}/scp-ssh-wrapper.scp" else scpopts="-qs -D ${SFTPSERVER}" fi verbose "$tag: simple copy local file to local file" scpclean $SCP $scpopts ${DATA} ${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: simple copy local file to remote file" scpclean $SCP $scpopts ${DATA} somehost:${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: simple copy remote file to local file" scpclean $SCP $scpopts somehost:${DATA} ${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: copy local file to remote file in place" scpclean cp ${DATA} ${COPY} $SCP $scpopts ${COPY} somehost:${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: copy remote file to local file in place" scpclean cp ${DATA} ${COPY} $SCP $scpopts somehost:${COPY} ${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: copy local file to remote file clobber" scpclean cat ${DATA} ${DATA} > ${COPY} $SCP $scpopts ${DATA} somehost:${COPY} || fail "copy failed" ls -l $DATA $COPY cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: copy remote file to local file clobber" scpclean cat ${DATA} ${DATA} > ${COPY} $SCP $scpopts somehost:${DATA} ${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: simple copy local file to remote dir" scpclean cp ${DATA} ${COPY} $SCP $scpopts ${COPY} somehost:${DIR} || fail "copy failed" cmp ${COPY} ${DIR}/copy || fail "corrupted copy" verbose "$tag: simple copy local file to local dir" scpclean cp ${DATA} ${COPY} $SCP $scpopts ${COPY} ${DIR} || fail "copy failed" cmp ${COPY} ${DIR}/copy || fail "corrupted copy" verbose "$tag: 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 "$tag: recursive local dir to remote dir" forest $SCP $scpopts -r ${DIR} somehost:${DIR2} || fail "copy failed" diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy" verbose "$tag: recursive local dir to local dir" forest rm -rf ${DIR2} cp ${DATA} ${DIR}/copy $SCP $scpopts -r ${DIR} ${DIR2} || fail "copy failed" diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy" verbose "$tag: recursive remote dir to local dir" forest rm -rf ${DIR2} cp ${DATA} ${DIR}/copy $SCP $scpopts -r somehost:${DIR} ${DIR2} || fail "copy failed" diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy" verbose "$tag: unmatched glob file local->remote" scpclean $SCP $scpopts ${DATA} somehost:${COPY3} || fail "copy failed" cmp ${DATA} ${COPY3} || fail "corrupted copy" verbose "$tag: unmatched glob file remote->local" # NB. no clean $SCP $scpopts somehost:${COPY3} ${COPY2} || fail "copy failed" cmp ${DATA} ${COPY2} || fail "corrupted copy" verbose "$tag: unmatched glob dir recursive local->remote" scpclean rm -rf ${DIR3} cp ${DATA} ${DIR}/copy cp ${DATA} ${DIR}/copy.glob[1234] $SCP $scpopts -r ${DIR} somehost:${DIR3} || fail "copy failed" diff ${DIFFOPT} ${DIR} ${DIR3} || fail "corrupted copy" verbose "$tag: unmatched glob dir recursive remote->local" # NB. no clean rm -rf ${DIR2} $SCP $scpopts -r somehost:${DIR3} ${DIR2} || fail "copy failed" diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy" verbose "$tag: 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 "$tag: skipped file after scp -p with failed chown+utimes" scpclean cp -p ${DATA} ${DIR}/copy cp -p ${DATA} ${DIR}/copy2 cp ${DATA} ${DIR2}/copy chmod 660 ${DIR2}/copy $SUDO chown root ${DIR2}/copy $SCP -p $scpopts somehost:${DIR}/\* ${DIR2} >/dev/null 2>&1 $SUDO diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy" $SUDO rm ${DIR2}/copy fi for i in 0 1 2 3 4 5 6 7; do verbose "$tag: disallow bad server #$i" SCPTESTMODE=badserver_$i export DIR SCPTESTMODE scpclean $SCP $scpopts somehost:${DATA} ${DIR} >/dev/null 2>/dev/null [ -d {$DIR}/rootpathdir ] && fail "allows dir relative to root dir" [ -d ${DIR}/dotpathdir ] && fail "allows dir creation in non-recursive mode" scpclean $SCP -r $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null [ -d ${DIR}/dotpathdir ] && fail "allows dir creation outside of subdir" scpclean $SCP -pr $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null [ ! -w ${DIR2} ] && fail "allows target root attribute change" scpclean $SCP $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null [ -e ${DIR2}/extrafile ] && fail "allows unauth object creation" rm -f ${DIR2}/extrafile done verbose "$tag: detect non-directory target" scpclean echo a > ${COPY} echo b > ${COPY2} $SCP $scpopts ${DATA} ${COPY} ${COPY2} cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target" done scpclean rm -f ${OBJ}/scp-ssh-wrapper.scp openssh-10.0p1/regress/PaxHeaders.10889/scp3.sh100644 001750 001750 0000000003614775415623 0016032xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/scp3.sh010064400017500001750000000033221477541562300144150ustar00djmdjm# $OpenBSD: scp3.sh,v 1.5 2023/09/08 06:10:57 djm Exp $ # Placed in the Public Domain. tid="scp3" COPY2=${OBJ}/copy2 DIR=${COPY}.dd DIR2=${COPY}.dd2 maybe_add_scp_path_to_sshd SRC=`dirname ${SCRIPT}` cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp chmod 755 ${OBJ}/scp-ssh-wrapper.scp export SCP # used in scp-ssh-wrapper.scp scpclean() { rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2} mkdir ${DIR} ${DIR2} chmod 755 ${DIR} ${DIR2} } # Create directory structure for recursive copy tests. forest() { scpclean rm -rf ${DIR2} cp ${DATA} ${DIR}/copy ln -s ${DIR}/copy ${DIR}/copy-sym mkdir ${DIR}/subdir cp ${DATA} ${DIR}/subdir/copy ln -s ${DIR}/subdir ${DIR}/subdir-sym } for mode in scp sftp ; do scpopts="-F${OBJ}/ssh_proxy -S ${SSH} -q" tag="$tid: $mode mode" if test $mode = scp ; then scpopts="$scpopts -O" else scpopts="-s -D ${SFTPSERVER}" fi verbose "$tag: simple copy remote file to remote file" scpclean $SCP $scpopts -3 hostA:${DATA} hostB:${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: simple copy remote file to remote dir" scpclean cp ${DATA} ${COPY} $SCP $scpopts -3 hostA:${COPY} hostB:${DIR} || fail "copy failed" cmp ${COPY} ${DIR}/copy || fail "corrupted copy" verbose "$tag: recursive remote dir to remote dir" forest $SCP $scpopts -3r hostA:${DIR} hostB:${DIR2} || fail "copy failed" diff -r ${DIR} ${DIR2} || fail "corrupted copy" diff -r ${DIR2} ${DIR} || fail "corrupted copy" verbose "$tag: detect non-directory target" scpclean echo a > ${COPY} echo b > ${COPY2} $SCP $scpopts -3 hostA:${DATA} hostA:${COPY} hostB:${COPY2} cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target" done scpclean rm -f ${OBJ}/scp-ssh-wrapper.exe openssh-10.0p1/regress/PaxHeaders.10889/servcfginclude.sh100644 001750 001750 0000000003614775415623 0020165xustar0030 atime=1744182234.719555342 openssh-10.0p1/regress/servcfginclude.sh010064400017500001750000000074521477541562300165600ustar00djmdjm# 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.* # comment Match host=c Include $OBJ/sshd_config.i.* # comment Banner /cc Match host m Include $OBJ/sshd_config.i.* Match Host d Banner /dd # comment 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 # comment Banner /cccc Match Host=d Banner /dddd Match Host e Banner /eeee Match Host f Banner /ffff Match all Banner /xxxx _EOF trial() { _host="$1" _exp="$2" _desc="$3" test -z "$_desc" && _desc="test match" trace "$_desc host=$_host expect=$_exp" ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \ -C "host=$_host,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || fatal "ssh config parse failed: $_desc host=$_host expect=$_exp" _got=`grep -i '^banner ' $OBJ/sshd_config.out | awk '{print $2}'` if test "x$_exp" != "x$_got" ; then fail "$desc_ host $_host include fail: expected $_exp got $_got" fi } trial a /aa trial b /bb trial c /ccc trial d /dd trial e /ee trial f /fff trial m /xxxx trial n /xxxx trial x none # Prepare an included config with an error. cat > $OBJ/sshd_config.i.3 << _EOF Banner xxxx Junk _EOF trace "disallow invalid config host=a" ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \ -C "host=a,user=test,addr=127.0.0.1" 2>/dev/null && \ fail "sshd include allowed invalid config" trace "disallow invalid config host=x" ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \ fail "sshd include allowed invalid config" rm -f $OBJ/sshd_config.i.* # Ensure that a missing include is not fatal. cat > $OBJ/sshd_config.i << _EOF HostKey $OBJ/host.ssh-ed25519 Include $OBJ/sshd_config.i.* Banner /aa _EOF trial a /aa "missing include non-fatal" # Ensure that Match/Host in an included config does not affect parent. cat > $OBJ/sshd_config.i.x << _EOF Match host x _EOF trial a /aa "included file does not affect match state" # Ensure the empty include directive is not accepted cat > $OBJ/sshd_config.i.x << _EOF Include _EOF trace "disallow invalid with no argument" ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x -T \ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \ fail "sshd allowed Include with no argument" # Ensure the Include before any Match block works as expected (bug #3122) cat > $OBJ/sshd_config.i << _EOF Banner /xx HostKey $OBJ/host.ssh-ed25519 Include $OBJ/sshd_config.i.2 Match host a Banner /aaaa _EOF cat > $OBJ/sshd_config.i.2 << _EOF Match host a Banner /aa _EOF trace "Include before match blocks" trial a /aa "included file before match blocks is properly evaluated" # Port in included file is correctly interpretted (bug #3169) cat > $OBJ/sshd_config.i << _EOF Include $OBJ/sshd_config.i.2 Port 7722 _EOF cat > $OBJ/sshd_config.i.2 << _EOF HostKey $OBJ/host.ssh-ed25519 _EOF trace "Port after included files" ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \ -C "host=x,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || \ fail "failed to parse Port after included files" _port=`grep -i '^port ' $OBJ/sshd_config.out | awk '{print $2}'` if test "x7722" != "x$_port" ; then fail "The Port in included file was intertepretted wrongly. Expected 7722, got $_port" fi # cleanup rm -f $OBJ/sshd_config.i $OBJ/sshd_config.i.* $OBJ/sshd_config.out openssh-10.0p1/regress/PaxHeaders.10889/setuid-allowed.c100644 001750 001750 0000000003614775415623 0017714xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/setuid-allowed.c010064400017500001750000000027161477541562300163050ustar00djmdjm/* * Copyright (c) 2013 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* $OpenBSD$ */ #include "includes.h" #include #ifdef HAVE_SYS_STATVFS_H # include #endif #include #include #include #include static void usage(void) { fprintf(stderr, "check-setuid [path]\n"); exit(1); } int main(int argc, char **argv) { 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; } openssh-10.0p1/regress/PaxHeaders.10889/sftp-badcmds.sh100644 001750 001750 0000000003614775415623 0017531xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-badcmds.sh010064400017500001750000000043411477541562300161160ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/sftp-batch.sh100644 001750 001750 0000000003614775415623 0017215xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-batch.sh010064400017500001750000000022451477541562300156030ustar00djmdjm# $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}.* openssh-10.0p1/regress/PaxHeaders.10889/sftp-chroot.sh100644 001750 001750 0000000003614775415623 0017432xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-chroot.sh010064400017500001750000000023371477541562300160220ustar00djmdjm# $OpenBSD: sftp-chroot.sh,v 1.9 2023/05/12 06:37:42 djm 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 skip "need SUDO to create file in /var/run, test won't work without" fi if ! $OBJ/check-perm -m chroot "$CHROOT" ; then skip "$CHROOT is unsuitable as ChrootDirectory" fi $SUDO sh -c "echo mekmitastdigoat > $PRIVDATA" || \ fatal "create $PRIVDATA failed" echo "ForceCommand internal-sftp -d /" >> $OBJ/sshd_config start_sshd -oChrootDirectory=$CHROOT 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" stop_sshd verbose "test $tid: match" cat << EOF >> $OBJ/sshd_config Match All ChrootDirectory $CHROOT EOF start_sshd $SUDO sh -c "echo orpheanbeholder > $PRIVDATA" || \ fatal "create $PRIVDATA failed" ${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" stop_sshd openssh-10.0p1/regress/PaxHeaders.10889/sftp-cmds.sh100644 001750 001750 0000000003614775415623 0017062xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-cmds.sh010064400017500001750000000166131477541562300154540ustar00djmdjm# $OpenBSD: sftp-cmds.sh,v 1.20 2024/07/01 03:10:19 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" printf "lcd ${OBJ}\nlls\n" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \ grep copy.dd >/dev/null || fail "lls failed" verbose "$tid: lls w/path" echo "lls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \ grep copy.dd >/dev/null || 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} 2>&1 | \ egrep '^hi there$' >/dev/null || fail "shell failed" 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" printf "lcd ${COPY}.dd\nget $DATA\n" | ${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" printf "lcd ${COPY}.dd\nget /bin/l*\n" | ${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" printf "cd ${COPY}.dd\nput $DATA\n" | ${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" printf "cd ${COPY}.dd\nput /bin/l*\n" | ${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: cp" rm -f ${COPY}.2 echo "cp ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "cp failed" cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after cp" 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" openssh-10.0p1/regress/PaxHeaders.10889/sftp-glob.sh100644 001750 001750 0000000003614775415623 0017057xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-glob.sh010064400017500001750000000047401477541562300154470ustar00djmdjm# $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} openssh-10.0p1/regress/PaxHeaders.10889/sftp-perm.sh100644 001750 001750 0000000003614775415623 0017077xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-perm.sh010064400017500001750000000126031477541562300154640ustar00djmdjm# $OpenBSD: sftp-perm.sh,v 1.3 2021/03/31 21:59:26 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" # Can't readily test this because the client falls back to traditional rename. # XXX maybe there is a behaviorial difference we can test for? #perm_test \ # "posix-rename" \ # "realpath,stat,lstat" \ # "rename $COPY ${COPY}.1" \ # "touch $COPY" \ # "test -f ${COPY}.1 -a ! -f $COPY" \ # "test -f $COPY -a ! -f ${COPY}.1" perm_test \ "rename" \ "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 openssh-10.0p1/regress/PaxHeaders.10889/sftp-resume.sh100644 001750 001750 0000000003614775415623 0017434xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-resume.sh010064400017500001750000000022531477541562300160210ustar00djmdjm# $OpenBSD: sftp-resume.sh,v 1.2 2025/03/11 09:06:50 dtucker Exp $ # Placed in the Public Domain. tid="sftp resume" CLIENT_LOG=${OBJ}/sftp.log # We test up to 1MB, ensure source data is large enough. increase_datafile_size 1200 for cmd in put get; do verbose "$tid: ${cmd}" for size in 0 1 1k 1m size-1 same; do trace "$tid: test ${cmd} ${size}" rm -rf ${COPY}.1 ${COPY}.2 cp ${DATA} ${COPY}.1 # Set up requested source and destination file sizes. case "${size}" in 0) touch ${COPY}.2 ;; size-1) dd if=${DATA} of=${COPY}.1 bs=1024 count=1 >/dev/null 2>&1 dd if=${DATA} of=${COPY}.2 bs=1023 count=1 >/dev/null 2>&1 ;; same) cp ${DATA} ${COPY}.2 ;; 1m) dd if=${COPY}.1 of=${COPY}.2 bs=1k count=1k >/dev/null 2<&1 ;; *) dd if=${COPY}.1 of=${COPY}.2 bs=${size} count=1 >/dev/null 2>&1 ;; esac # Perform copy and check. echo "${cmd} -a ${COPY}.1 ${COPY}.2" | \ ${SFTP} -D ${SFTPSERVER} -vvv >${CLIENT_LOG} 2>&1 \ || fail "${cmd} failed" cmp ${COPY}.1 ${COPY}.2 || fail "corrupted copy after ${cmd} ${size}" grep "reordered" ${CLIENT_LOG} >/dev/null && \ fail "server reordered requests ${cmd} ${size}" done done rm -rf ${COPY}.1 ${COPY}.2 openssh-10.0p1/regress/PaxHeaders.10889/sftp-uri.sh100644 001750 001750 0000000003614775415623 0016733xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp-uri.sh010064400017500001750000000031301477541562300153130ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/sftp.sh100644 001750 001750 0000000003614775415623 0016136xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/sftp.sh010064400017500001750000000013411477541562300145200ustar00djmdjm# $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 < /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 openssh-10.0p1/regress/PaxHeaders.10889/ssh-com-client.sh100644 001750 001750 0000000003614775415623 0020007xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/ssh-com-client.sh010064400017500001750000000060271477541562300163770ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/ssh-com-keygen.sh100644 001750 001750 0000000003614775415623 0020013xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/ssh-com-keygen.sh010064400017500001750000000026051477541562300164010ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/ssh-com-sftp.sh100644 001750 001750 0000000003614775415623 0017505xustar0030 atime=1744182234.720531599 openssh-10.0p1/regress/ssh-com-sftp.sh010064400017500001750000000023061477541562300160710ustar00djmdjm# $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 < /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 openssh-10.0p1/regress/PaxHeaders.10889/ssh-com.sh100644 001750 001750 0000000003614775415623 0016533xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/ssh-com.sh010064400017500001750000000053301477541562300151170ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/ssh2putty.sh100755 001750 001750 0000000003614775415623 0017152xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/ssh2putty.sh010075500017500001750000000013521477541562300155360ustar00djmdjm#!/bin/sh # $OpenBSD: ssh2putty.sh,v 1.9 2021/07/25 12:13:03 dtucker Exp $ if test "x$1" = "x" -o "x$2" = "x" -o "x$3" = "x" ; then echo "Usage: ssh2putty hostname port ssh-private-key" exit 1 fi HOST=$1 PORT=$2 KEYFILE=$3 OPENSSL_BIN="${OPENSSL_BIN:-openssl}" # XXX - support DSA keys too if grep "BEGIN RSA PRIVATE KEY" $KEYFILE >/dev/null 2>&1 ; then : else echo "Unsupported private key format" exit 1 fi public_exponent=` $OPENSSL_BIN rsa -noout -text -in $KEYFILE | grep ^publicExponent | sed 's/.*(//;s/).*//' ` test $? -ne 0 && exit 1 modulus=` $OPENSSL_BIN 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" openssh-10.0p1/regress/PaxHeaders.10889/sshcfgparse.sh100644 001750 001750 0000000003614775415623 0017472xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/sshcfgparse.sh010064400017500001750000000114121477541562300160540ustar00djmdjm# $OpenBSD: sshcfgparse.sh,v 1.9 2021/06/08 07:05:27 dtucker 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 "failed to reparse minimal" 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 "pubkeyacceptedalgorithms" # Default set f=`${SSH} -GF none host | awk '/^pubkeyacceptedalgorithms /{print $2}'` expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" expect_result_absent "$f" "ssh-dss" # Explicit override f=`${SSH} -GF none -opubkeyacceptedalgorithms=ssh-ed25519 host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` expect_result_present "$f" "ssh-ed25519" expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" # Removal from default set f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519-cert* host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` expect_result_present "$f" "ssh-ed25519" expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519 host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` expect_result_present "$f" "ssh-ed25519-cert-v01.*" expect_result_absent "$f" "ssh-ed25519" "ssh-dss" # Append to default set. # This is not tested when built !WITH_OPENSSL if [ "$dsa" = "1" ]; then f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss-cert* host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` expect_result_present "$f" "ssh-ed25519" "ssh-dss-cert-v01.*" expect_result_absent "$f" "ssh-dss" f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" "ssh-dss" expect_result_absent "$f" "ssh-dss-cert-v01.*" fi 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" verbose "command line override" cat >$OBJ/ssh_config.0 </dev/null; then skip "RSA keys not supported." elif [ -z "${TEST_SSH_SSHFP_DOMAIN}" ]; then skip "TEST_SSH_SSHFP_DOMAIN not set." else # Prime any DNS caches and resolvers. for i in sshtest sshtest-sha1 sshtest-sha256; do host -t sshfp ${i}.${TEST_SSH_SSHFP_DOMAIN} >/dev/null 2>&1 host -t sshfp ${i}-bad.${TEST_SSH_SSHFP_DOMAIN} >/dev/null 2>&1 done # Set RSA host key to match fingerprints above. mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig $SUDO cp $SRC/rsa_openssh.prv $OBJ/host.ssh-rsa $SUDO chmod 600 $OBJ/host.ssh-rsa sed -e "s|$OBJ/ssh-rsa|$OBJ/host.ssh-rsa|" \ $OBJ/sshd_proxy.orig > $OBJ/sshd_proxy # Zero out known hosts and key aliases to force use of SSHFP records. > $OBJ/known_hosts mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig sed -e "/HostKeyAlias.*localhost-with-alias/d" \ -e "/Hostname.*127.0.0.1/d" \ $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy for n in sshtest sshtest-sha1 sshtest-sha256; do trace "sshfp connect $n good fingerprint" host="${n}.dtucker.net" opts="-F $OBJ/ssh_proxy -o VerifyHostKeyDNS=yes " opts="$opts -o HostKeyAlgorithms=rsa-sha2-512,rsa-sha2-256" host="${n}.${TEST_SSH_SSHFP_DOMAIN}" SSH_CONNECTION=`${SSH} $opts $host 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then fail "ssh sshfp connect failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then fail "bad SSH_CONNECTION: $SSH_CONNECTION" fi trace "sshfp connect $n bad fingerprint" host="${n}-bad.${TEST_SSH_SSHFP_DOMAIN}" if ${SSH} $opts ${host} true; then fail "sshfp-connect succeeded with bad SSHFP record" fi done fi openssh-10.0p1/regress/PaxHeaders.10889/sshsig.sh100644 001750 001750 0000000003614775415623 0016462xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/sshsig.sh010064400017500001750000000536041477541562300150550ustar00djmdjm# $OpenBSD: sshsig.sh,v 1.15 2023/10/12 03:51:08 djm Exp $ # Placed in the Public Domain. tid="sshsig" DATA2=$OBJ/${DATANAME}.2 cat ${DATA} ${DATA} > ${DATA2} rm -f $OBJ/sshsig-*.sig $OBJ/wrong-key* $OBJ/sigca-key* sig_namespace="test-$$" sig_principal="user-$$@example.com" # Make a "wrong key" ${SSHKEYGEN} -q -t ed25519 -f $OBJ/wrong-key \ -C "wrong trousers, Grommit" -N '' \ || fatal "couldn't generate key" WRONG=$OBJ/wrong-key.pub # Make a CA key. ${SSHKEYGEN} -q -t ed25519 -f $OBJ/sigca-key -C "CA" -N '' \ || fatal "couldn't generate key" CA_PRIV=$OBJ/sigca-key CA_PUB=$OBJ/sigca-key.pub trace "start agent" eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fatal "could not start ssh-agent: exit code $r" fi SIGNKEYS="$SSH_KEYTYPES" verbose "$tid: make certificates" for t in $SSH_KEYTYPES ; do ${SSHKEYGEN} -q -s $CA_PRIV -z $$ \ -I "regress signature key for $USER" \ -V "19840101:19860101" \ -n $sig_principal $OBJ/${t} || \ fatal "couldn't sign ${t}" SIGNKEYS="$SIGNKEYS ${t}-cert.pub" done for t in $SIGNKEYS; do verbose "$tid: check signature for $t" keybase=`basename $t .pub` privkey=${OBJ}/`basename $t -cert.pub` sigfile=${OBJ}/sshsig-${keybase}.sig sigfile_agent=${OBJ}/sshsig-agent-${keybase}.sig pubkey=${OBJ}/${keybase}.pub cert=${OBJ}/${keybase}-cert.pub sigfile_cert=${OBJ}/sshsig-${keybase}-cert.sig trace "$tid: key type $t check bad hashlg" ${SSHKEYGEN} -vvv -Y sign -f ${OBJ}/$t -n $sig_namespace \ -Ohashalg=sha1 < $DATA > $sigfile 2>/dev/null && \ fail "sign using $t with bad hash algorithm succeeded" for h in default sha256 sha512 ; do case "$h" in default) hashalg_arg="" ;; *) hashalg_arg="-Ohashalg=$h" ;; esac trace "$tid: key type $t sign with hash $h" ${SSHKEYGEN} -vvv -Y sign -f ${OBJ}/$t -n $sig_namespace \ $hashalg_arg < $DATA > $sigfile 2>/dev/null || \ fail "sign using $t / $h failed" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers trace "$tid: key type $t verify with hash $h" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t / $h key" done trace "$tid: key type $t verify with limited namespace" (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t key w/ limited namespace" trace "$tid: key type $t print-pubkey" (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -q -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -O print-pubkey \ < $DATA | cut -d' ' -f1-2 > ${OBJ}/${keybase}-fromsig.pub || \ fail "failed signature for $t key w/ print-pubkey" cut -d' ' -f1-2 ${OBJ}/${keybase}.pub > ${OBJ}/${keybase}-strip.pub diff -r ${OBJ}/${keybase}-strip.pub ${OBJ}/${keybase}-fromsig.pub || \ fail "print-pubkey differs from signature key" # Invalid option trace "$tid: key type $t verify with bad signers" (printf "$sig_principal octopus " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with bad signers option" # Wrong key trusted. trace "$tid: key type $t verify with wrong key" (printf "$sig_principal " ; cat $WRONG) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with wrong key trusted" # incorrect data trace "$tid: key type $t verify with wrong data" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA2 >/dev/null 2>&1 && \ fail "passed signature for wrong data with $t key" # wrong principal in signers trace "$tid: key type $t verify with wrong principal" (printf "josef.k@example.com " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with wrong principal" # wrong namespace trace "$tid: key type $t verify with wrong namespace" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n COWS_COWS_COWS \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with wrong namespace" # namespace excluded by option trace "$tid: key type $t verify with excluded namespace" (printf "$sig_principal namespaces=\"whatever\" " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with excluded namespace" ( printf "$sig_principal " ; printf "valid-after=\"19800101\",valid-before=\"19900101\" " ; cat $pubkey) > $OBJ/allowed_signers # key lifespan valid trace "$tid: key type $t verify with valid lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t key with valid expiry interval" # key not yet valid trace "$tid: key type $t verify with not-yet-valid lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19790101 \ < $DATA >/dev/null 2>&1 && \ fail "failed signature for $t not-yet-valid key" # key expired trace "$tid: key type $t verify with expired lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19910101 \ < $DATA >/dev/null 2>&1 && \ fail "failed signature for $t with expired key" # NB. assumes we're not running this test in the 1980s trace "$tid: key type $t verify with expired lifespan (now)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "failed signature for $t with expired key" # key lifespan valid trace "$tid: key type $t find-principals with valid lifespan" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19850101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t key with valid expiry interval" # key not yet valid trace "$tid: key type $t find principals with not-yet-valid lifespan" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19790101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t not-yet-valid key" # key expired trace "$tid: key type $t find-principals with expired lifespan" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19990101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # NB. assumes we're not running this test in the 1980s trace "$tid: key type $t find-principals with expired lifespan (now)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # public key in revoked keys file trace "$tid: key type $t verify with revoked key" cat $pubkey > $OBJ/revoked_keys (printf "$sig_principal namespaces=\"whatever\" " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -r $OBJ/revoked_keys \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key, but key is in revoked_keys" # public key not revoked, but others are present in revoked_keysfile trace "$tid: key type $t verify with unrevoked key" cat $WRONG > $OBJ/revoked_keys (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -r $OBJ/revoked_keys \ < $DATA >/dev/null 2>&1 || \ fail "couldn't verify signature for $t key, but key not in revoked_keys" # check-novalidate with valid data trace "$tid: key type $t check-novalidate with valid data" ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \ < $DATA >/dev/null 2>&1 || \ fail "failed to check valid signature for $t key" # check-novalidate with invalid data trace "$tid: key type $t check-novalidate with invalid data" ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \ < $DATA2 >/dev/null 2>&1 && \ fail "succeeded checking signature for $t key with invalid data" # find-principals with valid public key trace "$tid: key type $t find-principals with valid key" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed to find valid principals in allowed_signers" # find-principals with wrong key not in allowed_signers trace "$tid: key type $t find-principals with wrong key" (printf "$sig_principal " ; cat $WRONG) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "succeeded finding principal with invalid signers file" # find-principals with a configured namespace but none on command-line trace "$tid: key type $t find-principals with missing namespace" (printf "$sig_principal " ; printf "namespaces=\"test1,test2\" "; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed finding principal when namespaces are configured" # Check signing keys using ssh-agent. trace "$tid: key type $t prepare agent" ${SSHADD} -D >/dev/null 2>&1 # Remove all previously-loaded keys. ${SSHADD} ${privkey} > /dev/null 2>&1 || fail "ssh-add failed" # Move private key to ensure agent key is used mv ${privkey} ${privkey}.tmp trace "$tid: key type $t sign with agent" ${SSHKEYGEN} -vvv -Y sign -f $pubkey -n $sig_namespace \ < $DATA > $sigfile_agent 2>/dev/null || \ fail "ssh-agent based sign using $pubkey failed" trace "$tid: key type $t check signature w/ agent" ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile_agent \ -n $sig_namespace < $DATA >/dev/null 2>&1 || \ fail "failed to check valid signature for $t key" (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile_agent -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t key w/ limited namespace" # Move private key back mv ${privkey}.tmp ${privkey} # Duplicate principals & keys in allowed_signers but with different validities ( printf "$sig_principal " ; printf "valid-after=\"19800101\",valid-before=\"19900101\" " ; cat $pubkey; printf "${sig_principal} " ; printf "valid-after=\"19850101\",valid-before=\"20000101\" " ; cat $pubkey) > $OBJ/allowed_signers # find-principals outside of any validity lifespan trace "$tid: key type $t find principals outside multiple validities" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="20100101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "succeeded find-principals for $t verify-time outside of validity" # find-principals matching only the first lifespan trace "$tid: key type $t find principals matching one validity (1st)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19830101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t verify-time within first span" # find-principals matching both lifespans trace "$tid: key type $t find principals matching two validities" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19880101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t verify-time within both spans" # find-principals matching only the second lifespan trace "$tid: key type $t find principals matching one validity (2nd)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19950101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t verify-time within second span" # verify outside of any validity lifespan trace "$tid: key type $t verify outside multiple validities" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="20100101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "succeeded verify for $t verify-time outside of validity" # verify matching only the first lifespan trace "$tid: key type $t verify matching one validity (1st)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="19830101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed verify for $t verify-time within first span" # verify matching both lifespans trace "$tid: key type $t verify matching two validities" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="19880101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed verify for $t verify-time within both spans" # verify matching only the second lifespan trace "$tid: key type $t verify matching one validity (2nd)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="19950101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed verify for $t verify-time within second span" # Remaining tests are for certificates only. case "$keybase" in *-cert) ;; *) continue ;; esac # Check key lifespan on find-principals when using the CA ( printf "$sig_principal " ; printf "cert-authority,valid-after=\"19800101\",valid-before=\"19900101\" "; cat $CA_PUB) > $OBJ/allowed_signers # key lifespan valid trace "$tid: key type $t find-principals cert lifetime valid" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19850101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t key with valid expiry interval" # key not yet valid trace "$tid: key type $t find-principals cert lifetime not-yet-valid" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19790101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t not-yet-valid key" # key expired trace "$tid: key type $t find-principals cert lifetime expired" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19990101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # NB. assumes we're not running this test in the 1980s trace "$tid: key type $t find-principals cert lifetime expired (now)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # correct CA key trace "$tid: key type $t verify cert good CA" (printf "$sig_principal cert-authority " ; cat $CA_PUB) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t cert" # find-principals trace "$tid: key type $t find-principals cert good CA" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time=19850101 \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t with ca key" # CA with wildcard principal trace "$tid: key type $t find-principals cert good wildcard CA" (printf "*@example.com cert-authority " ; cat $CA_PUB) > $OBJ/allowed_signers # find-principals CA with wildcard principal ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time=19850101 \ -f $OBJ/allowed_signers 2>/dev/null | \ fgrep "$sig_principal" >/dev/null || \ fail "failed find-principals for $t with ca key using wildcard principal" # verify CA with wildcard principal trace "$tid: key type $t verify cert good wildcard CA" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t cert using wildcard principal" # signing key listed as cert-authority trace "$tid: key type $t verify signing key listed as CA" (printf "$sig_principal cert-authority " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature with $t key listed as CA" # CA key not flagged cert-authority trace "$tid: key type $t verify key not marked as CA" (printf "$sig_principal " ; cat $CA_PUB) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t cert with CA not marked" # mismatch between cert principal and file trace "$tid: key type $t verify cert with wrong principal" (printf "josef.k@example.com cert-authority " ; cat $CA_PUB) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t cert with wrong principal" # Cert valid but CA revoked trace "$tid: key type $t verify cert with revoked CA" cat $CA_PUB > $OBJ/revoked_keys (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -r $OBJ/revoked_keys \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key, but CA key in revoked_keys" # Set lifespan of CA key and verify signed user certs behave accordingly ( printf "$sig_principal " ; printf "cert-authority,valid-after=\"19800101\",valid-before=\"19900101\" " ; cat $CA_PUB) > $OBJ/allowed_signers # CA key lifespan valid trace "$tid: key type $t verify cert valid CA lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 >/dev/null 2>&1 || \ fail "failed signature for $t key with valid CA expiry interval" # CA lifespan is valid but user key not yet valid trace "$tid: key type $t verify cert valid CA lifespan, not-yet-valid cert" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19810101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with valid CA expiry interval but not yet valid cert" # CA lifespan is valid but user key expired trace "$tid: key type $t verify cert valid CA lifespan, expired cert" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19890101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with valid CA expiry interval but expired cert" # CA key not yet valid trace "$tid: key type $t verify cert CA not-yet-valid" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19790101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t not-yet-valid CA key" # CA key expired trace "$tid: key type $t verify cert CA expired" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19910101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t with expired CA key" # NB. assumes we're not running this test in the 1980s trace "$tid: key type $t verify cert CA expired (now)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t with expired CA key" # Set lifespan of CA outside of the cert validity trace "$tid: key type $t verify CA/cert lifespan mismatch" ( printf "$sig_principal " ; printf "cert-authority,valid-after=\"19800101\",valid-before=\"19820101\" " ; cat $CA_PUB) > $OBJ/allowed_signers # valid cert validity but expired CA ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19840101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with expired CA but valid cert" done # Test key independant match-principals ( printf "principal1 " ; cat $pubkey; printf "princi* " ; cat $pubkey; printf "unique " ; cat $pubkey; ) > $OBJ/allowed_signers verbose "$tid: match principals" ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "unique" | \ fgrep "unique" >/dev/null || \ fail "failed to match static principal" trace "$tid: match principals wildcard" ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "princip" | \ fgrep "princi*" >/dev/null || \ fail "failed to match wildcard principal" trace "$tid: match principals static/wildcard" ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "principal1" | \ fgrep -e "principal1" -e "princi*" >/dev/null || \ fail "failed to match static and wildcard principal" verbose "$tid: nomatch principals" for x in princ prince unknown ; do ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers \ -I $x >/dev/null 2>&1 && \ fail "succeeded to match unknown principal \"$x\"" done trace "kill agent" ${SSHAGENT} -k > /dev/null openssh-10.0p1/regress/PaxHeaders.10889/stderr-after-eof.sh100644 001750 001750 0000000003614775415623 0020333xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/stderr-after-eof.sh010064400017500001750000000011331477541562300167140ustar00djmdjm# $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} openssh-10.0p1/regress/PaxHeaders.10889/stderr-data.sh100644 001750 001750 0000000003614775415623 0017374xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/stderr-data.sh010064400017500001750000000013051477541562300157560ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/t11.ok100644 001750 001750 0000000003614775415623 0015566xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/t11.ok010064400017500001750000000000631477541562300141500ustar00djmdjmSHA256:4w1rnrek3klTJOTVhwuCIFd5k+pq9Bfo5KTxxb8BqbY openssh-10.0p1/regress/PaxHeaders.10889/t4.ok100644 001750 001750 0000000003614775415623 0015510xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/t4.ok010064400017500001750000000000641477541562300140730ustar00djmdjmMD5:3b:dd:44:e9:49:18:84:95:f1:e7:33:6b:9d:93:b1:36 openssh-10.0p1/regress/PaxHeaders.10889/t5.ok100644 001750 001750 0000000003614775415623 0015511xustar0030 atime=1744182234.721508637 openssh-10.0p1/regress/t5.ok010064400017500001750000000001021477541562300140650ustar00djmdjmxokes-lylis-byleh-zebib-kalus-bihas-tevah-haroz-suhar-foved-noxex openssh-10.0p1/regress/PaxHeaders.10889/test-exec.sh100644 001750 001750 0000000003614775415623 0017063xustar0030 atime=1744182234.722485204 openssh-10.0p1/regress/test-exec.sh010064400017500001750000000652661477541562300154650ustar00djmdjm# $OpenBSD: test-exec.sh,v 1.127 2025/03/28 05:41:15 dtucker Exp $ # Placed in the Public Domain. #SUDO=sudo if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then STARTTIME=`date '+%s'` fi if [ ! -z "$TEST_SSH_PORT" ]; then PORT="$TEST_SSH_PORT" else PORT=4242 fi OBJ=$1 if [ "x$OBJ" = "x" ]; then echo '$OBJ not defined' exit 2 fi if [ ! -d $OBJ ]; then echo "not a directory: $OBJ" exit 2 fi SCRIPT=$2 if [ "x$SCRIPT" = "x" ]; then echo '$SCRIPT not defined' exit 2 fi if [ ! -f $SCRIPT ]; then echo "not a file: $SCRIPT" exit 2 fi if $TEST_SHELL -n $SCRIPT; then true else echo "syntax error in $SCRIPT" exit 2 fi unset SSH_AUTH_SOCK # Portable-specific settings. if [ -x /usr/ucb/whoami ]; then USER=`/usr/ucb/whoami` elif whoami >/dev/null 2>&1; then USER=`whoami` elif logname >/dev/null 2>&1; then USER=`logname` else USER=`id -un` fi if test -z "$LOGNAME"; then LOGNAME="${USER}" export LOGNAME fi # Unbreak GNU head(1) _POSIX2_VERSION=199209 export _POSIX2_VERSION case `uname -s 2>/dev/null` in OSF1*) BIN_SH=xpg4 export BIN_SH ;; CYGWIN*) os=cygwin ;; esac # If configure tells us to use a different egrep, create a wrapper function # to call it. This means we don't need to change all the tests that depend # on a good implementation. if test "x${EGREP}" != "x"; then egrep () { ${EGREP} "$@" } fi SRC=`dirname ${SCRIPT}` # defaults SSH=ssh SSHD=sshd SSHAGENT=ssh-agent SSHADD=ssh-add SSHKEYGEN=ssh-keygen SSHKEYSCAN=ssh-keyscan SFTP=sftp SFTPSERVER=/usr/libexec/openssh/sftp-server SSHD_SESSION=/usr/libexec/sshd-session SSHD_AUTH=/usr/libexec/sshd-auth SCP=scp # Set by make_tmpdir() on demand (below). SSH_REGRESS_TMP= # Interop testing PLINK=/usr/local/bin/plink PUTTYGEN=/usr/local/bin/puttygen CONCH=/usr/local/bin/conch DROPBEAR=/usr/local/bin/dropbear DBCLIENT=/usr/local/bin/dbclient DROPBEARKEY=/usr/local/bin/dropbearkey DROPBEARCONVERT=/usr/local/bin/dropbearconvert # So we can override this in Portable. TEST_SHELL="${TEST_SHELL:-/bin/sh}" # Tools used by multiple tests NC=$OBJ/netcat # Always use the one configure tells us to, even if that's empty. #OPENSSL_BIN="${OPENSSL_BIN:-openssl}" if [ "x$TEST_SSH_SSH" != "x" ]; then SSH="${TEST_SSH_SSH}" fi if [ "x$TEST_SSH_SSHD_SESSION" != "x" ]; then SSHD_SESSION="${TEST_SSH_SSHD_SESSION}" fi if [ "x$TEST_SSH_SSHD_AUTH" != "x" ]; then SSHD_AUTH="${TEST_SSH_SSHD_AUTH}" 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 PLINK="${TEST_SSH_PLINK}" fi if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then PUTTYGEN="${TEST_SSH_PUTTYGEN}" fi if [ "x$TEST_SSH_CONCH" != "x" ]; then CONCH="${TEST_SSH_CONCH}" fi if [ "x$TEST_SSH_DROPBEAR" != "x" ]; then DROPBEAR="${TEST_SSH_DROPBEAR}" fi if [ "x$TEST_SSH_DBCLIENT" != "x" ]; then DBCLIENT="${TEST_SSH_DBCLIENT}" fi if [ "x$TEST_SSH_DROPBEARKEY" != "x" ]; then DROPBEARKEY="${TEST_SSH_DROPBEARKEY}" fi if [ "x$TEST_SSH_DROPBEARCONVERT" != "x" ]; then DROPBEARCONVERT="${TEST_SSH_DROPBEARCONVERT}" fi if [ "x$TEST_SSH_PKCS11_HELPER" != "x" ]; then SSH_PKCS11_HELPER="${TEST_SSH_PKCS11_HELPER}" fi if [ "x$TEST_SSH_SK_HELPER" != "x" ]; then SSH_SK_HELPER="${TEST_SSH_SK_HELPER}" fi if [ "x$TEST_SSH_OPENSSL" != "x" ]; then OPENSSL_BIN="${TEST_SSH_OPENSSL}" fi # Path to sshd must be absolute for rexec case "$SSHD" in /*) ;; *) SSHD=`which $SSHD` ;; esac case "$SSH" in /*) ;; *) SSH=`which $SSH` ;; esac case "$SSHAGENT" in /*) ;; *) SSHAGENT=`which $SSHAGENT` ;; esac # Record the actual binaries used. SSH_BIN=${SSH} SSHD_BIN=${SSHD} SSHAGENT_BIN=${SSHAGENT} SSHADD_BIN=${SSHADD} SSHKEYGEN_BIN=${SSHKEYGEN} SSHKEYSCAN_BIN=${SSHKEYSCAN} SFTP_BIN=${SFTP} SFTPSERVER_BIN=${SFTPSERVER} SCP_BIN=${SCP} if [ "x$USE_VALGRIND" != "x" ]; then rm -rf $OBJ/valgrind-out $OBJ/valgrind-vgdb mkdir -p $OBJ/valgrind-out $OBJ/valgrind-vgdb # When using sudo ensure low-priv tests can write pipes and logs. if [ "x$SUDO" != "x" ]; then chmod 777 $OBJ/valgrind-out $OBJ/valgrind-vgdb fi VG_TEST=`basename $SCRIPT .sh` # Some tests are difficult to fix. case "$VG_TEST" in reexec) VG_SKIP=1 ;; sftp-chroot) if [ "x${SUDO}" != "x" ]; then VG_SKIP=1 fi ;; esac if [ x"$VG_SKIP" = "x" ]; then VG_LEAK="--leak-check=no" if [ x"$VALGRIND_CHECK_LEAKS" != "x" ]; then VG_LEAK="--leak-check=full" fi VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*" VG_LOG="$OBJ/valgrind-out/${VG_TEST}." VG_OPTS="--track-origins=yes $VG_LEAK" VG_OPTS="$VG_OPTS --trace-children=yes" VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}" VG_OPTS="$VG_OPTS --vgdb-prefix=$OBJ/valgrind-vgdb/" VG_PATH="valgrind" if [ "x$VALGRIND_PATH" != "x" ]; then VG_PATH="$VALGRIND_PATH" fi VG="$VG_PATH $VG_OPTS" SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH" SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD" SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT" SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD" SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN" SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN" SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}" SCP="$VG --log-file=${VG_LOG}scp.%p $SCP" cat > $OBJ/valgrind-sftp-server.sh << EOF #!/bin/sh exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@" EOF chmod a+rx $OBJ/valgrind-sftp-server.sh SFTPSERVER="$OBJ/valgrind-sftp-server.sh" fi fi # Logfiles. # SSH_LOGFILE should be the debug output of ssh(1) only # SSHD_LOGFILE should be the debug output of sshd(8) only # REGRESS_LOGFILE is the log of progress of the regress test itself. # TEST_SSH_LOGDIR will contain datestamped logs of all binaries run in # chronological order. if [ "x$TEST_SSH_LOGDIR" = "x" ]; then TEST_SSH_LOGDIR=$OBJ/log mkdir -p $TEST_SSH_LOGDIR fi if [ "x$TEST_SSH_LOGFILE" = "x" ]; then TEST_SSH_LOGFILE=$OBJ/ssh.log fi if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then TEST_SSHD_LOGFILE=$OBJ/sshd.log fi if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then TEST_REGRESS_LOGFILE=$OBJ/regress.log fi # If set, keep track of successful tests and skip them them if we've # previously completed that test. if [ "x$TEST_REGRESS_CACHE_DIR" != "x" ]; then if [ ! -d "$TEST_REGRESS_CACHE_DIR" ]; then mkdir -p "$TEST_REGRESS_CACHE_DIR" fi TEST="`basename $SCRIPT .sh`" CACHE="${TEST_REGRESS_CACHE_DIR}/${TEST}.cache" for i in ${SSH} ${SSHD} ${SSHAGENT} ${SSHADD} ${SSHKEYGEN} ${SCP} \ ${SFTP} ${SFTPSERVER} ${SSHKEYSCAN}; do case $i in /*) bin="$i" ;; *) bin="`which $i`" ;; esac if [ "$bin" -nt "$CACHE" ]; then rm -f "$CACHE" fi done if [ -f "$CACHE" ]; then echo ok cached $CACHE exit 0 fi fi # truncate logfiles >$TEST_REGRESS_LOGFILE # Create ssh and sshd wrappers with logging. These create a datestamped # unique file for every invocation so that we can retain all logs from a # given test no matter how many times it's invoked. It also leaves a # symlink with the original name for tests (and people) who look for that. # For ssh, e can't just specify "SSH=ssh -E..." because sftp and scp don't # handle spaces in arguments. scp and sftp like to use -q so we remove those # to preserve our debug logging. In the rare instance where -q is desirable # -qq is equivalent and is not removed. SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh rm -f ${SSHLOGWRAP} cat >$SSHLOGWRAP <>$TEST_REGRESS_LOGFILE echo "Executing: ${SSH} \$@" >>\${logfile} for i in "\$@";do shift;case "\$i" in -q):;; *) set -- "\$@" "\$i";;esac;done rm -f $TEST_SSH_LOGFILE ln -f -s \${logfile} $TEST_SSH_LOGFILE exec ${SSH} -E\${logfile} "\$@" EOD chmod a+rx $OBJ/ssh-log-wrapper.sh REAL_SSH="$SSH" REAL_SSHD="$SSHD" SSH="$SSHLOGWRAP" SSHDLOGWRAP=$OBJ/sshd-log-wrapper.sh rm -f ${SSHDLOGWRAP} cat >$SSHDLOGWRAP <>$TEST_REGRESS_LOGFILE echo "Executing: ${SSHD} \$@" >>\${logfile} exec ${SSHD} -E\${logfile} "\$@" EOD chmod a+rx $OBJ/sshd-log-wrapper.sh ssh_logfile () { tool="$1" timestamp="`$OBJ/timestamp`" logfile="${TEST_SSH_LOGDIR}/${timestamp}.$tool.$$.log" echo "Logging $tool to log \${logfile}" >>$TEST_REGRESS_LOGFILE echo $logfile } # Some test data. We make a copy because some tests will overwrite it. # The tests may assume that $DATA exists and is writable and $COPY does # not exist. Tests requiring larger data files can call increase_datafile_size # [kbytes] to ensure the file is at least that large. DATANAME=data DATA=$OBJ/${DATANAME} cat ${SSH_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 ${SSH_BIN} >>${DATA} done } # these should be used in tests export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP export SSH_PKCS11_HELPER SSH_SK_HELPER #echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP # Portable specific functions which() { saved_IFS="$IFS" IFS=":" for i in $PATH do if [ -x $i/$1 ]; then IFS="$saved_IFS" echo "$i/$1" return 0 fi done IFS="$saved_IFS" echo "$i/$1" return 1 } have_prog() { which "$1" >/dev/null 2>&1 return $? } jot() { awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }" } if [ ! -x "`which rev`" ]; then rev() { awk '{for (i=length; i>0; i--) printf "%s", substr($0, i, 1); print ""}' } fi if [ -x "/usr/xpg4/bin/id" ]; then id() { /usr/xpg4/bin/id $@ } fi # Check whether preprocessor symbols are defined in config.h. config_defined () { str=$1 while test "x$2" != "x" ; do str="$str|$2" shift done egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1 } md5 () { if have_prog md5sum; then md5sum elif have_prog openssl; then openssl md5 elif have_prog cksum; then cksum elif have_prog sum; then sum elif [ -x ${OPENSSL_BIN} ]; then ${OPENSSL_BIN} md5 else wc -c fi } # Some platforms don't have hostname at all, but on others uname -n doesn't # provide the fully qualified name we need, so in the former case we create # our own hostname function. if ! have_prog hostname; then hostname() { uname -n } fi make_tmpdir () { SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \ fatal "failed to create temporary directory" } # End of portable specific functions stop_sshd () { [ -z $PIDFILE ] && return [ -f $PIDFILE ] || return pid=`$SUDO cat $PIDFILE` if [ "X$pid" = "X" ]; then echo "no sshd running" 1>&2 return elif [ $pid -lt 2 ]; then echo "bad pid for sshd: $pid" 1>&2 return fi $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" 1>&2 else echo "sshd died without cleanup" 1>&2 fi exit 1 fi PIDFILE="" } # helper cleanup () { if [ "x$SSH_PID" != "x" ]; then if [ $SSH_PID -lt 2 ]; then echo bad pid for ssh: $SSH_PID else kill $SSH_PID fi fi if [ "x$SSH_REGRESS_TMP" != "x" ]; then rm -rf "$SSH_REGRESS_TMP" fi stop_sshd if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then now=`date '+%s'` elapsed=$(($now - $STARTTIME)) echo elapsed $elapsed `basename $SCRIPT .sh` fi } start_debug_log () { echo "trace: $@" >>$TEST_REGRESS_LOGFILE if [ -d "$TEST_SSH_LOGDIR" ]; then rm -f $TEST_SSH_LOGDIR/* fi } save_debug_log () { testname=`echo $tid | tr ' ' _` tarname="$OBJ/failed-$testname-logs.tar" for logfile in $TEST_SSH_LOGDIR $TEST_REGRESS_LOGFILE \ $TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE; do if [ ! -z "$SUDO" ] && [ -e "$logfile" ]; then $SUDO chown -R $USER $logfile fi done echo $@ >>$TEST_REGRESS_LOGFILE echo $@ >>$TEST_SSH_LOGFILE echo $@ >>$TEST_SSHD_LOGFILE echo "Saving debug logs to $tarname" >>$TEST_REGRESS_LOGFILE (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log # Save all logfiles in a tarball. (cd $OBJ && logfiles="" for i in $TEST_REGRESS_LOGFILE $TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE \ $TEST_SSH_LOGDIR; do if [ -e "`basename $i`" ]; then logfiles="$logfiles `basename $i`" else logfiles="$logfiles $i" fi done tar cf "$tarname" $logfiles) } trace () { start_debug_log $@ if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then echo "$@" fi } verbose () { start_debug_log $@ if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then echo "$@" fi } fail () { save_debug_log "FAIL: $@" RESULT=1 echo "$@" if test "x$TEST_SSH_FAIL_FATAL" != "x" ; then cleanup exit $RESULT fi } fatal () { save_debug_log "FATAL: $@" printf "FATAL: " fail "$@" cleanup exit $RESULT } # Skip remaining tests in script. skip () { echo "SKIPPED: $@" cleanup exit $RESULT } maybe_add_scp_path_to_sshd () { # If we're testing a non-installed scp, add its directory to sshd's # PATH so we can test it. We don't do this for all tests as it # breaks the SetEnv tests. case "$SCP" in /*) PATH_WITH_SCP="`dirname $SCP`:$PATH" echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_config echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_proxy ;; esac } RESULT=0 PIDFILE=$OBJ/pidfile trap fatal 3 2 # create server config cat << EOF > $OBJ/sshd_config StrictModes no Port $PORT AddressFamily inet ListenAddress 127.0.0.1 #ListenAddress ::1 PidFile $PIDFILE AuthorizedKeysFile $OBJ/authorized_keys_%u LogLevel DEBUG3 AcceptEnv _XXX_TEST_* AcceptEnv _XXX_TEST Subsystem sftp $SFTPSERVER SshdSessionPath $SSHD_SESSION SshdAuthPath $SSHD_AUTH PerSourcePenalties no EOF # This may be necessary if /usr/src and/or /usr/obj are group-writable, # but if you aren't careful with permissions then the unit tests could # be abused to locally escalate privileges. if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then echo " StrictModes no" >> $OBJ/sshd_config else # check and warn if excessive permissions are likely to cause failures. unsafe="" dir="${OBJ}" while test ${dir} != "/"; do if test -d "${dir}" && ! test -h "${dir}"; then perms=`ls -ld ${dir}` case "${perms}" in ?????w????*|????????w?*) unsafe="${unsafe} ${dir}" ;; esac fi dir=`dirname ${dir}` done if ! test -z "${unsafe}"; then cat <> $OBJ/sshd_config fi if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config fi # server config for proxy connects cp $OBJ/sshd_config $OBJ/sshd_proxy # allow group-writable directories in proxy-mode echo 'StrictModes no' >> $OBJ/sshd_proxy # create client config cat << EOF > $OBJ/ssh_config Host * Hostname 127.0.0.1 HostKeyAlias localhost-with-alias Port $PORT User $USER GlobalKnownHostsFile $OBJ/known_hosts UserKnownHostsFile $OBJ/known_hosts PubkeyAuthentication yes ChallengeResponseAuthentication no PasswordAuthentication no BatchMode yes StrictHostKeyChecking yes LogLevel DEBUG3 EOF if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS" echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config fi rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER SSH_SK_PROVIDER= if ! config_defined ENABLE_SK; then trace skipping sk-dummy elif [ -f "${SRC}/misc/sk-dummy/obj/sk-dummy.so" ] ; then SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/obj/sk-dummy.so" elif [ -f "${OBJ}/misc/sk-dummy/sk-dummy.so" ] ; then SSH_SK_PROVIDER="${OBJ}/misc/sk-dummy/sk-dummy.so" elif [ -f "${SRC}/misc/sk-dummy/sk-dummy.so" ] ; then SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/sk-dummy.so" fi export SSH_SK_PROVIDER if ! test -z "$SSH_SK_PROVIDER"; then EXTRA_AGENT_ARGS='-P/*' # XXX want realpath(1)... echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/ssh_config echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_config echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_proxy fi export EXTRA_AGENT_ARGS maybe_filter_sk() { if test -z "$SSH_SK_PROVIDER" ; then grep -v ^sk else cat fi } SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk` SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk` for t in ${SSH_KEYTYPES}; do # generate user key if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then trace "generating key type $t" rm -f $OBJ/$t ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ fail "ssh-keygen for $t failed" else trace "using cached key type $t" fi # setup authorized keys cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER echo IdentityFile $OBJ/$t >> $OBJ/ssh_config done for t in ${SSH_HOSTKEY_TYPES}; do # known hosts file for client ( printf 'localhost-with-alias,127.0.0.1,::1 ' cat $OBJ/$t.pub ) >> $OBJ/known_hosts # use key as host key, too (umask 077; $SUDO cp $OBJ/$t $OBJ/host.$t) echo HostKey $OBJ/host.$t >> $OBJ/sshd_config # don't use SUDO for proxy connect echo HostKey $OBJ/$t >> $OBJ/sshd_proxy done chmod 644 $OBJ/authorized_keys_$USER # Activate Twisted Conch tests if the binary is present REGRESS_INTEROP_CONCH=no if test -x "$CONCH" ; then REGRESS_INTEROP_CONCH=yes fi # If PuTTY is present, new enough and we are running a PuTTY test, prepare # keys and configuration. REGRESS_INTEROP_PUTTY=no if test -x "$PUTTYGEN" -a -x "$PLINK" && "$PUTTYGEN" --help 2>&1 | grep -- --new-passphrase >/dev/null; then REGRESS_INTEROP_PUTTY=yes fi case "$SCRIPT" in *putty*) ;; *) REGRESS_INTEROP_PUTTY=no ;; esac puttysetup() { if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then skip "putty interop tests not enabled" fi mkdir -p ${OBJ}/.putty # Add a PuTTY key to authorized_keys rm -f ${OBJ}/putty.rsa2 if ! "$PUTTYGEN" -t rsa -o ${OBJ}/putty.rsa2 \ --random-device=/dev/urandom \ --new-passphrase /dev/null < /dev/null > /dev/null; then echo "Your installed version of PuTTY is too old to support --new-passphrase, skipping test" >&2 exit 1 fi "$PUTTYGEN" -O public-openssh ${OBJ}/putty.rsa2 \ >> $OBJ/authorized_keys_$USER # Convert rsa2 host key to PuTTY format cp $OBJ/ssh-rsa $OBJ/ssh-rsa_oldfmt ${SSHKEYGEN} -p -N '' -m PEM -f $OBJ/ssh-rsa_oldfmt >/dev/null ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/ssh-rsa_oldfmt > \ ${OBJ}/.putty/sshhostkeys ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/ssh-rsa_oldfmt >> \ ${OBJ}/.putty/sshhostkeys rm -f $OBJ/ssh-rsa_oldfmt # Setup proxied session mkdir -p ${OBJ}/.putty/sessions rm -f ${OBJ}/.putty/sessions/localhost_proxy echo "Protocol=ssh" >> ${OBJ}/.putty/sessions/localhost_proxy echo "HostName=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyTelnetCommand=${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyLocalhost=1" >> ${OBJ}/.putty/sessions/localhost_proxy PUTTYVER="`${PLINK} --version | awk '/plink: Release/{print $3}'`" PUTTYMAJORVER="`echo ${PUTTYVER} | cut -f1 -d.`" PUTTYMINORVER="`echo ${PUTTYVER} | cut -f2 -d.`" verbose "plink version ${PUTTYVER} major ${PUTTYMAJORVER} minor ${PUTTYMINORVER}" # Re-enable ssh-rsa on older PuTTY versions since they don't do newer # key types. if [ "$PUTTYMAJORVER" -eq "0" ] && [ "$PUTTYMINORVER" -lt "76" ]; then echo "HostKeyAlgorithms +ssh-rsa" >> ${OBJ}/sshd_proxy echo "PubkeyAcceptedKeyTypes +ssh-rsa" >> ${OBJ}/sshd_proxy fi if [ "$PUTTYMAJORVER" -eq "0" ] && [ "$PUTTYMINORVER" -le "64" ]; then echo "KexAlgorithms +diffie-hellman-group14-sha1" \ >>${OBJ}/sshd_proxy fi PUTTYDIR=${OBJ}/.putty export PUTTYDIR } REGRESS_INTEROP_DROPBEAR=no if test -x "$DROPBEARKEY" -a -x "$DBCLIENT" -a -x "$DROPBEARCONVERT"; then REGRESS_INTEROP_DROPBEAR=yes fi case "$SCRIPT" in *dropbear*) ;; *) REGRESS_INTEROP_DROPBEAR=no ;; esac if test "$REGRESS_INTEROP_DROPBEAR" = "yes" ; then trace Create dropbear keys and add to authorized_keys mkdir -p $OBJ/.dropbear $OBJ/.ssh awk '{print "somehost "$2" "$3}' $OBJ/known_hosts >$OBJ/.ssh/known_hosts kt="ed25519" for i in dss rsa ecdsa; do if $SSH -Q key-plain | grep "$i" >/dev/null; then kt="$kt $i" else rm -f "$OBJ/.dropbear/id_$i" fi done for i in $kt; do if [ ! -f "$OBJ/.dropbear/id_$i" ]; then verbose Create dropbear key type $i $DROPBEARKEY -t $i -f $OBJ/.dropbear/id_$i \ >/dev/null 2>&1 fi $DROPBEARCONVERT dropbear openssh $OBJ/.dropbear/id_$i \ $OBJ/.dropbear/ossh.id_$i >/dev/null 2>&1 $SSHKEYGEN -y -f $OBJ/.dropbear/ossh.id_$i \ >>$OBJ/authorized_keys_$USER rm -f $OBJ/.dropbear/id_$i.pub $OBJ/.dropbear/ossh.id_$i done fi # create a proxy version of the client config ( cat $OBJ/ssh_config echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${TEST_SSH_SSHD_ENV} ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy ) > $OBJ/ssh_proxy # check proxy config ${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" # extract proxycommand into separate shell script for use by Dropbear. echo '#!/bin/sh' >$OBJ/ssh_proxy.sh awk '/^proxycommand/' $OBJ/ssh_proxy | sed 's/^proxycommand//' \ >>$OBJ/ssh_proxy.sh chmod a+x $OBJ/ssh_proxy.sh start_sshd () { PIDFILE=$OBJ/pidfile # start sshd logfile="${TEST_SSH_LOGDIR}/sshd.`$OBJ/timestamp`.$$.log" $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" ${TEST_SSH_SSHD_ENV} \ ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" ${TEST_SSH_SSHD_ENV} \ ${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 rm -f ${TEST_SSHD_LOGFILE} ln -f -s ${logfile} $TEST_SSHD_LOGFILE test -f $PIDFILE || fatal "no sshd running on port $PORT" } # Find a PKCS#11 library. p11_find_lib() { TEST_SSH_PKCS11="" for _lib in "$@" ; do if test -f "$_lib" ; then TEST_SSH_PKCS11="$_lib" return fi done } # Perform PKCS#11 setup: prepares a softhsm2 token configuration, generated # keys and loads them into the virtual token. PKCS11_OK= export PKCS11_OK p11_setup() { p11_find_lib \ /usr/local/lib/softhsm/libsofthsm2.so \ /usr/lib64/pkcs11/libsofthsm2.so \ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so test -z "$TEST_SSH_PKCS11" && return 1 verbose "using token library $TEST_SSH_PKCS11" TEST_SSH_PIN=1234 TEST_SSH_SOPIN=12345678 if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}" export SSH_PKCS11_HELPER fi # setup environment for softhsm2 token SSH_SOFTHSM_DIR=$OBJ/SOFTHSM export SSH_SOFTHSM_DIR rm -rf $SSH_SOFTHSM_DIR TOKEN=$SSH_SOFTHSM_DIR/tokendir mkdir -p $TOKEN SOFTHSM2_CONF=$SSH_SOFTHSM_DIR/softhsm2.conf export SOFTHSM2_CONF cat > $SOFTHSM2_CONF << EOF # SoftHSM v2 configuration file directories.tokendir = ${TOKEN} objectstore.backend = file # ERROR, WARNING, INFO, DEBUG log.level = DEBUG # If CKF_REMOVABLE_DEVICE flag should be set slots.removable = false EOF out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN") slot=$(echo -- $out | sed 's/.* //') trace "generating keys" # RSA key RSA=${SSH_SOFTHSM_DIR}/RSA RSAP8=${SSH_SOFTHSM_DIR}/RSAP8 $OPENSSL_BIN genpkey -algorithm rsa > $RSA 2>/dev/null || \ fatal "genpkey RSA fail" $OPENSSL_BIN pkcs8 -nocrypt -in $RSA > $RSAP8 || fatal "pkcs8 RSA fail" softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" \ --import $RSAP8 >/dev/null || fatal "softhsm import RSA fail" chmod 600 $RSA ssh-keygen -y -f $RSA > ${RSA}.pub # ECDSA key ECPARAM=${SSH_SOFTHSM_DIR}/ECPARAM EC=${SSH_SOFTHSM_DIR}/EC ECP8=${SSH_SOFTHSM_DIR}/ECP8 $OPENSSL_BIN genpkey -genparam -algorithm ec \ -pkeyopt ec_paramgen_curve:prime256v1 > $ECPARAM || \ fatal "param EC fail" $OPENSSL_BIN genpkey -paramfile $ECPARAM > $EC || \ fatal "genpkey EC fail" $OPENSSL_BIN pkcs8 -nocrypt -in $EC > $ECP8 || fatal "pkcs8 EC fail" softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" \ --import $ECP8 >/dev/null || fatal "softhsm import EC fail" chmod 600 $EC ssh-keygen -y -f $EC > ${EC}.pub # Prepare askpass script to load PIN. PIN_SH=$SSH_SOFTHSM_DIR/pin.sh cat > $PIN_SH << EOF #!/bin/sh echo "${TEST_SSH_PIN}" EOF chmod 0700 "$PIN_SH" PKCS11_OK=yes return 0 } # Peforms ssh-add with the right token PIN. p11_ssh_add() { env SSH_ASKPASS="$PIN_SH" SSH_ASKPASS_REQUIRE=force ${SSHADD} "$@" } # source test body . $SCRIPT # kill sshd cleanup if [ "x$USE_VALGRIND" != "x" ]; then # If there is an EXIT trap handler, invoke it now. # Some tests set these to clean up processes such as ssh-agent. We # need to wait for all valgrind processes to complete so we can check # their logs, but since the EXIT traps are not invoked until # test-exec.sh exits, waiting here will deadlock. # This is not very portable but then neither is valgrind itself. # As a bonus, dash (as used on the runners) has a "trap" that doesn't # work in a pipeline (hence the temp file) or a subshell. exithandler="" trap >/tmp/trap.$$ && exithandler=$(cat /tmp/trap.$$ | \ awk -F "'" '/EXIT$/{print $2}') rm -f /tmp/trap.$$ if [ "x${exithandler}" != "x" ]; then verbose invoking EXIT trap handler early: ${exithandler} eval "${exithandler}" trap '' EXIT fi # wait for any running process to complete wait; sleep 1 VG_RESULTS=$(find $OBJ/valgrind-out -type f -print) VG_RESULT_COUNT=0 VG_FAIL_COUNT=0 for i in $VG_RESULTS; do if grep "ERROR SUMMARY" $i >/dev/null; then VG_RESULT_COUNT=$(($VG_RESULT_COUNT + 1)) if ! grep "ERROR SUMMARY: 0 errors" $i >/dev/null; then VG_FAIL_COUNT=$(($VG_FAIL_COUNT + 1)) RESULT=1 verbose valgrind failure $i cat $i fi fi done if [ x"$VG_SKIP" != "x" ]; then verbose valgrind skipped else verbose valgrind results $VG_RESULT_COUNT failures $VG_FAIL_COUNT fi fi if [ $RESULT -eq 0 ]; then verbose ok $tid if [ "x$CACHE" != "x" ]; then touch "$CACHE" fi else echo failed $tid fi exit $RESULT openssh-10.0p1/regress/PaxHeaders.10889/timestamp.c100644 001750 001750 0000000003614775415623 0016775xustar0030 atime=1744182234.722485204 openssh-10.0p1/regress/timestamp.c010064400017500001750000000026441477541562300153660ustar00djmdjm/* * Copyright (c) 2023 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. */ /* $OpenBSD: timestamp.c,v 1.1 2023/03/01 09:29:32 dtucker Exp $ */ /* * Print a microsecond-granularity timestamp to stdout in an ISO8601-ish * format, which we can then use as the first component of the log file * so that they'll sort into chronological order. */ #include #include #include #include int main(void) { struct timeval tv; struct tm *tm; char buf[1024]; if (gettimeofday(&tv, NULL) != 0) exit(1); if ((tm = localtime(&tv.tv_sec)) == NULL) exit(2); if (strftime(buf, sizeof buf, "%Y%m%dT%H%M%S", tm) <= 0) exit(3); printf("%s.%06d\n", buf, (int)tv.tv_usec); exit(0); } openssh-10.0p1/regress/PaxHeaders.10889/transfer.sh100644 001750 001750 0000000003614775415623 0017006xustar0030 atime=1744182234.722485204 openssh-10.0p1/regress/transfer.sh010064400017500001750000000011071477541562300153700ustar00djmdjm# $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} openssh-10.0p1/regress/PaxHeaders.10889/unittests040755 001750 001750 0000000003614775415623 0016621xustar0030 atime=1744182234.722485204 openssh-10.0p1/regress/unittests004075500017500001750000000000001477541562300151775ustar00djmdjmopenssh-10.0p1/regress/unittests/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0020330xustar0030 atime=1744182234.722485204 openssh-10.0p1/regress/unittests/Makefile010064400017500001750000000003011477541562300167050ustar00djmdjm# $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion SUBDIR+=authopt misc sshsig .include openssh-10.0p1/regress/unittests/PaxHeaders.10889/Makefile.inc100644 001750 001750 0000000003614775415623 0021100xustar0030 atime=1744182234.722485204 openssh-10.0p1/regress/unittests/Makefile.inc010064400017500001750000000041331477541562300174640ustar00djmdjm# $OpenBSD: Makefile.inc,v 1.16 2024/01/11 01:45:58 djm Exp $ .include .include # User-settable options UNITTEST_FAST?= no # Skip slow tests (e.g. less intensive fuzzing). UNITTEST_SLOW?= no # Include slower tests (e.g. more intensive fuzzing). UNITTEST_VERBOSE?= no # Verbose test output (inc. per-test names). MALLOC_OPTIONS?= CFGJRSUX TEST_ENV?= MALLOC_OPTIONS=${MALLOC_OPTIONS} # XXX detect from ssh binary? OPENSSL?= yes DSAKEY?= yes .if (${DSAKEY:L} == "yes") CFLAGS+= -DWITH_DSA .endif .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 openssh-10.0p1/regress/unittests/PaxHeaders.10889/authopt040755 001750 001750 0000000003614775415623 0020305xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt004075500017500001750000000000001477541562300166635ustar00djmdjmopenssh-10.0p1/regress/unittests/authopt/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0022014xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/Makefile010064400017500001750000000014251477541562300204010ustar00djmdjm# $OpenBSD: Makefile,v 1.7 2023/01/15 23:35:10 djm Exp $ PROG=test_authopt SRCS=tests.c SRCS+=auth-options.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c 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 openssh-10.0p1/regress/unittests/authopt/PaxHeaders.10889/testdata040755 001750 001750 0000000003614775415623 0022116xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata004075500017500001750000000000001477541562300204745ustar00djmdjmopenssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/all_permit.cert100644 001750 001750 0000000003614775415623 0025174xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/all_permit.cert010064400017500001750000000011671477541562300235640ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIOv/h7mJS1WkRHukSvqPwKDiNVrcib/VqBLpbHW6xjWCAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQNe1XDN+J4Eb82TH5J5sYypcabocufjTFRfpU57K+csRP41Yo1FCSEWx95ilUuNvK9Iv3yFDOeVPzdqRqzWoHwE= user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/bad_sourceaddr.cert100644 001750 001750 0000000003614775415623 0026005xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/bad_sourceaddr.cert010064400017500001750000000012371477541562300243730ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAILFEJyunlz9scYU3mwbOEJoSSkeO1z20uNBw13tEn+lJAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAHwAAAA5zb3VyY2UtYWRkcmVzcwAAAAkAAAAFeHh4eHgAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEA5xY/OEAJ3tgg8/KJqaBR5KMdYYRDiMJ6u4VKS9lQOV1HJQvDDvjj3F5k53BIqTJRVQx242YWs+B3C4db/uLgB user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/force_command.cert100644 001750 001750 0000000003614775415623 0025640xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/force_command.cert010064400017500001750000000012331477541562300242220ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJkpCeqaVl6qnp7qa90KehAmHFecx3HW8HZQ22KEqeKBAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAHAAAAA1mb3JjZS1jb21tYW5kAAAABwAAAANmb28AAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAxbhjgbXvfEumRP1E7VH8nUfuJyVlDChhCxiPg9Nvb9PFK8cHdDUEybDCzKCsIDieRc3mtLTyEu7Kb52va/B4C user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/host.cert100644 001750 001750 0000000003614775415623 0024021xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/host.cert010064400017500001750000000007131477541562300224050ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFWMw3ftP29RSefnxQwdvK1KiE2G9Y7rPRrJ7ZsrDiOeAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAACAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAKTMqwPkaBg23RS7/aj347dc2kY4bWt/sHwzREYSrKRqZ5RNBnSvZOQ8m5euMCEuf92bZ8VJEdF653jRiW6VoBA== user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/mktestdata.sh100644 001750 001750 0000000003614775415623 0024662xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/mktestdata.sh010064400017500001750000000025141477541562300232470ustar00djmdjm#/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 openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/no_agentfwd.cert100644 001750 001750 0000000003614775415623 0025337xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/no_agentfwd.cert010064400017500001750000000011171477541562300237220ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIL2qEsLCVtKaBkbCrZicxbPUorcHHrQ8yw5h/26krTOlAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGMAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAdRhISpol01OwV30g39PM/JD1t35muskX4lyCcGpFQ08GQtBuHE/hABOp6apbGBJIC7CZYYF+uHkD7PfGU3NPAQ== user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/no_permit.cert100644 001750 001750 0000000003614775415623 0025040xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/no_permit.cert010064400017500001750000000007131477541562300234240ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIGVQtVgp9sD4sc8esIhVWbZaM8d0NxpX3UbEVzTHm9feAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAIKlI0TqqraKjYTjIuKhwoxAV/XnzWRJHq8lNs4aj5yDb84un2xXDF/0vXoLjPgVcLgEbksBKKn0i4whp+xn9Ag== user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/no_portfwd.cert100644 001750 001750 0000000003614775415623 0025225xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/no_portfwd.cert010064400017500001750000000011171477541562300236100ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIE6gC/QjjuzGWVDkr8ZyaHhja80V+lKLC/MvmEFa+CEBAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGQAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQEzpgckYlfc1BK1ir0reDSXo9OIDx4UoDMrNXrFO6I44NXoJJ4TlUUJH07WcKp/Xp5ESCdyVZtqwgHQxZr0+PwI= user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/no_pty.cert100644 001750 001750 0000000003614775415623 0024354xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/no_pty.cert010064400017500001750000000011371477541562300227410ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFFjhISpSDR3blDejuCf2T9Fe4aHW53jG7KOH2PV/E7jAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAHAAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQF5c4BdxVYgqbMGAep414IGFK4deCFBCeNUTOLpKodrfb1M0gS4d2qoeMxZvMv5yMf/viKl/gallHzEmcrEcIQY= user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/no_user_rc.cert100644 001750 001750 0000000003614775415623 0025202xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/no_user_rc.cert010064400017500001750000000011331477541562300235630ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFUM0VLATkYh05QeS5uuhB1X50NMom3jTWeQUmrPQ1FwAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGwAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAcmJ3c2FCKJL9BCLv1Ij+uN1N+NWZmMXYionsSkv42Go4pMZiH3g8UfTd+OKq9Q7GAcCzGXa///6Dr/wqFssoDA== user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/no_x11fwd.cert100644 001750 001750 0000000003614775415623 0024652xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/no_x11fwd.cert010064400017500001750000000011171477541562300232350ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIPRKPAP+b5S+4zihdgoJrYNcMovFBgKZaJupIhN1kUvkAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGUAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECMzj6VDfT+BJmIEo1qUKdr8VDLExF92K7KkbNxTH77n7uip7TL24HDfXjYBCvqxSSn9KAGBhnWsIC/GPx6A+cP user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/only_agentfwd.cert100644 001750 001750 0000000003614775415623 0025704xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/only_agentfwd.cert010064400017500001750000000007631477541562300242750ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIOvJ28yW5uvA7yxE3ySuyFvPjcRYKAr03CYr4okGTNIFAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB8AAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQEG2uTgmOSk9dJ0s/Ol1EIERXFP9PF6AauF9t5jBMSthNyvSANSrC/1EIaf4TV5kMYfhZxJXoS0XHQjGndcq2AE= user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/only_portfwd.cert100644 001750 001750 0000000003614775415623 0025572xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/only_portfwd.cert010064400017500001750000000007631477541562300241630ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIGPoYoExiSyHMyDEvOFgoNZXk5z91u7xq/7357X23TotAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB4AAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAHN3YnwipcbDKVn+PObGSoaT9rwlau+yrPYZ50oetvCKng3RMjGaV+roqlv0vjjLcxE9J4Y0ti+9MXtQ0D7beBA== user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/only_pty.cert100644 001750 001750 0000000003614775415623 0024721xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/only_pty.cert010064400017500001750000000007431477541562300233100ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAILvocWYto5Lg7P46YLbe7U4/b2h9Lr5rWqMZ4Cj4ra7RAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAABIAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABASv2xQvp+Y6E8dCf5pzg3MZaan5bl1ToYXNcmQ3ysGrk9Djkcu8m3TytDpF471KmUejxy/iF4xjs9CDpk7h+SBQ== user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/only_user_rc.cert100644 001750 001750 0000000003614775415623 0025547xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/only_user_rc.cert010064400017500001750000000007471477541562300241420ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJwsRZQ7kx4A8AQ0q/G/3i6sHM48kr4TxJtTcyy3lZAPAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAABYAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQDhgEXsvoHr21XrxmiZq/sIjWeYapp11XvEVkkTBPVhBnPwtrrUeJbPmGs3gmJkQdv8BYajYpT7TXEX8GvEeLwU= user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/only_x11fwd.cert100644 001750 001750 0000000003614775415623 0025217xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/only_x11fwd.cert010064400017500001750000000007571477541562300236130ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIDAhZFZBl3eu8Qa8I5BaHCz/mpH8xCjaPusBwo1eJ9OGAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB0AAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDysfgbhniX/zdA8576rrDJpaO2D7QtQse2KWIM9XmREPkLKeP6FKiXKKFcPQiMyV28rptfvK8bBXAiOvITSUgL user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/sourceaddr.cert100644 001750 001750 0000000003614775415623 0025177xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/sourceaddr.cert010064400017500001750000000012631477541562300235640ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJ54qqoPs87gtjN1aJoLUn7ZTYUtcaGxkzLyJvRkYG7nAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAALgAAAA5zb3VyY2UtYWRkcmVzcwAAABgAAAAUMTI3LjAuMC4xLzMyLDo6MS8xMjgAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAppSUKQ/a9tw/HgIazWceCO3d48GU7mkV4iQMpWWs2nB1dFryY1GDtZrBggAjMviwmBXyM3jIk5vxJDINZXGQJ user key openssh-10.0p1/regress/unittests/authopt/testdata/PaxHeaders.10889/unknown_critical.cert100644 001750 001750 0000000003614775415623 0026415xustar0030 atime=1744182234.723461671 openssh-10.0p1/regress/unittests/authopt/testdata/unknown_critical.cert010064400017500001750000000012171477541562300250010ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIjs/wRAB/p5QShSfqoU9cWnCLT3lSveUirk61A27KxVAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAEwAAAARibGFoAAAABwAAAANmb28AAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDix3FV7JIBuHNAwtZOVIqGBq8lqhnEwP51DqPA43qt+Tzynm56EWxuFzgGehBPF3L8gl+fVqxIJmiQ9iHB0LUD user key openssh-10.0p1/regress/unittests/authopt/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021662xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/authopt/tests.c010064400017500001750000000417761477541562300202640ustar00djmdjm/* $OpenBSD: tests.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for keys options functions. * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/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("environment", "environment=\"foo=1\",environment=\"foo=2\"", env, nenv, "foo=1"); ARRAY_TEST("permitopen", "permitopen=\"foo:123\",permitopen=\"bar:*\"", permitopen, npermitopen, "foo:123,bar:*"); #undef ARRAY_TEST 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(); } openssh-10.0p1/regress/unittests/PaxHeaders.10889/bitmap040755 001750 001750 0000000003614775415623 0020075xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/bitmap004075500017500001750000000000001477541562300164535ustar00djmdjmopenssh-10.0p1/regress/unittests/bitmap/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021604xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/bitmap/Makefile010064400017500001750000000004001477541562300201610ustar00djmdjm# $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 openssh-10.0p1/regress/unittests/bitmap/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021452xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/bitmap/tests.c010064400017500001750000000060331477541562300200370ustar00djmdjm/* $OpenBSD: tests.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for bitmap.h bitmap API * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #ifdef WITH_OPENSSL #include #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 } openssh-10.0p1/regress/unittests/PaxHeaders.10889/conversion040755 001750 001750 0000000003614775415623 0021006xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/conversion004075500017500001750000000000001477541562300173645ustar00djmdjmopenssh-10.0p1/regress/unittests/conversion/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0022515xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/conversion/Makefile010064400017500001750000000006451477541562300211050ustar00djmdjm# $OpenBSD: Makefile,v 1.4 2021/01/09 12:24:30 dtucker 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 SRCS+=match.c addr.c addrmatch.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} env ${TEST_ENV} ./${PROG} .include openssh-10.0p1/regress/unittests/conversion/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0022363xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/conversion/tests.c010064400017500001750000000024231477541562300207470ustar00djmdjm/* $OpenBSD: tests.c,v 1.4 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for conversions * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "misc.h" void tests(void) { char buf[1024]; TEST_START("conversion_convtime"); ASSERT_INT_EQ(convtime("0"), 0); ASSERT_INT_EQ(convtime("1"), 1); ASSERT_INT_EQ(convtime("1S"), 1); /* from the examples in the comment above the function */ ASSERT_INT_EQ(convtime("90m"), 5400); ASSERT_INT_EQ(convtime("1h30m"), 5400); ASSERT_INT_EQ(convtime("2d"), 172800); ASSERT_INT_EQ(convtime("1w"), 604800); /* negative time is not allowed */ ASSERT_INT_EQ(convtime("-7"), -1); ASSERT_INT_EQ(convtime("-9d"), -1); /* overflow */ snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX); ASSERT_INT_EQ(convtime(buf), INT_MAX); snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX + 1); ASSERT_INT_EQ(convtime(buf), -1); /* overflow with multiplier */ snprintf(buf, sizeof buf, "%lluM", (unsigned long long)INT_MAX/60 + 1); ASSERT_INT_EQ(convtime(buf), -1); ASSERT_INT_EQ(convtime("1000000000000000000000w"), -1); TEST_DONE(); } openssh-10.0p1/regress/unittests/PaxHeaders.10889/hostkeys040755 001750 001750 0000000003614775415623 0020472xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/hostkeys004075500017500001750000000000001477541562300170505ustar00djmdjmopenssh-10.0p1/regress/unittests/hostkeys/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0022201xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/hostkeys/Makefile010064400017500001750000000014331477541562300205650ustar00djmdjm# $OpenBSD: Makefile,v 1.10 2023/01/15 23:35:10 djm 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+=addr.c addrmatch.c bitmap.c hostfile.c SRCS+=ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c SRCS+=ssh-ed25519-sk.c sk-usbhid.c SRCS+=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 openssh-10.0p1/regress/unittests/hostkeys/PaxHeaders.10889/mktestdata.sh100644 001750 001750 0000000003614775415623 0023236xustar0030 atime=1744182234.724438118 openssh-10.0p1/regress/unittests/hostkeys/mktestdata.sh010064400017500001750000000045541477541562300216310ustar00djmdjm#!/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 openssh-10.0p1/regress/unittests/hostkeys/PaxHeaders.10889/test_iterate.c100644 001750 001750 0000000003614775415623 0023401xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/test_iterate.c010064400017500001750000000603331477541562300217710ustar00djmdjm/* $OpenBSD: test_iterate.c,v 1.9 2024/01/11 01:45:58 djm Exp $ */ /* * Regress test for hostfile.h hostkeys_foreach() * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #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_DSA if (expected->l.keytype == KEY_DSA || expected->no_parse_keytype == KEY_DSA) skip = 1; #endif #ifndef WITH_OPENSSL if (expected->l.keytype == KEY_DSA || expected->no_parse_keytype == KEY_DSA || expected->l.keytype == KEY_RSA || 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_DSA if (expected[i].l.keytype == KEY_DSA) continue; #endif #ifndef WITH_OPENSSL switch (expected[i].l.keytype) { case KEY_RSA: case KEY_DSA: case KEY_ECDSA: continue; } #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 */ 0, /* note */ } }, { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, 2, HKF_STATUS_OK, 0, NULL, MRK_NONE, "sisyphus.example.com", NULL, KEY_DSA, NULL, /* filled at runtime */ "DSA #1", 0, } }, { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, 3, HKF_STATUS_OK, 0, NULL, MRK_NONE, "sisyphus.example.com", NULL, KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #1", 0, } }, { "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", 0, } }, { "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", 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 6, HKF_STATUS_COMMENT, 0, "", MRK_NONE, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, { 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, 0, } }, { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, 8, HKF_STATUS_OK, 0, NULL, MRK_NONE, "prometheus.example.com,192.0.2.1,2001:db8::1", NULL, KEY_DSA, NULL, /* filled at runtime */ "DSA #2", 0, } }, { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, 9, 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", 0, } }, { "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", 0, } }, { "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", 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 12, HKF_STATUS_COMMENT, 0, "", MRK_NONE, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, { 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, 0, } }, { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, 14, HKF_STATUS_OK, 0, NULL, MRK_NONE, "*.example.com,192.0.2.*,2001:*", NULL, KEY_DSA, NULL, /* filled at runtime */ "DSA #3", 0, } }, { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, 15, HKF_STATUS_OK, 0, NULL, MRK_NONE, "*.example.com,192.0.2.*,2001:*", NULL, KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #3", 0, } }, { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, 16, HKF_STATUS_OK, 0, NULL, MRK_NONE, "*.example.com,192.0.2.*,2001:*", NULL, KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #3", 0, } }, { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, 17, HKF_STATUS_OK, 0, NULL, MRK_NONE, "*.example.com,192.0.2.*,2001:*", NULL, KEY_RSA, NULL, /* filled at runtime */ "RSA #3", 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 18, HKF_STATUS_COMMENT, 0, "", MRK_NONE, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, { 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, 0, } }, { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, 20, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_DSA, NULL, /* filled at runtime */ "DSA #5", 0, } }, { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, 21, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #5", 0, } }, { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, 22, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #5", 0, } }, { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, 23, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_RSA, NULL, /* filled at runtime */ "RSA #5", 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 24, HKF_STATUS_COMMENT, 0, "", MRK_NONE, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, /* * 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", 0, } }, { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, 26, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_DSA, NULL, /* filled at runtime */ "DSA #6", 0, } }, { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, 27, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_DSA, NULL, /* filled at runtime */ "DSA #6", 0, } }, { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, 28, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #6", 0, } }, { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, 29, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #6", 0, } }, { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, 30, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #6", 0, } }, { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, 31, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #6", 0, } }, { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, 32, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #6", 0, } }, { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, 33, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #6", 0, } }, { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, 34, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_RSA, NULL, /* filled at runtime */ "RSA #6", 0, } }, { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, 35, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_RSA, NULL, /* filled at runtime */ "RSA #6", 0, } }, { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, 36, HKF_STATUS_OK, 0, NULL, MRK_NONE, NULL, NULL, KEY_RSA, NULL, /* filled at runtime */ "RSA #6", 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 37, HKF_STATUS_COMMENT, 0, "", MRK_NONE, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 38, HKF_STATUS_COMMENT, 0, "", MRK_NONE, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, { 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, 0, } }, { "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", 0, } }, { "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", 0, } }, { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, { NULL, 42, HKF_STATUS_OK, 0, NULL, MRK_CA, "*.example.com", NULL, KEY_DSA, NULL, /* filled at runtime */ "DSA #4", 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 43, HKF_STATUS_COMMENT, 0, "", MRK_NONE, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, { 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, 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, 45, HKF_STATUS_INVALID, 0, NULL, MRK_ERROR, NULL, NULL, KEY_UNSPEC, NULL, NULL, 0, } }, { 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, 0, } }, { 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, 0, } }, { 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, 0, } }, { 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, 0, } }, { 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, 0, } }, }; 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); } openssh-10.0p1/regress/unittests/hostkeys/PaxHeaders.10889/testdata040755 001750 001750 0000000003614775415623 0022303xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata004075500017500001750000000000001477541562300206615ustar00djmdjmopenssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/dsa_1.pub100644 001750 001750 0000000003614775415623 0024051xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/dsa_1.pub010064400017500001750000000011241477541562300224320ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/dsa_2.pub100644 001750 001750 0000000003614775415623 0024052xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/dsa_2.pub010064400017500001750000000011241477541562300224330ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/dsa_3.pub100644 001750 001750 0000000003614775415623 0024053xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/dsa_3.pub010064400017500001750000000011241477541562300224340ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/dsa_4.pub100644 001750 001750 0000000003614775415623 0024054xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/dsa_4.pub010064400017500001750000000011241477541562300224350ustar00djmdjmssh-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 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/dsa_5.pub100644 001750 001750 0000000003614775415623 0024055xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/dsa_5.pub010064400017500001750000000011241477541562300224360ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/dsa_6.pub100644 001750 001750 0000000003614775415623 0024056xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/dsa_6.pub010064400017500001750000000011241477541562300224370ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ecdsa_1.pub100644 001750 001750 0000000003614775415623 0024361xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/ecdsa_1.pub010064400017500001750000000003261477541562300227450ustar00djmdjmecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ecdsa_2.pub100644 001750 001750 0000000003614775415623 0024362xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/ecdsa_2.pub010064400017500001750000000004061477541562300227450ustar00djmdjmecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ecdsa_3.pub100644 001750 001750 0000000003614775415623 0024363xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/ecdsa_3.pub010064400017500001750000000002521477541562300227450ustar00djmdjmecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ecdsa_4.pub100644 001750 001750 0000000003614775415623 0024364xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/ecdsa_4.pub010064400017500001750000000002521477541562300227460ustar00djmdjmecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ecdsa_5.pub100644 001750 001750 0000000003614775415623 0024365xustar0030 atime=1744182234.725415016 openssh-10.0p1/regress/unittests/hostkeys/testdata/ecdsa_5.pub010064400017500001750000000002521477541562300227470ustar00djmdjmecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ecdsa_6.pub100644 001750 001750 0000000003614775415623 0024366xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/ecdsa_6.pub010064400017500001750000000002521477541562300227500ustar00djmdjmecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ed25519_1.pub100644 001750 001750 0000000003614775415623 0024300xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/ed25519_1.pub010064400017500001750000000001341477541562300226610ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ed25519_2.pub100644 001750 001750 0000000003614775415623 0024301xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/ed25519_2.pub010064400017500001750000000001341477541562300226620ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ed25519_3.pub100644 001750 001750 0000000003614775415623 0024302xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/ed25519_3.pub010064400017500001750000000001341477541562300226630ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ed25519_4.pub100644 001750 001750 0000000003614775415623 0024303xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/ed25519_4.pub010064400017500001750000000001341477541562300226640ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ed25519_5.pub100644 001750 001750 0000000003614775415623 0024304xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/ed25519_5.pub010064400017500001750000000001341477541562300226650ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/ed25519_6.pub100644 001750 001750 0000000003614775415623 0024305xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/ed25519_6.pub010064400017500001750000000001341477541562300226660ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/known_hosts100644 001750 001750 0000000003614775415623 0024651xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/known_hosts010064400017500001750000000257251477541562300232470ustar00djmdjm# 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== openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa1_1.pub100644 001750 001750 0000000003614775415623 0024150xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa1_1.pub010064400017500001750000000005111477541562300225300ustar00djmdjm1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa1_2.pub100644 001750 001750 0000000003614775415623 0024151xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa1_2.pub010064400017500001750000000005111477541562300225310ustar00djmdjm1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa1_3.pub100644 001750 001750 0000000003614775415623 0024152xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa1_3.pub010064400017500001750000000005111477541562300225320ustar00djmdjm1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa1_4.pub100644 001750 001750 0000000003614775415623 0024153xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa1_4.pub010064400017500001750000000005111477541562300225330ustar00djmdjm1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa1_5.pub100644 001750 001750 0000000003614775415623 0024154xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa1_5.pub010064400017500001750000000005111477541562300225340ustar00djmdjm1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa1_6.pub100644 001750 001750 0000000003614775415623 0024155xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa1_6.pub010064400017500001750000000005111477541562300225350ustar00djmdjm1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa_1.pub100644 001750 001750 0000000003614775415623 0024067xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa_1.pub010064400017500001750000000003341477541562300224520ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa_2.pub100644 001750 001750 0000000003614775415623 0024070xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa_2.pub010064400017500001750000000003341477541562300224530ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa_3.pub100644 001750 001750 0000000003614775415623 0024071xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa_3.pub010064400017500001750000000003341477541562300224540ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa_4.pub100644 001750 001750 0000000003614775415623 0024072xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa_4.pub010064400017500001750000000003341477541562300224550ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDI8AdjBAozcdRnIikVlt69iyDHKyrtxmpdkbRy9bWaL86OH+PTmLUk5e+T/ufiakpeE2pm0hkE3e4Sh/FsY+rsQdRoraWVNFfchcMeVlKvuy5RZN0ElvmaQebOJUeNeBn2LLw8aL8bJ4CP/bQRKrmrSSqjz3+4H9YNVyyk1OGBPQ== RSA #4 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa_5.pub100644 001750 001750 0000000003614775415623 0024073xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa_5.pub010064400017500001750000000003341477541562300224560ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 openssh-10.0p1/regress/unittests/hostkeys/testdata/PaxHeaders.10889/rsa_6.pub100644 001750 001750 0000000003614775415623 0024074xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/testdata/rsa_6.pub010064400017500001750000000003341477541562300224570ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 openssh-10.0p1/regress/unittests/hostkeys/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0022047xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/hostkeys/tests.c010064400017500001750000000003741477541562300204360ustar00djmdjm/* $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(); } openssh-10.0p1/regress/unittests/PaxHeaders.10889/kex040755 001750 001750 0000000003614775415623 0017410xustar0030 atime=1744182234.726391433 openssh-10.0p1/regress/unittests/kex004075500017500001750000000000001477541562300157665ustar00djmdjmopenssh-10.0p1/regress/unittests/kex/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021117xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/kex/Makefile010064400017500001750000000021111477541562300174750ustar00djmdjm# $OpenBSD: Makefile,v 1.16 2024/09/09 03:13:39 djm Exp $ PROG=test_kex SRCS=tests.c test_kex.c test_proposal.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c SRCS+=compat.c ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c SRCS+=ssh-ed25519-sk.c sk-usbhid.c SRCS+= kex.c SRCS+= kex-names.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+= kexsntrup761x25519.c SRCS+= kexmlkem768x25519.c SRCS+= sntrup761.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 LDADD+=-lz openssh-10.0p1/regress/unittests/kex/PaxHeaders.10889/test_kex.c100644 001750 001750 0000000003614775415623 0021451xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/kex/test_kex.c010064400017500001750000000127671477541562300200510ustar00djmdjm/* $OpenBSD: test_kex.c,v 1.9 2024/09/09 03:13:39 djm Exp $ */ /* * Regress test KEX * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "ssherr.h" #include "ssh_api.h" #include "sshbuf.h" #include "packet.h" #include "myproposal.h" #include "log.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->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; server2->kex->kex[KEX_KEM_MLKEM768X25519_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) { #if 0 log_init("test_kex", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); #endif #ifdef WITH_OPENSSL do_kex_with_key(kex, KEY_RSA, 2048); #ifdef WITH_DSA do_kex_with_key(kex, KEY_DSA, 1024); #endif #ifdef OPENSSL_HAS_ECC do_kex_with_key(kex, KEY_ECDSA, 256); #endif /* OPENSSL_HAS_ECC */ #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"); # ifdef USE_MLKEM768X25519 do_kex("mlkem768x25519-sha256"); # endif /* USE_MLKEM768X25519 */ # ifdef USE_SNTRUP761X25519 do_kex("sntrup761x25519-sha512@openssh.com"); # endif /* USE_SNTRUP761X25519 */ #endif /* WITH_OPENSSL */ } openssh-10.0p1/regress/unittests/kex/PaxHeaders.10889/test_proposal.c100644 001750 001750 0000000003614775415623 0022521xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/kex/test_proposal.c010064400017500001750000000061201477541562300211030ustar00djmdjm/* $OpenBSD: test_proposal.c,v 1.2 2023/03/06 12:15:47 dtucker Exp $ */ /* * Regress test KEX * * Placed in the public domain */ #include "includes.h" #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "cipher.h" #include "compat.h" #include "ssherr.h" #include "sshbuf.h" #include "kex.h" #include "myproposal.h" #include "packet.h" #include "xmalloc.h" void kex_proposal_tests(void); void kex_proposal_populate_tests(void); #define CURVE25519 "curve25519-sha256@libssh.org" #define DHGEX1 "diffie-hellman-group-exchange-sha1" #define DHGEX256 "diffie-hellman-group-exchange-sha256" #define KEXALGOS CURVE25519","DHGEX256","DHGEX1 void kex_proposal_tests(void) { size_t i; struct ssh ssh; char *result, *out, *in; struct { char *in; /* TODO: make this const */ char *out; int compat; } tests[] = { { KEXALGOS, KEXALGOS, 0}, { KEXALGOS, DHGEX256","DHGEX1, SSH_BUG_CURVE25519PAD }, { KEXALGOS, CURVE25519, SSH_OLD_DHGEX }, { "a,"KEXALGOS, "a", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX }, /* TODO: enable once compat_kex_proposal doesn't fatal() */ /* { KEXALGOS, "", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX }, */ }; TEST_START("compat_kex_proposal"); for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { ssh.compat = tests[i].compat; /* match entire string */ result = compat_kex_proposal(&ssh, tests[i].in); ASSERT_STRING_EQ(result, tests[i].out); free(result); /* match at end */ in = kex_names_cat("a", tests[i].in); out = kex_names_cat("a", tests[i].out); result = compat_kex_proposal(&ssh, in); ASSERT_STRING_EQ(result, out); free(result); free(in); free(out); /* match at start */ in = kex_names_cat(tests[i].in, "a"); out = kex_names_cat(tests[i].out, "a"); result = compat_kex_proposal(&ssh, in); ASSERT_STRING_EQ(result, out); free(result); free(in); free(out); /* match in middle */ xasprintf(&in, "a,%s,b", tests[i].in); if (*(tests[i].out) == '\0') out = xstrdup("a,b"); else xasprintf(&out, "a,%s,b", tests[i].out); result = compat_kex_proposal(&ssh, in); ASSERT_STRING_EQ(result, out); free(result); free(in); free(out); } TEST_DONE(); } void kex_proposal_populate_tests(void) { char *prop[PROPOSAL_MAX], *kexalgs, *ciphers, *macs, *hkalgs; const char *comp = compression_alg_list(0); int i; struct ssh ssh; struct kex kex; kexalgs = kex_alg_list(','); ciphers = cipher_alg_list(',', 0); macs = mac_alg_list(','); hkalgs = kex_alg_list(','); ssh.kex = &kex; TEST_START("compat_kex_proposal_populate"); for (i = 0; i <= 1; i++) { kex.server = i; for (ssh.compat = 0; ssh.compat < 0x40000000; ) { kex_proposal_populate_entries(&ssh, prop, NULL, NULL, NULL, NULL, NULL); kex_proposal_free_entries(prop); kex_proposal_populate_entries(&ssh, prop, kexalgs, ciphers, macs, hkalgs, comp); kex_proposal_free_entries(prop); if (ssh.compat == 0) ssh.compat = 1; else ssh.compat <<= 1; } } free(kexalgs); free(ciphers); free(macs); free(hkalgs); } openssh-10.0p1/regress/unittests/kex/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0020765xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/kex/tests.c010064400017500001750000000005111477541562300173450ustar00djmdjm/* $OpenBSD: tests.c,v 1.3 2023/03/06 12:15:47 dtucker Exp $ */ /* * Placed in the public domain */ #include "../test_helper/test_helper.h" void kex_tests(void); void kex_proposal_tests(void); void kex_proposal_populate_tests(void); void tests(void) { kex_tests(); kex_proposal_tests(); kex_proposal_populate_tests(); } openssh-10.0p1/regress/unittests/PaxHeaders.10889/match040755 001750 001750 0000000003614775415623 0017715xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/match004075500017500001750000000000001477541562300162735ustar00djmdjmopenssh-10.0p1/regress/unittests/match/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021424xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/match/Makefile010064400017500001750000000006401477541562300200070ustar00djmdjm# $OpenBSD: Makefile,v 1.5 2021/01/09 12:24:31 dtucker 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 addr.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} env ${TEST_ENV} ./${PROG} .include openssh-10.0p1/regress/unittests/match/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021272xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/match/tests.c010064400017500001750000000121721477541562300176600ustar00djmdjm/* $OpenBSD: tests.c,v 1.8 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for matching functions * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #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_denylist((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 *); */ } openssh-10.0p1/regress/unittests/PaxHeaders.10889/misc040755 001750 001750 0000000003614775415623 0017554xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/misc004075500017500001750000000000001477541562300161325ustar00djmdjmopenssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021263xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/misc/Makefile010064400017500001750000000011731477541562300176500ustar00djmdjm# $OpenBSD: Makefile,v 1.9 2023/01/06 02:59:50 djm Exp $ PROG=test_misc SRCS=tests.c SRCS+= test_convtime.c SRCS+= test_expand.c SRCS+= test_parse.c SRCS+= test_argv.c SRCS+= test_strdelim.c SRCS+= test_hpdelim.c SRCS+= test_ptimeout.c # From usr.bin/ssh/Makefile.inc SRCS+= sshbuf.c SRCS+= sshbuf-getput-basic.c SRCS+= sshbuf-misc.c SRCS+= ssherr.c SRCS+= log.c SRCS+= xmalloc.c SRCS+= misc.c SRCS+= match.c SRCS+= addr.c SRCS+= addrmatch.c # From usr.bin/ssh/sshd/Makefile SRCS+= atomicio.c cleanup.c fatal.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} env ${TEST_ENV} ./${PROG} .include openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/test_argv.c100644 001750 001750 0000000003614775415623 0021765xustar0030 atime=1744182234.727368641 openssh-10.0p1/regress/unittests/misc/test_argv.c010064400017500001750000000116751477541562300203620ustar00djmdjm/* $OpenBSD: test_argv.c,v 1.4 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for misc argv handling functions. * * Placed in the public domain. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" void test_argv(void); void test_argv(void) { char **av = NULL; int ac = 0; #define RESET_ARGV() \ do { \ argv_free(av, ac); \ av = NULL; \ ac = -1; \ } while (0) TEST_START("empty args"); ASSERT_INT_EQ(argv_split("", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 0); ASSERT_PTR_NE(av, NULL); ASSERT_PTR_EQ(av[0], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split(" ", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 0); ASSERT_PTR_NE(av, NULL); ASSERT_PTR_EQ(av[0], NULL); RESET_ARGV(); TEST_DONE(); TEST_START("trivial args"); ASSERT_INT_EQ(argv_split("leamas", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "leamas"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("smiley leamas", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 2); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley"); ASSERT_STRING_EQ(av[1], "leamas"); ASSERT_PTR_EQ(av[2], NULL); RESET_ARGV(); TEST_DONE(); TEST_START("quoted"); ASSERT_INT_EQ(argv_split("\"smiley\"", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("leamas \" smiley \"", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 2); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "leamas"); ASSERT_STRING_EQ(av[1], " smiley "); ASSERT_PTR_EQ(av[2], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("\"smiley leamas\"", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley leamas"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("smiley\" leamas\" liz", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 2); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley leamas"); ASSERT_STRING_EQ(av[1], "liz"); ASSERT_PTR_EQ(av[2], NULL); RESET_ARGV(); TEST_DONE(); TEST_START("escaped"); ASSERT_INT_EQ(argv_split("\\\"smiley\\'", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "\"smiley'"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("'\\'smiley\\\"'", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "'smiley\""); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("smiley\\'s leamas\\'", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 2); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley's"); ASSERT_STRING_EQ(av[1], "leamas'"); ASSERT_PTR_EQ(av[2], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("leamas\\\\smiley", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "leamas\\smiley"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("leamas\\\\ \\\\smiley", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 2); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "leamas\\"); ASSERT_STRING_EQ(av[1], "\\smiley"); ASSERT_PTR_EQ(av[2], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("smiley\\ leamas", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley leamas"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); TEST_DONE(); TEST_START("quoted escaped"); ASSERT_INT_EQ(argv_split("'smiley\\ leamas'", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley\\ leamas"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("\"smiley\\ leamas\"", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "smiley\\ leamas"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); TEST_DONE(); TEST_START("comments"); ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 0), 0); ASSERT_INT_EQ(ac, 2); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "#"); ASSERT_STRING_EQ(av[1], "gold"); ASSERT_PTR_EQ(av[2], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 1), 0); ASSERT_INT_EQ(ac, 0); ASSERT_PTR_NE(av, NULL); ASSERT_PTR_EQ(av[0], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("leamas#gold", &ac, &av, 1), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "leamas#gold"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("\"leamas # gold\"", &ac, &av, 1), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "leamas # gold"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); ASSERT_INT_EQ(argv_split("\"leamas\"#gold", &ac, &av, 1), 0); ASSERT_INT_EQ(ac, 1); ASSERT_PTR_NE(av, NULL); ASSERT_STRING_EQ(av[0], "leamas#gold"); ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); TEST_DONE(); /* XXX test char *argv_assemble(int argc, char **argv) */ } openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/test_convtime.c100644 001750 001750 0000000003614775415623 0022652xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/misc/test_convtime.c010064400017500001750000000076111477541562300212420ustar00djmdjm/* $OpenBSD: test_convtime.c,v 1.3 2022/08/11 01:57:50 djm Exp $ */ /* * Regress test for misc time conversion functions. * * Placed in the public domain. */ #include "includes.h" #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" #include "ssherr.h" void test_convtime(void); void test_convtime(void) { char buf[1024]; uint64_t t; TEST_START("misc_convtime"); ASSERT_INT_EQ(convtime("0"), 0); ASSERT_INT_EQ(convtime("1"), 1); ASSERT_INT_EQ(convtime("2s"), 2); ASSERT_INT_EQ(convtime("3m"), 180); ASSERT_INT_EQ(convtime("1m30"), 90); ASSERT_INT_EQ(convtime("1m30s"), 90); ASSERT_INT_EQ(convtime("1h1s"), 3601); ASSERT_INT_EQ(convtime("1h30m"), 90 * 60); ASSERT_INT_EQ(convtime("1d"), 24 * 60 * 60); ASSERT_INT_EQ(convtime("1w"), 7 * 24 * 60 * 60); ASSERT_INT_EQ(convtime("1w2d3h4m5"), 788645); ASSERT_INT_EQ(convtime("1w2d3h4m5s"), 788645); /* any negative number or error returns -1 */ ASSERT_INT_EQ(convtime("-1"), -1); ASSERT_INT_EQ(convtime(""), -1); ASSERT_INT_EQ(convtime("trout"), -1); ASSERT_INT_EQ(convtime("-77"), -1); /* boundary conditions */ snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX); ASSERT_INT_EQ(convtime(buf), INT_MAX); snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX + 1); ASSERT_INT_EQ(convtime(buf), -1); ASSERT_INT_EQ(convtime("3550w5d3h14m7s"), 2147483647); #if INT_MAX == 2147483647 ASSERT_INT_EQ(convtime("3550w5d3h14m8s"), -1); #endif TEST_DONE(); /* XXX timezones/DST make verification of this tricky */ /* XXX maybe setenv TZ and tzset() to make it unambiguous? */ TEST_START("misc_parse_absolute_time"); ASSERT_INT_EQ(parse_absolute_time("20000101", &t), 0); ASSERT_INT_EQ(parse_absolute_time("200001011223", &t), 0); ASSERT_INT_EQ(parse_absolute_time("20000101122345", &t), 0); /* forced UTC TZ */ ASSERT_INT_EQ(parse_absolute_time("20000101Z", &t), 0); ASSERT_U64_EQ(t, 946684800); ASSERT_INT_EQ(parse_absolute_time("200001011223Z", &t), 0); ASSERT_U64_EQ(t, 946729380); ASSERT_INT_EQ(parse_absolute_time("20000101122345Z", &t), 0); ASSERT_U64_EQ(t, 946729425); ASSERT_INT_EQ(parse_absolute_time("20000101UTC", &t), 0); ASSERT_U64_EQ(t, 946684800); ASSERT_INT_EQ(parse_absolute_time("200001011223UTC", &t), 0); ASSERT_U64_EQ(t, 946729380); ASSERT_INT_EQ(parse_absolute_time("20000101122345UTC", &t), 0); ASSERT_U64_EQ(t, 946729425); /* Bad month */ ASSERT_INT_EQ(parse_absolute_time("20001301", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("20000001", &t), SSH_ERR_INVALID_FORMAT); /* Incomplete */ ASSERT_INT_EQ(parse_absolute_time("2", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("2000", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("20000", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("200001", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("2000010", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("200001010", &t), SSH_ERR_INVALID_FORMAT); /* Bad day, hour, minute, second */ ASSERT_INT_EQ(parse_absolute_time("20000199", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("200001019900", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("200001010099", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("20000101000099", &t), SSH_ERR_INVALID_FORMAT); /* Invalid TZ specifier */ ASSERT_INT_EQ(parse_absolute_time("20000101ZZ", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("20000101PDT", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("20000101U", &t), SSH_ERR_INVALID_FORMAT); ASSERT_INT_EQ(parse_absolute_time("20000101UTCUTC", &t), SSH_ERR_INVALID_FORMAT); TEST_DONE(); } openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/test_expand.c100644 001750 001750 0000000003614775415623 0022305xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/misc/test_expand.c010064400017500001750000000054031477541562300206720ustar00djmdjm/* $OpenBSD: test_expand.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for misc string expansion functions. * * Placed in the public domain. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" void test_expand(void); void test_expand(void) { int parseerr; char *ret; TEST_START("dollar_expand"); ASSERT_INT_EQ(setenv("FOO", "bar", 1), 0); ASSERT_INT_EQ(setenv("BAR", "baz", 1), 0); (void)unsetenv("BAZ"); #define ASSERT_DOLLAR_EQ(x, y) do { \ char *str = dollar_expand(NULL, (x)); \ ASSERT_STRING_EQ(str, (y)); \ free(str); \ } while(0) ASSERT_DOLLAR_EQ("${FOO}", "bar"); ASSERT_DOLLAR_EQ(" ${FOO}", " bar"); ASSERT_DOLLAR_EQ("${FOO} ", "bar "); ASSERT_DOLLAR_EQ(" ${FOO} ", " bar "); ASSERT_DOLLAR_EQ("${FOO}${BAR}", "barbaz"); ASSERT_DOLLAR_EQ(" ${FOO} ${BAR}", " bar baz"); ASSERT_DOLLAR_EQ("${FOO}${BAR} ", "barbaz "); ASSERT_DOLLAR_EQ(" ${FOO} ${BAR} ", " bar baz "); ASSERT_DOLLAR_EQ("$", "$"); ASSERT_DOLLAR_EQ(" $", " $"); ASSERT_DOLLAR_EQ("$ ", "$ "); /* suppress error messages for error handing tests */ log_init("test_misc", SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_AUTH, 1); /* error checking, non existent variable */ ret = dollar_expand(&parseerr, "a${BAZ}"); ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); ret = dollar_expand(&parseerr, "${BAZ}b"); ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); ret = dollar_expand(&parseerr, "a${BAZ}b"); ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); /* invalid format */ ret = dollar_expand(&parseerr, "${"); ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); ret = dollar_expand(&parseerr, "${F"); ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); ret = dollar_expand(&parseerr, "${FO"); ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); /* empty variable name */ ret = dollar_expand(&parseerr, "${}"); ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); /* restore loglevel to default */ log_init("test_misc", SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1); TEST_DONE(); TEST_START("percent_expand"); ASSERT_STRING_EQ(percent_expand("%%", "%h", "foo", NULL), "%"); ASSERT_STRING_EQ(percent_expand("%h", "h", "foo", NULL), "foo"); ASSERT_STRING_EQ(percent_expand("%h ", "h", "foo", NULL), "foo "); ASSERT_STRING_EQ(percent_expand(" %h", "h", "foo", NULL), " foo"); ASSERT_STRING_EQ(percent_expand(" %h ", "h", "foo", NULL), " foo "); ASSERT_STRING_EQ(percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL), " foobar "); TEST_DONE(); TEST_START("percent_dollar_expand"); ASSERT_STRING_EQ(percent_dollar_expand("%h${FOO}", "h", "foo", NULL), "foobar"); TEST_DONE(); } openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/test_hpdelim.c100644 001750 001750 0000000003614775415623 0022450xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/misc/test_hpdelim.c010064400017500001750000000031571477541562300210410ustar00djmdjm/* $OpenBSD: test_hpdelim.c,v 1.2 2022/02/06 22:58:33 dtucker Exp $ */ /* * Regress test for misc hpdelim() and co * * Placed in the public domain. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" #include "xmalloc.h" void test_hpdelim(void); void test_hpdelim(void) { char *orig, *str, *cp, *port; #define START_STRING(x) orig = str = xstrdup(x) #define DONE_STRING() free(orig) TEST_START("hpdelim host only"); START_STRING("host"); cp = hpdelim(&str); ASSERT_STRING_EQ(cp, "host"); ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("hpdelim :port"); START_STRING(":1234"); cp = hpdelim(&str); ASSERT_STRING_EQ(cp, ""); ASSERT_PTR_NE(str, NULL); port = hpdelim(&str); ASSERT_STRING_EQ(port, "1234"); ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("hpdelim host:port"); START_STRING("host:1234"); cp = hpdelim(&str); ASSERT_STRING_EQ(cp, "host"); ASSERT_PTR_NE(str, NULL); port = hpdelim(&str); ASSERT_STRING_EQ(port, "1234"); ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("hpdelim [host]:port"); START_STRING("[::1]:1234"); cp = hpdelim(&str); ASSERT_STRING_EQ(cp, "[::1]"); ASSERT_PTR_NE(str, NULL); port = hpdelim(&str); ASSERT_STRING_EQ(port, "1234"); ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("hpdelim missing ] error"); START_STRING("[::1:1234"); cp = hpdelim(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); } openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/test_parse.c100644 001750 001750 0000000003614775415623 0022140xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/misc/test_parse.c010064400017500001750000000044541477541562300205320ustar00djmdjm/* $OpenBSD: test_parse.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for misc user/host/URI parsing functions. * * Placed in the public domain. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" void test_parse(void); void test_parse(void) { int port; char *user, *host, *path; TEST_START("misc_parse_user_host_path"); ASSERT_INT_EQ(parse_user_host_path("someuser@some.host:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); ASSERT_STRING_EQ(host, "some.host"); ASSERT_STRING_EQ(path, "some/path"); free(user); free(host); free(path); TEST_DONE(); TEST_START("misc_parse_user_ipv4_path"); ASSERT_INT_EQ(parse_user_host_path("someuser@1.22.33.144:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); ASSERT_STRING_EQ(host, "1.22.33.144"); ASSERT_STRING_EQ(path, "some/path"); free(user); free(host); free(path); TEST_DONE(); TEST_START("misc_parse_user_[ipv4]_path"); ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); ASSERT_STRING_EQ(host, "1.22.33.144"); ASSERT_STRING_EQ(path, "some/path"); free(user); free(host); free(path); TEST_DONE(); TEST_START("misc_parse_user_[ipv4]_nopath"); ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); ASSERT_STRING_EQ(host, "1.22.33.144"); ASSERT_STRING_EQ(path, "."); free(user); free(host); free(path); TEST_DONE(); TEST_START("misc_parse_user_ipv6_path"); ASSERT_INT_EQ(parse_user_host_path("someuser@[::1]:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); ASSERT_STRING_EQ(host, "::1"); ASSERT_STRING_EQ(path, "some/path"); free(user); free(host); free(path); TEST_DONE(); TEST_START("misc_parse_uri"); ASSERT_INT_EQ(parse_uri("ssh", "ssh://someuser@some.host:22/some/path", &user, &host, &port, &path), 0); ASSERT_STRING_EQ(user, "someuser"); ASSERT_STRING_EQ(host, "some.host"); ASSERT_INT_EQ(port, 22); ASSERT_STRING_EQ(path, "some/path"); free(user); free(host); free(path); TEST_DONE(); } openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/test_ptimeout.c100644 001750 001750 0000000003614775415623 0022674xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/misc/test_ptimeout.c010064400017500001750000000042771477541562300212710ustar00djmdjm/* $OpenBSD: test_ptimeout.c,v 1.1 2023/01/06 02:59:50 djm Exp $ */ /* * Regress test for misc poll/ppoll timeout helpers. * * Placed in the public domain. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #ifdef HAVE_POLL_H # include #endif #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" void test_ptimeout(void); void test_ptimeout(void) { struct timespec pt, *ts; TEST_START("ptimeout_init"); ptimeout_init(&pt); ASSERT_PTR_EQ(ptimeout_get_tsp(&pt), NULL); ASSERT_INT_EQ(ptimeout_get_ms(&pt), -1); TEST_DONE(); TEST_START("ptimeout_deadline_sec"); ptimeout_deadline_sec(&pt, 100); ptimeout_deadline_sec(&pt, 200); ASSERT_INT_EQ(ptimeout_get_ms(&pt), 100 * 1000); ts = ptimeout_get_tsp(&pt); ASSERT_PTR_NE(ts, NULL); ASSERT_LONG_EQ(ts->tv_nsec, 0); ASSERT_LONG_EQ(ts->tv_sec, 100); TEST_DONE(); TEST_START("ptimeout_deadline_ms"); ptimeout_deadline_ms(&pt, 50123); ptimeout_deadline_ms(&pt, 50500); ASSERT_INT_EQ(ptimeout_get_ms(&pt), 50123); ts = ptimeout_get_tsp(&pt); ASSERT_PTR_NE(ts, NULL); ASSERT_LONG_EQ(ts->tv_nsec, 123 * 1000000); ASSERT_LONG_EQ(ts->tv_sec, 50); TEST_DONE(); TEST_START("ptimeout zero"); ptimeout_init(&pt); ptimeout_deadline_ms(&pt, 0); ASSERT_INT_EQ(ptimeout_get_ms(&pt), 0); ts = ptimeout_get_tsp(&pt); ASSERT_PTR_NE(ts, NULL); ASSERT_LONG_EQ(ts->tv_nsec, 0); ASSERT_LONG_EQ(ts->tv_sec, 0); TEST_DONE(); TEST_START("ptimeout_deadline_monotime"); ptimeout_init(&pt); ptimeout_deadline_monotime(&pt, monotime() + 100); ASSERT_INT_GT(ptimeout_get_ms(&pt), 50000); ASSERT_INT_LT(ptimeout_get_ms(&pt), 200000); ts = ptimeout_get_tsp(&pt); ASSERT_PTR_NE(ts, NULL); ASSERT_LONG_GT(ts->tv_sec, 50); ASSERT_LONG_LT(ts->tv_sec, 200); TEST_DONE(); TEST_START("ptimeout_deadline_monotime past"); ptimeout_init(&pt); ptimeout_deadline_monotime(&pt, monotime() + 100); ptimeout_deadline_monotime(&pt, monotime() - 100); ASSERT_INT_EQ(ptimeout_get_ms(&pt), 0); ts = ptimeout_get_tsp(&pt); ASSERT_PTR_NE(ts, NULL); ASSERT_LONG_EQ(ts->tv_nsec, 0); ASSERT_LONG_EQ(ts->tv_sec, 0); TEST_DONE(); } openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/test_strdelim.c100644 001750 001750 0000000003614775415623 0022651xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/misc/test_strdelim.c010064400017500001750000000110031477541562300212270ustar00djmdjm/* $OpenBSD: test_strdelim.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for misc strdelim() and co * * Placed in the public domain. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" #include "xmalloc.h" void test_strdelim(void); void test_strdelim(void) { char *orig, *str, *cp; #define START_STRING(x) orig = str = xstrdup(x) #define DONE_STRING() free(orig) TEST_START("empty"); START_STRING(""); cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); /* XXX arguable */ cp = strdelim(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); TEST_START("whitespace"); START_STRING(" "); cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ ASSERT_STRING_EQ(str, ""); DONE_STRING(); TEST_DONE(); TEST_START("trivial"); START_STRING("blob"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob"); cp = strdelim(&str); ASSERT_PTR_EQ(cp, NULL); ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("trivial whitespace"); START_STRING("blob "); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob"); ASSERT_STRING_EQ(str, ""); cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("multi"); START_STRING("blob1 blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob1"); ASSERT_STRING_EQ(str, "blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob2"); ASSERT_PTR_EQ(str, NULL); cp = strdelim(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); TEST_START("multi whitespace"); START_STRING("blob1 blob2 "); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob1"); ASSERT_STRING_EQ(str, "blob2 "); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("multi equals"); START_STRING("blob1=blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob1"); ASSERT_STRING_EQ(str, "blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob2"); ASSERT_PTR_EQ(str, NULL); cp = strdelim(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); TEST_START("multi too many equals"); START_STRING("blob1==blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob1"); /* XXX better returning NULL early */ ASSERT_STRING_EQ(str, "=blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); ASSERT_STRING_EQ(str, "blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob2"); /* XXX should (but can't) reject */ ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("multi equals strdelimw"); START_STRING("blob1=blob2"); cp = strdelimw(&str); ASSERT_STRING_EQ(cp, "blob1=blob2"); ASSERT_PTR_EQ(str, NULL); cp = strdelimw(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); TEST_START("quoted"); START_STRING("\"blob\""); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("quoted multi"); START_STRING("\"blob1\" blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob1"); ASSERT_STRING_EQ(str, "blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob2"); ASSERT_PTR_EQ(str, NULL); cp = strdelim(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); TEST_START("quoted multi reverse"); START_STRING("blob1 \"blob2\""); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob1"); ASSERT_STRING_EQ(str, "\"blob2\""); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob2"); ASSERT_STRING_EQ(str, ""); cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ ASSERT_PTR_EQ(str, NULL); DONE_STRING(); TEST_DONE(); TEST_START("quoted multi middle"); START_STRING("blob1 \"blob2\" blob3"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob1"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob2"); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob3"); cp = strdelim(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); TEST_START("badquote"); START_STRING("\"blob"); cp = strdelim(&str); ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); TEST_START("oops quote"); START_STRING("\"blob\\\""); cp = strdelim(&str); ASSERT_STRING_EQ(cp, "blob\\"); /* XXX wrong */ cp = strdelim(&str); ASSERT_STRING_EQ(cp, ""); DONE_STRING(); TEST_DONE(); } openssh-10.0p1/regress/unittests/misc/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021131xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/misc/tests.c010064400017500001750000000012611477541562300175140ustar00djmdjm/* $OpenBSD: tests.c,v 1.10 2023/01/06 02:59:50 djm Exp $ */ /* * Regress test for misc helper functions. * * Placed in the public domain. */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include "../test_helper/test_helper.h" #include "log.h" #include "misc.h" void test_parse(void); void test_convtime(void); void test_expand(void); void test_argv(void); void test_strdelim(void); void test_hpdelim(void); void test_ptimeout(void); void tests(void) { test_parse(); test_convtime(); test_expand(); test_argv(); test_strdelim(); test_hpdelim(); test_ptimeout(); } openssh-10.0p1/regress/unittests/PaxHeaders.10889/sshbuf040755 001750 001750 0000000003614775415623 0020113xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/sshbuf004075500017500001750000000000001477541562300164715ustar00djmdjmopenssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021622xustar0030 atime=1744182234.728344016 openssh-10.0p1/regress/unittests/sshbuf/Makefile010064400017500001750000000011631477541562300202060ustar00djmdjm# $OpenBSD: Makefile,v 1.10 2021/01/09 12:24:31 dtucker Exp $ # $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $ 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 SRCS+=match.c addr.c addrmatch.c run-regress-${PROG}: ${PROG} env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/test_sshbuf.c100644 001750 001750 0000000003614775415623 0022657xustar0030 atime=1744182234.729321325 openssh-10.0p1/regress/unittests/sshbuf/test_sshbuf.c010064400017500001750000000145661477541562300212560ustar00djmdjm/* $OpenBSD: test_sshbuf.c,v 1.2 2021/12/14 21:25:27 deraadt 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 #include #ifdef HAVE_STDINT_H # include #endif #include #include #include "../test_helper/test_helper.h" #include "ssherr.h" #include "sshbuf.h" void sshbuf_tests(void); #ifndef roundup #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #endif 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(); } openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/test_sshbuf_fixed.c100644 001750 001750 0000000003614775415623 0024036xustar0030 atime=1744182234.729321325 openssh-10.0p1/regress/unittests/sshbuf/test_sshbuf_fixed.c010064400017500001750000000074341477541562300224310ustar00djmdjm/* $OpenBSD: test_sshbuf_fixed.c,v 1.2 2021/12/14 21:25:27 deraadt 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 #include #ifdef HAVE_STDINT_H # include #endif #include #include #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); } openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/test_sshbuf_fuzz.c100644 001750 001750 0000000003614775415623 0023735xustar0030 atime=1744182234.729321325 openssh-10.0p1/regress/unittests/sshbuf/test_sshbuf_fuzz.c010064400017500001750000000065231477541562300223260ustar00djmdjm/* $OpenBSD: test_sshbuf_fuzz.c,v 1.4 2021/12/18 06:53:59 anton Exp $ */ /* * Regress test for sshbuf.h buffer API * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #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 < ntests; 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(); } openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/test_sshbuf_getput_basic.c100644 001750 001750 0000000003614775415623 0025410xustar0030 atime=1744182234.729321325 openssh-10.0p1/regress/unittests/sshbuf/test_sshbuf_getput_basic.c010064400017500001750000000523561477541562300240060ustar00djmdjm/* $OpenBSD: test_sshbuf_getput_basic.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for sshbuf.h buffer API * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #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(); } openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/test_sshbuf_getput_crypto.c100644 001750 001750 0000000003614775415623 0025647xustar0030 atime=1744182234.729321325 openssh-10.0p1/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c010064400017500001750000000176511477541562300242440ustar00djmdjm/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for sshbuf.h buffer API * * Placed in the public domain */ #include "includes.h" #ifdef WITH_OPENSSL #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #ifdef OPENSSL_HAS_NISTP256 # include #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 */ openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/test_sshbuf_getput_fuzz.c100644 001750 001750 0000000003614775415623 0025325xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c010064400017500001750000000061231477541562300237120ustar00djmdjm/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for sshbuf.h buffer API * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #ifdef WITH_OPENSSL #include #include #ifdef OPENSSL_HAS_NISTP256 # include #endif #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); } openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/test_sshbuf_misc.c100644 001750 001750 0000000003614775415623 0023672xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshbuf/test_sshbuf_misc.c010064400017500001750000000141611477541562300222600ustar00djmdjm/* $OpenBSD: test_sshbuf_misc.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ /* * Regress test for sshbuf.h buffer API * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #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(); } openssh-10.0p1/regress/unittests/sshbuf/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021470xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshbuf/tests.c010064400017500001750000000011611477541562300200520ustar00djmdjm/* $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(); } openssh-10.0p1/regress/unittests/PaxHeaders.10889/sshkey040755 001750 001750 0000000003614775415623 0020127xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshkey004075500017500001750000000000001477541562300165055ustar00djmdjmopenssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021636xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshkey/Makefile010064400017500001750000000015001477541562300202150ustar00djmdjm# $OpenBSD: Makefile,v 1.12 2023/01/15 23:35:10 djm 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+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c SRCS+=ssh-ed25519-sk.c sk-usbhid.c SRCS+=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 openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/common.c100644 001750 001750 0000000003614775415623 0021632xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshkey/common.c010064400017500001750000000060271477541562300202220ustar00djmdjm/* $OpenBSD: common.c,v 1.6 2024/08/15 00:52:23 djm Exp $ */ /* * Helpers for key API tests * * Placed in the public domain */ #include "includes.h" #include #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include #ifdef WITH_OPENSSL #include #include #include #include #ifdef OPENSSL_HAS_NISTP256 # include #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->pkey, NULL); RSA_get0_key(EVP_PKEY_get0_RSA(k->pkey), &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->pkey, NULL); RSA_get0_key(EVP_PKEY_get0_RSA(k->pkey), NULL, &e, NULL); return e; } const BIGNUM * rsa_p(struct sshkey *k) { const BIGNUM *p = NULL; ASSERT_PTR_NE(k, NULL); ASSERT_PTR_NE(EVP_PKEY_get0_RSA(k->pkey), NULL); RSA_get0_factors(EVP_PKEY_get0_RSA(k->pkey), &p, NULL); return p; } const BIGNUM * rsa_q(struct sshkey *k) { const BIGNUM *q = NULL; ASSERT_PTR_NE(k, NULL); ASSERT_PTR_NE(EVP_PKEY_get0_RSA(k->pkey), NULL); RSA_get0_factors(EVP_PKEY_get0_RSA(k->pkey), NULL, &q); return q; } const BIGNUM * dsa_g(struct sshkey *k) { const BIGNUM *g = NULL; ASSERT_PTR_NE(k, NULL); ASSERT_PTR_NE(k->dsa, NULL); DSA_get0_pqg(k->dsa, NULL, NULL, &g); return g; } const BIGNUM * dsa_pub_key(struct sshkey *k) { const BIGNUM *pub_key = NULL; ASSERT_PTR_NE(k, NULL); ASSERT_PTR_NE(k->dsa, NULL); DSA_get0_key(k->dsa, &pub_key, NULL); return pub_key; } const BIGNUM * dsa_priv_key(struct sshkey *k) { const BIGNUM *priv_key = NULL; ASSERT_PTR_NE(k, NULL); ASSERT_PTR_NE(k->dsa, NULL); DSA_get0_key(k->dsa, NULL, &priv_key); return priv_key; } #endif /* WITH_OPENSSL */ openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/common.h100644 001750 001750 0000000003614775415623 0021637xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshkey/common.h010064400017500001750000000012721477541562300202240ustar00djmdjm/* $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); openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/mktestdata.sh100755 001750 001750 0000000003614775415623 0022676xustar0030 atime=1744182234.730297201 openssh-10.0p1/regress/unittests/sshkey/mktestdata.sh010075500017500001750000000176351477541562300212750ustar00djmdjm#!/bin/sh # $OpenBSD: mktestdata.sh,v 1.11 2020/06/19 03:48:49 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 if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so else echo "Can't find sk-dummy.so" 1>&2 exit 1 fi rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1 rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2 rm -f rsa_n dsa_n ecdsa_n # new-format keys 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 -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #1" \ -N "" -f ecdsa_sk1 ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #1" \ -N "" -f ed25519_sk1 ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 -m PEM ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 -m PEM ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 -m PEM ssh-keygen -t ed25519 -C "ED25519 test key #2" -N "" -f ed25519_2 ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #2" \ -N "" -f ecdsa_sk2 ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #2" \ -N "" -f ed25519_sk2 cp rsa_1 rsa_n cp dsa_1 dsa_n cp ecdsa_1 ecdsa_n ssh-keygen -pf rsa_n -N "" ssh-keygen -pf dsa_n -N "" ssh-keygen -pf ecdsa_n -N "" cp rsa_1 rsa_1_pw cp dsa_1 dsa_1_pw cp ecdsa_1 ecdsa_1_pw cp ed25519_1 ed25519_1_pw cp ecdsa_sk1 ecdsa_sk1_pw cp ed25519_sk1 ed25519_sk1_pw cp rsa_1 rsa_n_pw cp dsa_1 dsa_n_pw cp ecdsa_1 ecdsa_n_pw ssh-keygen -pf rsa_1_pw -m PEM -N "$PW" ssh-keygen -pf dsa_1_pw -m PEM -N "$PW" ssh-keygen -pf ecdsa_1_pw -m PEM -N "$PW" ssh-keygen -pf ed25519_1_pw -N "$PW" ssh-keygen -pf ecdsa_sk1_pw -m PEM -N "$PW" ssh-keygen -pf ed25519_sk1_pw -N "$PW" ssh-keygen -pf rsa_n_pw -N "$PW" ssh-keygen -pf dsa_n_pw -N "$PW" ssh-keygen -pf ecdsa_n_pw -N "$PW" rsa_params rsa_1 rsa_1.param rsa_params rsa_2 rsa_2.param dsa_params dsa_1 dsa_1.param dsa_params dsa_1 dsa_1.param ecdsa_params ecdsa_1 ecdsa_1.param ecdsa_params ecdsa_2 ecdsa_2.param # XXX ed25519, *sk params 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 ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ -V 19990101:20110101 -z 4 ecdsa_sk1.pub ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ -V 19990101:20110101 -z 4 ed25519_sk1.pub # Make a few RSA variant signature too. cp rsa_1 rsa_1_sha1 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 -s ecdsa_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 7 ecdsa_sk1.pub ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 8 ed25519_sk1.pub ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp ssh-keygen -lf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp ssh-keygen -lf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp ssh-keygen -lf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp ssh-keygen -lf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp ssh-keygen -lf ecdsa_sk1-cert.pub | awk '{print $2}' > ecdsa_sk1-cert.fp ssh-keygen -lf ed25519_sk1-cert.pub | awk '{print $2}' > ed25519_sk1-cert.fp ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb ssh-keygen -Bf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp.bb ssh-keygen -Bf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp.bb ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb ssh-keygen -Bf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp.bb ssh-keygen -Bf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp.bb echo "$PW" > pw openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/test_file.c100644 001750 001750 0000000003614775415623 0022320xustar0030 atime=1744182234.731273878 openssh-10.0p1/regress/unittests/sshkey/test_file.c010064400017500001750000000376171477541562300207210ustar00djmdjm/* $OpenBSD: test_file.c,v 1.12 2024/08/15 00:52:23 djm Exp $ */ /* * Regress test for sshkey.h key management API * * Placed in the public domain */ #include "includes.h" #include #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include #ifdef WITH_OPENSSL #include #include #include #include #ifdef OPENSSL_HAS_NISTP256 # include #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); #ifdef WITH_DSA TEST_START("parse DSA from private"); buf = load_file("dsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); sshbuf_free(buf); ASSERT_PTR_NE(k1, NULL); a = load_bignum("dsa_1.param.g"); b = load_bignum("dsa_1.param.priv"); c = load_bignum("dsa_1.param.pub"); ASSERT_BIGNUM_EQ(dsa_g(k1), a); ASSERT_BIGNUM_EQ(dsa_priv_key(k1), b); ASSERT_BIGNUM_EQ(dsa_pub_key(k1), c); BN_free(a); BN_free(b); BN_free(c); TEST_DONE(); 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); #endif #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); #ifndef OPENSSL_IS_BORINGSSL /* lacks EC_POINT_point2bn() */ a = load_bignum("ecdsa_1.param.priv"); b = load_bignum("ecdsa_1.param.pub"); c = EC_POINT_point2bn(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(k1->pkey)), EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(k1->pkey)), POINT_CONVERSION_UNCOMPRESSED, NULL, NULL); ASSERT_PTR_NE(c, NULL); ASSERT_BIGNUM_EQ( EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(k1->pkey)), a); ASSERT_BIGNUM_EQ(b, c); BN_free(a); BN_free(b); BN_free(c); #endif /* OPENSSL_IS_BORINGSSL */ 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); #ifdef ENABLE_SK #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) TEST_START("parse ECDSA-SK from private"); buf = load_file("ecdsa_sk1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); sshbuf_free(buf); ASSERT_PTR_NE(k1, NULL); ASSERT_INT_EQ(k1->type, KEY_ECDSA_SK); TEST_DONE(); TEST_START("parse ECDSA-SK from private w/ passphrase"); buf = load_file("ecdsa_sk1_pw"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, (const char *)sshbuf_ptr(pw), &k2, NULL), 0); sshbuf_free(buf); ASSERT_PTR_NE(k2, NULL); ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); sshkey_free(k2); TEST_DONE(); TEST_START("load ECDSA-SK from public"); ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_sk1.pub"), &k2, NULL), 0); ASSERT_PTR_NE(k2, NULL); ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); sshkey_free(k2); TEST_DONE(); TEST_START("load ECDSA-SK cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_sk1"), &k2), 0); ASSERT_PTR_NE(k2, NULL); ASSERT_INT_EQ(k2->type, KEY_ECDSA_SK_CERT); ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); TEST_DONE(); TEST_START("ECDSA-SK key hex fingerprint"); buf = load_text_file("ecdsa_sk1.fp"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); ASSERT_PTR_NE(cp, NULL); ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); sshbuf_free(buf); free(cp); TEST_DONE(); TEST_START("ECDSA-SK cert hex fingerprint"); buf = load_text_file("ecdsa_sk1-cert.fp"); cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); ASSERT_PTR_NE(cp, NULL); ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); sshbuf_free(buf); free(cp); sshkey_free(k2); TEST_DONE(); TEST_START("ECDSA-SK key bubblebabble fingerprint"); buf = load_text_file("ecdsa_sk1.fp.bb"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); ASSERT_PTR_NE(cp, NULL); ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); sshbuf_free(buf); free(cp); TEST_DONE(); sshkey_free(k1); #endif TEST_START("parse Ed25519-SK from private"); buf = load_file("ed25519_sk1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); sshbuf_free(buf); ASSERT_PTR_NE(k1, NULL); ASSERT_INT_EQ(k1->type, KEY_ED25519_SK); /* XXX check key contents */ TEST_DONE(); TEST_START("parse Ed25519-SK from private w/ passphrase"); buf = load_file("ed25519_sk1_pw"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, (const char *)sshbuf_ptr(pw), &k2, NULL), 0); sshbuf_free(buf); ASSERT_PTR_NE(k2, NULL); ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); sshkey_free(k2); TEST_DONE(); TEST_START("load Ed25519-SK from public"); ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_sk1.pub"), &k2, NULL), 0); ASSERT_PTR_NE(k2, NULL); ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); sshkey_free(k2); TEST_DONE(); TEST_START("load Ed25519-SK cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_sk1"), &k2), 0); ASSERT_PTR_NE(k2, NULL); ASSERT_INT_EQ(k2->type, KEY_ED25519_SK_CERT); ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); TEST_DONE(); TEST_START("Ed25519-SK key hex fingerprint"); buf = load_text_file("ed25519_sk1.fp"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); ASSERT_PTR_NE(cp, NULL); ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); sshbuf_free(buf); free(cp); TEST_DONE(); TEST_START("Ed25519-SK cert hex fingerprint"); buf = load_text_file("ed25519_sk1-cert.fp"); cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); ASSERT_PTR_NE(cp, NULL); ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); sshbuf_free(buf); free(cp); sshkey_free(k2); TEST_DONE(); TEST_START("Ed25519-SK key bubblebabble fingerprint"); buf = load_text_file("ed25519_sk1.fp.bb"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); ASSERT_PTR_NE(cp, NULL); ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); sshbuf_free(buf); free(cp); TEST_DONE(); sshkey_free(k1); #endif /* ENABLE_SK */ sshbuf_free(pw); } openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/test_fuzz.c100644 001750 001750 0000000003614775415623 0022377xustar0030 atime=1744182234.732250144 openssh-10.0p1/regress/unittests/sshkey/test_fuzz.c010064400017500001750000000246021477541562300207660ustar00djmdjm/* $OpenBSD: test_fuzz.c,v 1.14 2024/01/11 01:45:58 djm Exp $ */ /* * Fuzz tests for key parsing * * Placed in the public domain */ #include "includes.h" #include #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include #ifdef WITH_OPENSSL #include #include #include #include #ifdef OPENSSL_HAS_NISTP256 # include #endif #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, 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(); #ifdef WITH_DSA TEST_START("fuzz DSA private"); buf = load_file("dsa_1"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) break; } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz DSA new-format private"); buf = load_file("dsa_n"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) break; } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA private"); buf = load_file("ecdsa_1"); 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(); #ifdef WITH_DSA TEST_START("fuzz DSA public"); buf = load_file("dsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); sshbuf_free(buf); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz DSA cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA public"); buf = load_file("ecdsa_1"); 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(); #ifdef WITH_DSA TEST_START("fuzz DSA sig"); buf = load_file("dsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); sshbuf_free(buf); sig_fuzz(k1, NULL); sshkey_free(k1); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA sig"); buf = load_file("ecdsa_1"); 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 */ } openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/test_sshkey.c100644 001750 001750 0000000003614775415623 0022707xustar0030 atime=1744182234.732250144 openssh-10.0p1/regress/unittests/sshkey/test_sshkey.c010064400017500001750000000357141477541562300213040ustar00djmdjm/* $OpenBSD: test_sshkey.c,v 1.25 2024/08/15 00:52:23 djm Exp $ */ /* * Regress test for sshkey.h key management API * * Placed in the public domain */ #include "includes.h" #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #ifdef WITH_OPENSSL #include #include #include #if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) # include #endif #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, 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, 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, the_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 = NULL, *k2 = NULL, *k3 = NULL, *kf = NULL; #ifdef WITH_OPENSSL struct sshkey *k4 = NULL, *kr = NULL, *kd = NULL; #ifdef OPENSSL_HAS_ECC struct sshkey *ke = NULL; #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ struct sshbuf *b = NULL; 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->pkey, NULL); sshkey_free(k1); TEST_DONE(); #ifdef WITH_DSA TEST_START("new/free KEY_DSA"); k1 = sshkey_new(KEY_DSA); ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1->dsa, NULL); sshkey_free(k1); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("new/free KEY_ECDSA"); k1 = sshkey_new(KEY_ECDSA); ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_EQ(k1->pkey, 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(); #ifdef WITH_DSA TEST_START("generate KEY_DSA wrong bits"); ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1), SSH_ERR_KEY_LENGTH); ASSERT_PTR_EQ(k1, NULL); sshkey_free(k1); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("generate KEY_ECDSA wrong bits"); 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(EVP_PKEY_get0_RSA(kr->pkey), 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(); #ifdef WITH_DSA TEST_START("generate KEY_DSA"); ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); ASSERT_PTR_NE(kd, NULL); ASSERT_PTR_NE(kd->dsa, NULL); ASSERT_PTR_NE(dsa_g(kd), NULL); ASSERT_PTR_NE(dsa_priv_key(kd), NULL); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("generate KEY_ECDSA"); ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0); ASSERT_PTR_NE(ke, NULL); ASSERT_PTR_NE(EVP_PKEY_get0_EC_KEY(ke->pkey), NULL); ASSERT_PTR_NE(EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(ke->pkey)), NULL); ASSERT_PTR_NE(EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(ke->pkey)), 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(EVP_PKEY_get0_RSA(k1->pkey), 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(); #ifdef WITH_DSA TEST_START("demote KEY_DSA"); ASSERT_INT_EQ(sshkey_from_private(kd, &k1), 0); ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(kd, k1); ASSERT_INT_EQ(k1->type, KEY_DSA); ASSERT_PTR_NE(k1->dsa, NULL); ASSERT_PTR_NE(dsa_g(k1), NULL); ASSERT_PTR_EQ(dsa_priv_key(k1), NULL); TEST_DONE(); TEST_START("equal KEY_DSA/demoted KEY_DSA"); ASSERT_INT_EQ(sshkey_equal(kd, k1), 1); sshkey_free(k1); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("demote KEY_ECDSA"); 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(EVP_PKEY_get0_EC_KEY(k1->pkey), NULL); ASSERT_INT_EQ(k1->ecdsa_nid, ke->ecdsa_nid); ASSERT_PTR_NE(EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(ke->pkey)), NULL); ASSERT_PTR_EQ(EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(k1->pkey)), 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); #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, 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(); #ifdef WITH_DSA TEST_START("sign and verify DSA"); k1 = get_private("dsa_1"); ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2, NULL), 0); signature_tests(k1, k2, NULL); sshkey_free(k1); sshkey_free(k2); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("sign and verify ECDSA"); 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 */ } openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/testdata040755 001750 001750 0000000003614775415623 0021740xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata004075500017500001750000000000001477541562300203165ustar00djmdjmopenssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1100644 001750 001750 0000000003614775415623 0022721xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1010064400017500001750000000012401477541562300213010ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1-cert.fp100644 001750 001750 0000000003614775415623 0024260xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1-cert.fp010064400017500001750000000000631477541562300226420ustar00djmdjmSHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1-cert.pub100644 001750 001750 0000000003614775415623 0024441xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1-cert.pub010064400017500001750000000017361477541562300230330ustar00djmdjmssh-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 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1.fp100644 001750 001750 0000000003614775415623 0023325xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1.fp010064400017500001750000000000631477541562300217070ustar00djmdjmSHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1.fp.bb100644 001750 001750 0000000003614775415623 0023707xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1.fp.bb010064400017500001750000000001021477541562300222630ustar00djmdjmxetag-todiz-mifah-torec-mynyv-cyvit-gopon-pygag-rupic-cenav-bexax openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1.param.g100644 001750 001750 0000000003614775415623 0024245xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1.param.g010064400017500001750000000004031477541562300226250ustar00djmdjm00eee5f505556d24a8cb996ae9c3adbe97fc525c0e6bafb30706e5a3882615dd51c17d725a403c910ed1ae109283c1dcea62069ca460291962ff72e06d27d9d286c525e86446d116b4de0f87c7d551e4bbe2241b23015078a9581c894d4d1a06b406dd8b79c7755f81064110735577ae3a98aa18cea33ff236c8332cd0f6e87add openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1.param.priv100644 001750 001750 0000000003614775415623 0024777xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1.param.priv010064400017500001750000000000511477541562300233560ustar00djmdjm5821b43929f5ec66e04fb967b9149cf795d68483 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1.param.pub100644 001750 001750 0000000003614775415623 0024605xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1.param.pub010064400017500001750000000004031477541562300231650ustar00djmdjm00e757a727e6a1b10168ea9902ebe08f53f4ba18c6d8fdf551fbabbf6d8558f054dc0f6aae4c5b397c04d0bc2f8c2bebb1057f96b621273fed8b2b38d1579a86e956644e520073171887fde4b88b4a0697323928ee3a28b7e2caf3896d2f29b067840c9d88e765249c95fd54bb240c714b5bdf8f88d2ef58727ca1a7699216c42d openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1.pub100644 001750 001750 0000000003614775415623 0023506xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1.pub010064400017500001750000000011351477541562300220710ustar00djmdjmssh-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 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_1_pw100644 001750 001750 0000000003614775415623 0023427xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_1_pw010064400017500001750000000014031477541562300220100ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_2100644 001750 001750 0000000003614775415623 0022722xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_2010064400017500001750000000012401477541562300213020ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_2.fp100644 001750 001750 0000000003614775415623 0023326xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_2.fp010064400017500001750000000000631477541562300217100ustar00djmdjmSHA256:ecwhWcXgpdBxZ2e+OjpRRY7dqXHHCD62BGtoVQQBwCk openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_2.fp.bb100644 001750 001750 0000000003614775415623 0023710xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_2.fp.bb010064400017500001750000000001021477541562300222640ustar00djmdjmxeser-megad-pocan-rozit-belup-tapoh-fapif-kyvit-vonav-cehab-naxax openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_2.pub100644 001750 001750 0000000003614775415623 0023507xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_2.pub010064400017500001750000000011351477541562300220720ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBAJvI9c10d4uyOmhs9UIyR9qAGS3XlmyW2p/88Y0/XLVy7PuuxNdl6RDBSRJM2blyipd75k7DY7i2OhskN3rQjX9U+BoHQ1iVBH0efzszbzhYPh/pVj5q6ceY/XfhrzJsbkbg2pU0XeKG/EBHalUhOpvuQTjqva5hk1w2Ucjy+hELAAAAFQDHD28KhTbEGx+aScmVt9MI+ClWdwAAAIEAgr3wFV4pBV/yoMWrH2i8y42BVLGl343Ri1rlkTLU4jbOK7lGGO54gzYrsarYyenfyhvUAzncFTGqVwElocQNrquPrK+4yBb2gIl0iYEzywgXF8Ftc1ukmIxoPBrpbJPzg6SkMTq64B6lMydY5RaRRWQCLKiQcNQZeQYbKhBuVtcAAACBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZ DSA test key #2 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_n100644 001750 001750 0000000003614775415623 0023016xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_n010064400017500001750000000025211477541562300214010ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/dsa_n_pw100644 001750 001750 0000000003614775415623 0023524xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/dsa_n_pw010064400017500001750000000026111477541562300221070ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1100644 001750 001750 0000000003614775415623 0023231xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1010064400017500001750000000003431477541562300216140ustar00djmdjm-----BEGIN EC PRIVATE KEY----- MHcCAQEEIPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMoAoGCCqGSM49 AwEHoUQDQgAEDFlblkOrW9ydKVhtM+9AY3c9saBE7SG3lFx38nBavkADDaI9jh3/ kvG/Jt9vpm22qwoklTCGDfzCkXkIKaWlBw== -----END EC PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1-cert.fp100644 001750 001750 0000000003614775415623 0024570xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp010064400017500001750000000000631477541562300231520ustar00djmdjmSHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1-cert.pub100644 001750 001750 0000000003614775415623 0024751xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub010064400017500001750000000012201477541562300233270ustar00djmdjmecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOtFRnMigkGliaYfPmX5IidVWfV3tRH6lqRXv0l8bvKoAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAAAAAAAABwAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2jAHwAAAAAE0eYHAAAAAAAAAAAAAAAAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAABkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABJAAAAIHbxGwTnue7KxhHXGFvRcxBnekhQ3Qx84vV/Vs4oVCrpAAAAIQC7vk2+d14aS7td7kVXLQn392oALjEBzMZoDvT1vT/zOA== ECDSA test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1.fp100644 001750 001750 0000000003614775415623 0023635xustar0030 atime=1744182234.733227052 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1.fp010064400017500001750000000000631477541562300222170ustar00djmdjmSHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1.fp.bb100644 001750 001750 0000000003614775415623 0024217xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb010064400017500001750000000001021477541562300225730ustar00djmdjmxibah-vocun-sogyn-byhen-rivem-hegyh-luneh-dozyr-vatyf-dufid-myxyx openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1.param.curve100644 001750 001750 0000000003614775415623 0025453xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1.param.curve010064400017500001750000000000131477541562300240300ustar00djmdjmprime256v1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_2100644 001750 001750 0000000003614775415623 0023232xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_2010064400017500001750000000005551477541562300216220ustar00djmdjm-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIBqBtN7e6Essd3dlsgISViPCXXC0atlNkGtoMgSQdBTKVUfeJOi4lc RZaXJdXnqWUqI/KEsH8h8QN4YcB8ugmAcc+gBwYFK4EEACOhgYkDgYYABAHZ2VNy oDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/ 0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs 6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g== -----END EC PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1.param.priv100644 001750 001750 0000000003614775415623 0025307xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1.param.priv010064400017500001750000000001031477541562300236640ustar00djmdjm00f3cdc940278ef16bf9e4ffeedfc8ca3b9041dfda2c589363dd8b07d8088f2acc openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1.param.pub100644 001750 001750 0000000003614775415623 0025115xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1.param.pub010064400017500001750000000002031477541562300234730ustar00djmdjm040c595b9643ab5bdc9d29586d33ef4063773db1a044ed21b7945c77f2705abe40030da23d8e1dff92f1bf26df6fa66db6ab0a249530860dfcc291790829a5a507 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1.pub100644 001750 001750 0000000003614775415623 0024016xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1.pub010064400017500001750000000002631477541562300224020ustar00djmdjmecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQc= ECDSA test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_1_pw100644 001750 001750 0000000003614775415623 0023737xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_1_pw010064400017500001750000000004721477541562300223250ustar00djmdjm-----BEGIN EC PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,7BA38DE00F67851E4207216809C3BB15 8QkFoZHQkj9a2mt032sp+WKaJ1fwteqWDd4RpAW9OzDgqzMx1QO43qJgBDTfhzjt M2Q8YfiGjfBEYpg4kCbacfcV68DEV4z6Ll7rIzzzO7OfWUNL++brD64vKx4z6f46 +sn4nbZTXilpkzi/nmPDVzrNmTSywA8T7Yf0QcBUxks= -----END EC PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_2.fp100644 001750 001750 0000000003614775415623 0023636xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_2.fp010064400017500001750000000000631477541562300222200ustar00djmdjmSHA256:ed8YniRHA6qCrErCRnzrWxPHxYuA62a+CAFYUVxJgaI openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_2.fp.bb100644 001750 001750 0000000003614775415623 0024220xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb010064400017500001750000000001021477541562300225740ustar00djmdjmxufag-danul-putub-mokin-pugaz-covid-dofag-nihuz-sysab-genar-zaxyx openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_2.param.curve100644 001750 001750 0000000003614775415623 0025454xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_2.param.curve010064400017500001750000000000121477541562300240300ustar00djmdjmsecp521r1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_2.param.priv100644 001750 001750 0000000003614775415623 0025310xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_2.param.priv010064400017500001750000000002051477541562300236700ustar00djmdjm01a81b4dedee84b2c777765b202125623c25d70b46ad94d906b683204907414ca5547de24e8b895c45969725d5e7a9652a23f284b07f21f1037861c07cba098071cf openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_2.param.pub100644 001750 001750 0000000003614775415623 0025116xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_2.param.pub010064400017500001750000000004131477541562300234770ustar00djmdjm0401d9d95372a0379d070aac77363e924369b5cf43aed4425663ba7142cb8feebdd4c848b6a56a4cc25b4c5948e0c9c083d3e819317fd0a98b25fcbcbd27df5c62aaab018a70536d7755c2a3eed0bbdb576f1ae89fd83a0e6bbbcbc8da2e48b17306709f02ece86980f6a646ba201f38657419ff7fbbdf2cafebe290e6b83b0e491434f0e6 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_2.pub100644 001750 001750 0000000003614775415623 0024017xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_2.pub010064400017500001750000000004171477541562300224040ustar00djmdjmecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHZ2VNyoDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g== ECDSA test key #2 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_n100644 001750 001750 0000000003614775415623 0023326xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_n010064400017500001750000000007541477541562300217170ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS 1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQMWVuWQ6tb3J0pWG0z70Bjdz2xoETt IbeUXHfycFq+QAMNoj2OHf+S8b8m32+mbbarCiSVMIYN/MKReQgppaUHAAAAoFrmmZBa5p mQAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlY bTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQ cAAAAhAPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMAAAAAAECAwQFBgc= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_n_pw100644 001750 001750 0000000003614775415623 0024034xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_n_pw010064400017500001750000000010311477541562300224120ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk1100644 001750 001750 0000000003614775415623 0023567xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk1010064400017500001750000000015211477541562300221510ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQRnVT5Cji1D Ge2+q2X0vATh6LYnODV+DJrshJorr5GnipW29RfuaDXs0WB6XBej9dOLazVRDjQrtV19Qg O6cfkFAAAABHNzaDoAAAGQuPdnP7j3Zz8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEZ1U+Qo4tQxntvqtl9LwE4ei2Jzg1fgya7I SaK6+Rp4qVtvUX7mg17NFgelwXo/XTi2s1UQ40K7VdfUIDunH5BQAAAARzc2g6AQAAAOMt LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJRURmVFB4YzA0alN5Zk Z5NlhoV1pTVlpzcnU5ZFlaSVpTOWhjeVFhcDlVT29Bb0dDQ3FHU000OQpBd0VIb1VRRFFn QUVaMVUrUW80dFF4bnR2cXRsOUx3RTRlaTJKemcxZmd5YTdJU2FLNitScDRxVnR2VVg3bW cxCjdORmdlbHdYby9YVGkyczFVUTQwSzdWZGZVSUR1bkg1QlE9PQotLS0tLUVORCBFQyBQ UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzEBAgMEBQ== -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk1-cert.fp100644 001750 001750 0000000003614775415623 0025126xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp010064400017500001750000000000631477541562300235100ustar00djmdjmSHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk1-cert.pub100644 001750 001750 0000000003614775415623 0025307xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub010064400017500001750000000012421477541562300236710ustar00djmdjmsk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgE012YoSBE9hEC2FRzblcSx784JNo2A4g611A7I75YMMAAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAAAAAAAHAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaLg2AAAAAATR3h4AAAAAAAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEAlTtPiWUHubBeCys4Xp0QF91dYARpkyqtCnzg10HRS+ZDgkMrSUvPPG+Ge8iqtnB951MBxDq9FqDFIkhQBYXDAAAAGQAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAEkAAAAhALY+eXRJjVGnMk38Sm5S+H5CloNq757ypsoxt+WYoadtAAAAIA42/mAhUfLij1GY7wl+OFrI+icB/t4tGiEUZmhx6Foo ECDSA-SK test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk1.fp100644 001750 001750 0000000003614775415623 0024173xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp010064400017500001750000000000631477541562300225550ustar00djmdjmSHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk1.fp.bb100644 001750 001750 0000000003614775415623 0024555xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb010064400017500001750000000001021477541562300231310ustar00djmdjmxovem-sacac-dageg-vovoc-symyz-bozal-cibiv-cyvat-vylyn-romib-hoxax openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk1.pub100644 001750 001750 0000000003614775415623 0024354xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk1.pub010064400017500001750000000003451477541562300227410ustar00djmdjmsk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOg== ECDSA-SK test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk1_pw100644 001750 001750 0000000003614775415623 0024275xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk1_pw010064400017500001750000000015721477541562300226650ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB6vcJVx2 cPc7yYRROup8VnAAAAEAAAAAEAAAB/AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3Bl bnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmi uvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAZBrvCxe xFz0bvzXwaPhrUHBeNCoZy/wNKDx0kxlxUPuA+lgOvy5l3lT3yxxd0qj5PQB+NTcuz8AAE 1f7aSWQNZSifox3COsBGoHV9C8i+glcxiBKheAZD+EBnRGjG8kbcaLhuYDW/I39qNe8lHW YSDjmvsT55Hy0IAtVRAXizDoXKNdFPTZisC67WyOSJ3ED7Fy4bfT4ApbvhoFTwjikZBEhy LOad1sbJa4eT19TsskYfQdnJf8sjAmCMOZY4ZV0FiNW5XZOp8nIal1oyULPfzTAm6oaeFN 0ImCSU3U8h4wUQ8q/3XvBWtTKycZaoou0AwPoP0QN95Ywte7FHezNPb/n8KD7k0S6h9XAX UcBeCe5NHyov/0ZzA2p737hzm3w+MXGOboTQMu8WFXeGh4m7QH2o8ZJdgBhM5JF17uii+Q ppGoPWHf33MXwB3wxWmKZ0ua0f9AVLkQ2DfFszUoBJE/kcHRd4kj4Q4FWXeMBN0GoH8gdE gRWIlxn2/FAOce/BFPzzdP87H0jwz7SdcuVO1L -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk2100644 001750 001750 0000000003614775415623 0023570xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk2010064400017500001750000000015211477541562300221520ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSTl+SR6rTg lOZmcQkCtJ3Pd+lWinezo/gHk4oZdZcTQsmEYs766BlWGuB2Bz3qQRLa6cXsP+4K9kAjAJ 7zdoFUAAAABHNzaDoAAAGQ1qllJtapZSYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEk5fkkeq04JTmZnEJArSdz3fpVop3s6P4B5 OKGXWXE0LJhGLO+ugZVhrgdgc96kES2unF7D/uCvZAIwCe83aBVAAAAARzc2g6AQAAAOMt LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSkxwVkxnSTVvdkRlOW VMWmZodCs5WWlMaitnam0rTXhHTXg5NndiRWw0Wm9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn QUVrNWZra2VxMDRKVG1abkVKQXJTZHozZnBWb3AzczZQNEI1T0tHWFdYRTBMSmhHTE8rdW daClZocmdkZ2M5NmtFUzJ1bkY3RC91Q3ZaQUl3Q2U4M2FCVkE9PQotLS0tLUVORCBFQyBQ UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzIBAgMEBQ== -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk2.fp100644 001750 001750 0000000003614775415623 0024174xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp010064400017500001750000000000631477541562300225560ustar00djmdjmSHA256:pz8VkgtRY3r50F4zSuzRlmq9c6vPTpJXLKKOgkyUcKE openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/pw100644 001750 001750 0000000003614775415623 0022360xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/pw010064400017500001750000000000171477541562300207410ustar00djmdjmmekmitasdigoat openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk2.fp.bb100644 001750 001750 0000000003614775415623 0024556xustar0030 atime=1744182234.734203269 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb010064400017500001750000000001021477541562300231320ustar00djmdjmxobel-gavur-gorym-pedop-rarob-bunek-gucer-lofeg-syhaf-fylur-zoxix openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ecdsa_sk2.pub100644 001750 001750 0000000003614775415623 0024355xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ecdsa_sk2.pub010064400017500001750000000003451477541562300227420ustar00djmdjmsk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBJOX5JHqtOCU5mZxCQK0nc936VaKd7Oj+AeTihl1lxNCyYRizvroGVYa4HYHPepBEtrpxew/7gr2QCMAnvN2gVQAAAAEc3NoOg== ECDSA-SK test key #2 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_1100644 001750 001750 0000000003614775415623 0023150xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_1010064400017500001750000000006331477541562300215350ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAJjnj4Ao54+A KAAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQ AAAED3KgoDbjR54V7bdNpfKlQY5m20UK1QaHytkCR+6rZEDFOG6kY7Rf4UtCFvPwKgo/Bz tXck2xC4a2WyA34XtIwZAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_1-cert.fp100644 001750 001750 0000000003614775415623 0024507xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_1-cert.fp010064400017500001750000000000631477541562300230710ustar00djmdjmSHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_1-cert.pub100644 001750 001750 0000000003614775415623 0024670xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_1-cert.pub010064400017500001750000000007461477541562300232620ustar00djmdjmssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIxzuxl4z3uwAIslne8Huft+1n1IhHAlNbWZkQyyECCGAAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZAAAAAAAAAAgAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABABGTn+Bmz86Ajk+iqKCSdP5NClsYzn4alJd0V5bizhP0Kumc/HbqQfSt684J1WdSzih+EjvnTgBhK9jTBKb90AQ== ED25519 test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_1.fp100644 001750 001750 0000000003614775415623 0023554xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_1.fp010064400017500001750000000000631477541562300221360ustar00djmdjmSHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_1.fp.bb100644 001750 001750 0000000003614775415623 0024136xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_1.fp.bb010064400017500001750000000001021477541562300225120ustar00djmdjmxubop-rekyd-bakal-nubuf-pahaf-gicuh-logeb-gocif-petod-galip-fuxux openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_1.pub100644 001750 001750 0000000003614775415623 0023735xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_1.pub010064400017500001750000000001451477541562300223200ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZ ED25519 test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_1_pw100644 001750 001750 0000000003614775415623 0023656xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_1_pw010064400017500001750000000007201477541562300222400ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDKT56mBA tXIMsWqmuuA2gdAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFv PwKgo/BztXck2xC4a2WyA34XtIwZAAAAoC13U47yfUOSZJePNUAwWXuFOk3aOKwPM5PMvK 0zwRnMZZjgn+tsMAYPwhsT3Mx3h5QzvVGFyFEqsiK7j4vAotD+LVQeBN5TwWbUBx4lnoGs 3iAfYVDakO/gNvVBDDGOqv5kdCc4cgn5HacjHQLKOAx6KzHe7JFn7uCywMdVVQjlpI6LHb mHkaKiVX/C2oiRnsoe17HZ8Fxyt3vd1qNM8BE= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_2100644 001750 001750 0000000003614775415623 0023151xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_2010064400017500001750000000006331477541562300215360ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCwAAAJix1mBGsdZg RgAAAAtzc2gtZWQyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCw AAAECZEQHXs18o3DKjhUYaTyt+bUbhqfMeqmsKjYyFvzGVgs9UrIuebd5kTSWbQh8zdTL0 Cx0ZIG2jNygK3bVuVgELAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_2.fp100644 001750 001750 0000000003614775415623 0023555xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_2.fp010064400017500001750000000000631477541562300221370ustar00djmdjmSHA256:vMbaARqVciRgXyZPNHDo+P5p5WK5yWG1Oo6VC35Bomw openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_2.fp.bb100644 001750 001750 0000000003614775415623 0024137xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_2.fp.bb010064400017500001750000000001021477541562300225130ustar00djmdjmxuces-bapyb-vikob-zesyv-budod-nupip-kebon-tacyc-fofed-lezic-soxax openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_2.pub100644 001750 001750 0000000003614775415623 0023736xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_2.pub010064400017500001750000000001451477541562300223210ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM9UrIuebd5kTSWbQh8zdTL0Cx0ZIG2jNygK3bVuVgEL ED25519 test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk1100644 001750 001750 0000000003614775415623 0023506xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk1010064400017500001750000000007441477541562300220760ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAhaP5OS1PPOt7uumAvXlDtte9EHbqIT1EZEJ2y 2v3XMwAAAARzc2g6AAAAuBocY6UaHGOlAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 9tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoBAAAAQJYq lGHhFoA25/q8X/rdTqDAb7dhqs4ehhd/w8x99CwiIWj+TktTzzre7rpgL15Q7bXvRB26iE 9RGRCdstr91zMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzEBAgM= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk1-cert.fp100644 001750 001750 0000000003614775415623 0025045xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp010064400017500001750000000000631477541562300234270ustar00djmdjmSHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk1-cert.pub100644 001750 001750 0000000003614775415623 0025226xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub010064400017500001750000000007701477541562300236150ustar00djmdjmsk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJr7CuMntQKvHoUshx374fJLFEkyxKsEOBA1H6hk5scoAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAAAAAAAACAAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIOo/0xneV3iM2qWEo5RUwvUYa2bjff292T5vvuXRomGQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECgsRGLDh1SI3m66MRp9D2iLP4wabQ0OrDgGidk7LsVn2XZHV5jBZN1RtNfe6PBMeVzfRtGUzOg18sO7H7uU+EC ED25519-SK test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk1.fp100644 001750 001750 0000000003614775415623 0024112xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk1.fp010064400017500001750000000000631477541562300224740ustar00djmdjmSHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk1.fp.bb100644 001750 001750 0000000003614775415623 0024474xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb010064400017500001750000000001021477541562300230500ustar00djmdjmxucac-vusip-tydoz-dudad-nerif-raran-tezun-cogyd-pamoh-bahef-ruxix openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk1.pub100644 001750 001750 0000000003614775415623 0024273xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk1.pub010064400017500001750000000002271477541562300226570ustar00djmdjmsk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDo= ED25519-SK test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk1_pw100644 001750 001750 0000000003614775415623 0024214xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk1_pw010064400017500001750000000010311477541562300225720ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDr5R9Yf/ ucEh0Ns6c34tcIAAAAEAAAAAEAAABKAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t AAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAADA2T6owx OSgKz4DvLnS3UJ/renbuew5mbkIWB1/y8xd3y5Usm08iUCAlKxep9dVRQvmyoTrc/7rHOM DkokNw+WgKambnlYT/9QfqViZ9iCBtbdmhLM6ksUCgQefvquRyXoJxlWstjXUll6Ru+ZbT H//Ss8C1bYtAiXR68OQ+rhDrvQxA9P8J1sGIlkuV3h8YXddSpyBW2Sn0LTHHBXYZo86cXZ G4Lnc8aGYm65eqdHgkfRmht3eS8DTdzEBfBNH5Ml -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk2100644 001750 001750 0000000003614775415623 0023507xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk2010064400017500001750000000007441477541562300220770ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAV8fu1Sc31QLK2R/zGPdN3ve5xuFvDc7mEAWxb aI+YcwAAAARzc2g6AAAAuJCMX5uQjF+bAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 9tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDoBAAAAQObE PajcKI1W30EKOhBb6u+Fgx464kf7EjnqDSg4l7gAFfH7tUnN9UCytkf8xj3Td73ucbhbw3 O5hAFsW2iPmHMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzIBAgM= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk2.fp100644 001750 001750 0000000003614775415623 0024113xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk2.fp010064400017500001750000000000631477541562300224750ustar00djmdjmSHA256:b9BVPS5vuU4yu/FgweojLLg6zbfmBBoWLUgibdxxsoo openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk2.fp.bb100644 001750 001750 0000000003614775415623 0024475xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb010064400017500001750000000001021477541562300230510ustar00djmdjmxemac-tizim-dihep-supar-zupib-cukak-pasis-febeg-dyguv-hutec-dyxox openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/ed25519_sk2.pub100644 001750 001750 0000000003614775415623 0024274xustar0030 atime=1744182234.735180046 openssh-10.0p1/regress/unittests/sshkey/testdata/ed25519_sk2.pub010064400017500001750000000002271477541562300226600ustar00djmdjmsk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDo= ED25519-SK test key #2 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1100644 001750 001750 0000000003614775415623 0022737xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1010064400017500001750000000015671477541562300213330ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1-cert.fp100644 001750 001750 0000000003614775415623 0024276xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1-cert.fp010064400017500001750000000000631477541562300226600ustar00djmdjmSHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1-cert.pub100644 001750 001750 0000000003614775415623 0024457xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1-cert.pub010064400017500001750000000011421477541562300230400ustar00djmdjmssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg98LhS2EHxLOWCLopZPwHdg/RJXusnkOqQXSc9R7aITkAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAAFAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaMAfAAAAAATR5gcAAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgU4bqRjtF/hS0IW8/AqCj8HO1dyTbELhrZbIDfhe0jBkAAABTAAAAC3NzaC1lZDI1NTE5AAAAQI3QGlUCzC07KorupxpDkkGy6tniaZ8EvBflzvv+itXWNchGvfUeHmVT6aX0sRqehdz/lR+GmXRoZBhofwh0qAM= RSA test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1.fp100644 001750 001750 0000000003614775415623 0023343xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1.fp010064400017500001750000000000631477541562300217250ustar00djmdjmSHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1.fp.bb100644 001750 001750 0000000003614775415623 0023725xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1.fp.bb010064400017500001750000000001021477541562300223010ustar00djmdjmxosis-fodod-votot-dibum-ryvac-rediz-naruf-votun-kevis-halis-gexux openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1.param.n100644 001750 001750 0000000003614775415623 0024272xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1.param.n010064400017500001750000000004031477541562300226520ustar00djmdjm00cb5799544edec5ac00ec781fc21a1119ce9a288e3116e72f3e78fbcba6998adcc98c235f2e77abf1ce92b76f064b624552c9f2582341e622e1a176eef232b5bac1bf3881babc0b7d57a1ef4439170852e192bc329d3523354a39610eab916e50c507c913a2a5f2c7596aad779c5f297121438bd2313ebb4ad4d7debba43271fb openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1.param.p100644 001750 001750 0000000003614775415623 0024274xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1.param.p010064400017500001750000000002031477541562300226520ustar00djmdjm00f56077ef05be4574906f52175ed8897e8da1626bc9b055534d6a20f6102c57c7a0b31b3e7864b101f4d3d57c35192bc949e14243a9e956361de23c5dd179f583 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1.param.q100644 001750 001750 0000000003614775415623 0024275xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1.param.q010064400017500001750000000002031477541562300226530ustar00djmdjm00d42541cc014be26370a657953f3adfcbaf713f781639adba33133f184eb3c7d8c2ec7810dca3da58a746fc5b87b34f396934436832e619c67c22f32ebbb36029 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1.pub100644 001750 001750 0000000003614775415623 0023524xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1.pub010064400017500001750000000003451477541562300221110ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1_pw100644 001750 001750 0000000003614775415623 0023445xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1_pw010064400017500001750000000017321477541562300220330ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1_sha1100644 001750 001750 0000000003614775415623 0023653xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1_sha1010064400017500001750000000015671477541562300222470ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1_sha1-cert.pub100644 001750 001750 0000000003614775415623 0025373xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub010064400017500001750000000025521477541562300237620ustar00djmdjmssh-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 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1_sha1.pub100644 001750 001750 0000000003614775415623 0024440xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1_sha1.pub010064400017500001750000000003451477541562300230250ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1_sha512100644 001750 001750 0000000003614775415623 0024022xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1_sha512010064400017500001750000000015671477541562300224160ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1_sha512-cert.pub100644 001750 001750 0000000003614775415623 0025542xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub010064400017500001750000000025621477541562300241320ustar00djmdjmssh-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 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_1_sha512.pub100644 001750 001750 0000000003614775415623 0024607xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_1_sha512.pub010064400017500001750000000003451477541562300231740ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_2100644 001750 001750 0000000003614775415623 0022740xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_2010064400017500001750000000032171477541562300213260ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_2.fp100644 001750 001750 0000000003614775415623 0023344xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_2.fp010064400017500001750000000000631477541562300217260ustar00djmdjmSHA256:NoQh0XBUuYUSWqnzOzOBnfpgJTRWLMj7BlWAb8IbjeE openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_2.fp.bb100644 001750 001750 0000000003614775415623 0023726xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_2.fp.bb010064400017500001750000000001021477541562300223020ustar00djmdjmxogit-gupof-mydon-hocep-zuval-feson-rarif-cefar-tobar-ryvap-kuxex openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_2.param.n100644 001750 001750 0000000003614775415623 0024273xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_2.param.n010064400017500001750000000010031477541562300226500ustar00djmdjm00f4d1145e9efc4809262f8f9e023e260733ce8e4f9c7023d5ce44d1fa66497724f09090011d4378727e1ada44e687b12bf8df025c2b22ab120e57519f1f67f068288194e117790262fdc323c6bf645563b81610ba97552a6ef3d476b5025198c54c0f7f021f4c2a093ba8662ae528c4de9fac9f818b85129baa6abd2e388780c9a406ebff6b54a58adfab5c7cced85f1f1f98648de1e2bf2615830e3968dbc609ed9145f6e9a1e5b6991b6022fef2f7049ec2de9a9a11035d2a3f17a9a4a80ef15629f3ae8e4d7adb445cba3dd6d03d1dbe9feb1fcc73f1890cd5d32a1a56086789eb17969c079f0d939158063b63d61bb80c61109562f502f9356a05380d02eb openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_2.param.p100644 001750 001750 0000000003614775415623 0024275xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_2.param.p010064400017500001750000000004031477541562300226550ustar00djmdjm00fb82dee3474e88898acebcf23b8a970737490ea07abe5f7c0837c9a36111ca4792f3ad759945fc27d7f78c5accca2ffd8a85c24be949274ab17f8f797b9aaa76f584f28d617e6de3953d46307fa31ec12108ffdab3f105fb3df54156f4728fe07b1598bbb5c5e260d4f73d8b29532bfc6b9f07d8899f87ec819571c8b38e7a87 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_2.param.q100644 001750 001750 0000000003614775415623 0024276xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_2.param.q010064400017500001750000000004031477541562300226560ustar00djmdjm00f92f9f57e501dc41cc91ff3b4ad7a2283612d66c0d130f639d4c18376a54e5b5e1939f4d5966bb43929e448a426dadc1fae84cf0d56f64d8df04d1badcfc1fdc8e156d5cd4dcf860ec936fc166261136156010f6df10a70525867d7989fef6752fd8db6faf3fe018bbbc1fa862fb4155445e1a398468d78b4e77884bdf5c197d openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_2.pub100644 001750 001750 0000000003614775415623 0023525xustar0030 atime=1744182234.736157004 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_2.pub010064400017500001750000000006151477541562300221120ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLr RSA test key #2 openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_n100644 001750 001750 0000000003614775415623 0023034xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_n010064400017500001750000000017741477541562300214300ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/testdata/PaxHeaders.10889/rsa_n_pw100644 001750 001750 0000000003614775415623 0023542xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshkey/testdata/rsa_n_pw010064400017500001750000000020651477541562300221300ustar00djmdjm-----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----- openssh-10.0p1/regress/unittests/sshkey/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021504xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshkey/tests.c010064400017500001750000000005671477541562300200770ustar00djmdjm/* $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(); } openssh-10.0p1/regress/unittests/PaxHeaders.10889/sshsig040755 001750 001750 0000000003614775415623 0020121xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig004075500017500001750000000000001477541562300164775ustar00djmdjmopenssh-10.0p1/regress/unittests/sshsig/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021630xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/Makefile010064400017500001750000000014301477541562300202110ustar00djmdjm# $OpenBSD: Makefile,v 1.3 2023/01/15 23:35:10 djm Exp $ PROG=test_sshsig SRCS=tests.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c sshsig.c SRCS+=ed25519.c hash.c 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 openssh-10.0p1/regress/unittests/sshsig/PaxHeaders.10889/mktestdata.sh100755 001750 001750 0000000003614775415623 0022670xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/mktestdata.sh010075500017500001750000000027111477541562300212540ustar00djmdjm#!/bin/sh # $OpenBSD: mktestdata.sh,v 1.1 2020/06/19 04:32:09 djm Exp $ NAMESPACE=unittest set -ex cd testdata if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so else echo "Can't find sk-dummy.so" 1>&2 exit 1 fi rm -f signed-data namespace rm -f rsa dsa ecdsa ed25519 ecdsa_sk ed25519_sk rm -f rsa.sig dsa.sig ecdsa.sig ed25519.sig ecdsa_sk.sig ed25519_sk.sig printf "This is a test, this is only a test" > signed-data printf "$NAMESPACE" > namespace ssh-keygen -t rsa -C "RSA test" -N "" -f rsa -m PEM ssh-keygen -t dsa -C "DSA test" -N "" -f dsa -m PEM ssh-keygen -t ecdsa -C "ECDSA test" -N "" -f ecdsa -m PEM ssh-keygen -t ed25519 -C "ED25519 test key" -N "" -f ed25519 ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key" \ -N "" -f ecdsa_sk ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key" \ -N "" -f ed25519_sk ssh-keygen -Y sign -f rsa -n $NAMESPACE - < signed-data > rsa.sig ssh-keygen -Y sign -f dsa -n $NAMESPACE - < signed-data > dsa.sig ssh-keygen -Y sign -f ecdsa -n $NAMESPACE - < signed-data > ecdsa.sig ssh-keygen -Y sign -f ed25519 -n $NAMESPACE - < signed-data > ed25519.sig ssh-keygen -w "$SK_DUMMY" \ -Y sign -f ecdsa_sk -n $NAMESPACE - < signed-data > ecdsa_sk.sig ssh-keygen -w "$SK_DUMMY" \ -Y sign -f ed25519_sk -n $NAMESPACE - < signed-data > ed25519_sk.sig openssh-10.0p1/regress/unittests/sshsig/PaxHeaders.10889/testdata040755 001750 001750 0000000003614775415623 0021732xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata004075500017500001750000000000001477541562300203105ustar00djmdjmopenssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/dsa100644 001750 001750 0000000003614775415623 0022473xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/dsa010064400017500001750000000012341477541562300210560ustar00djmdjm-----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQCXpndQdz2mQVnk+lYOF3nxDT+h6SiJmUvBFhnFWBv8tG4pTOkb EwGufLEzGpzjTj+3bjVau7LFt37AFrqs4Num272BWNsYNIjOlGPgq7Xjv32FN00x JYh1DoRs1cGGnvohlsWEamGGhTHD1a9ipctPEBV+NrxtZMrl+pO/ZZg8vQIVAKJB P3iNYSpSuW74+q4WxLCuK8O3AoGAQldE+BIuxlvoG1IFiWesx0CU+H2KO0SEZc9A SX/qjOabh0Fb78ofTlEf9gWHFfat8SvSJQIOPMVlb76Lio8AAMT8Eaa/qQKKYmQL dNq4MLhhjxx5KLGt6J2JyFPExCv+qnHYHD59ngtLwKyqGjpSC8LPLktdXn8W/Aad Ly1K7+MCgYBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSN u4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dB yJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501BkwIVAILIa3Rg 0h7J9lQpHJphvF3K0M1T -----END DSA PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/dsa.pub100644 001750 001750 0000000003614775415623 0023260xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/dsa.pub010064400017500001750000000011261477541562300216430ustar00djmdjmssh-dss AAAAB3NzaC1kc3MAAACBAJemd1B3PaZBWeT6Vg4XefENP6HpKImZS8EWGcVYG/y0bilM6RsTAa58sTManONOP7duNVq7ssW3fsAWuqzg26bbvYFY2xg0iM6UY+CrteO/fYU3TTEliHUOhGzVwYae+iGWxYRqYYaFMcPVr2Kly08QFX42vG1kyuX6k79lmDy9AAAAFQCiQT94jWEqUrlu+PquFsSwrivDtwAAAIBCV0T4Ei7GW+gbUgWJZ6zHQJT4fYo7RIRlz0BJf+qM5puHQVvvyh9OUR/2BYcV9q3xK9IlAg48xWVvvouKjwAAxPwRpr+pAopiZAt02rgwuGGPHHkosa3onYnIU8TEK/6qcdgcPn2eC0vArKoaOlILws8uS11efxb8Bp0vLUrv4wAAAIBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSNu4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dByJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501Bkw== DSA test openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/dsa.sig100644 001750 001750 0000000003614775415623 0023254xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/dsa.sig010064400017500001750000000014151477541562300216400ustar00djmdjm-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAAbEAAAAHc3NoLWRzcwAAAIEAl6Z3UHc9pkFZ5PpWDhd58Q0/oekoiZ lLwRYZxVgb/LRuKUzpGxMBrnyxMxqc404/t241Wruyxbd+wBa6rODbptu9gVjbGDSIzpRj 4Ku14799hTdNMSWIdQ6EbNXBhp76IZbFhGphhoUxw9WvYqXLTxAVfja8bWTK5fqTv2WYPL 0AAAAVAKJBP3iNYSpSuW74+q4WxLCuK8O3AAAAgEJXRPgSLsZb6BtSBYlnrMdAlPh9ijtE hGXPQEl/6ozmm4dBW+/KH05RH/YFhxX2rfEr0iUCDjzFZW++i4qPAADE/BGmv6kCimJkC3 TauDC4YY8ceSixreidichTxMQr/qpx2Bw+fZ4LS8Csqho6UgvCzy5LXV5/FvwGnS8tSu/j AAAAgGwwcFzOFJ5SHzDuLbQJWDg6U1OZ8lFVTa07o6kzFn+q6K1GbeEspI27jFGS8cnCLg uFC2/VJe8sjmCzk/eAIby2wgCLIKouKceFrreIF0mmqGdX/H+Pt0HImvfElueYt1YuSQK0 2TUivX8K4TP658DIsZ0paSwQC7VRSVvnTUGTAAAACHVuaXR0ZXN0AAAAAAAAAAZzaGE1MT IAAAA3AAAAB3NzaC1kc3MAAAAodi5lr0pqBpO76OY4N1CtfR85BCgZ95qfVjP/e9lToj0q lwjSJJXUjw== -----END SSH SIGNATURE----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa100644 001750 001750 0000000003614775415623 0023003xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa010064400017500001750000000003431477541562300213660ustar00djmdjm-----BEGIN EC PRIVATE KEY----- MHcCAQEEIFg0ZCSEB5LNeLsXYL25g3kqEWsqh52DR+yNOjyQJqyZoAoGCCqGSM49 AwEHoUQDQgAE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWb LzXBuUJucepaCNuW/QWgHBRbrjWj3ERm3A== -----END EC PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa.pub100644 001750 001750 0000000003614775415623 0023570xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa.pub010064400017500001750000000002541477541562300221540ustar00djmdjmecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN7LnfPBVdDfBT7KWUley1qo+rjzy0WYkrHpzbhGALXlj8g4K2bFmy81wblCbnHqWgjblv0FoBwUW641o9xEZtw= ECDSA test openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa.sig100644 001750 001750 0000000003614775415623 0023564xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa.sig010064400017500001750000000006131477541562300221470ustar00djmdjm-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAE EE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWbLzXBuUJucepaCNuW /QWgHBRbrjWj3ERm3AAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAAAZQAAABNlY2RzYS 1zaGEyLW5pc3RwMjU2AAAASgAAACEAycVNsTlE+XEZYyYiDxWZlliruf/pPMhEEMR/XLdQ a4MAAAAhALQt+5gES7L3uKGptHB6UZQMuZ2WyI0C6FJs4v6AtMIU -----END SSH SIGNATURE----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa_sk100644 001750 001750 0000000003614775415623 0023500xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa_sk010064400017500001750000000015051477541562300220640ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSg1WuY0XE+ VexOsrJsFYuxyVoe6eQ/oXmyz2pEHKZw9moyWehv+Fs7oZWFp3JVmOtybKQ6dvfUZYauQE /Ov4PAAAAABHNzaDoAAAGI6iV41+oleNcAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss 9qRBymcPZqMlnob/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AQAAAOMt LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJQm9oeW54M2tpTFVEeS t5UjU3WXBXSU5KektnU1p6WnV2VTljYXFla3JGcW9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn QUVvTlZybU5GeFBsWHNUckt5YkJXTHNjbGFIdW5rUDZGNXNzOXFSQnltY1BacU1sbm9iL2 hiCk82R1ZoYWR5VlpqcmNteWtPbmIzMUdXR3JrQlB6citEd0E9PQotLS0tLUVORCBFQyBQ UklWQVRFIEtFWS0tLS0tCgAAAAAAAAARRUNEU0EtU0sgdGVzdCBrZXk= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa_sk.pub100644 001750 001750 0000000003614775415623 0024265xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa_sk.pub010064400017500001750000000003421477541562300226470ustar00djmdjmsk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBKDVa5jRcT5V7E6ysmwVi7HJWh7p5D+hebLPakQcpnD2ajJZ6G/4WzuhlYWnclWY63JspDp299Rlhq5AT86/g8AAAAAEc3NoOg== ECDSA-SK test key openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa_sk.sig100644 001750 001750 0000000003614775415623 0024261xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa_sk.sig010064400017500001750000000007041477541562300226450ustar00djmdjm-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAAH8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ AAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss9qRBymcPZqMlno b/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AAAACHVuaXR0ZXN0AAAAAA AAAAZzaGE1MTIAAAB3AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20A AABIAAAAIHohGwyy8iKT3zwd1TYA9V/Ioo7h/3zCJUtyq/Qigt/HAAAAIGzidTwq7D/kFa 7Xjcp/KkdbIs4MfQpfAW/0OciajlpzARI0Vng= -----END SSH SIGNATURE----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa_sk_webauthn.pub100644 001750 001750 0000000003614775415623 0026162xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub010064400017500001750000000003301477541562300245410ustar00djmdjmsk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBBRGwDjs4HhJFcn4tJ5Gr72KcmRmCS1OirETxaXvnsNApgoOLF1a/7rxldfSMHm73eT1nhHe97W8qicPPEAKDJQAAAALbWluZHJvdC5vcmc= openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ecdsa_sk_webauthn.sig100644 001750 001750 0000000003614775415623 0026156xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig010064400017500001750000000014751477541562300245500ustar00djmdjm-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAAIYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ AAAAhuaXN0cDI1NgAAAEEEFEbAOOzgeEkVyfi0nkavvYpyZGYJLU6KsRPFpe+ew0CmCg4s XVr/uvGV19Iwebvd5PWeEd73tbyqJw88QAoMlAAAAAttaW5kcm90Lm9yZwAAAAh1bml0dG VzdAAAAAAAAAAGc2hhNTEyAAABhwAAACt3ZWJhdXRobi1zay1lY2RzYS1zaGEyLW5pc3Rw MjU2QG9wZW5zc2guY29tAAAASQAAACBj2oMT9tb5wRXe6mdmf4/lgAO8wrgr95ouozwNg4 itnQAAACEAtU9g5wz3HchUiLfLD6plr9T4TiJ32lVCrATSjpiy0SMBAAADHwAAABdodHRw czovL3d3dy5taW5kcm90Lm9yZwAAAON7InR5cGUiOiJ3ZWJhdXRobi5nZXQiLCJjaGFsbG VuZ2UiOiJVMU5JVTBsSEFBQUFDSFZ1YVhSMFpYTjBBQUFBQUFBQUFBWnphR0UxTVRJQUFB QkFMTHU4WmdjU3h0Nk1zRlV6dWlaZ0c2R3dNZEo5ZDd4ZUU3WW9SSXcwZzlpSEpfd3NGRD cxbzRXbHllenZGV0VqYnFRMHFDN0Z3R3Bqa2pVUVAtTmQ2dyIsIm9yaWdpbiI6Imh0dHBz Oi8vd3d3Lm1pbmRyb3Qub3JnIiwiY3Jvc3NPcmlnaW4iOmZhbHNlfQAAAAA= -----END SSH SIGNATURE----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ed25519100644 001750 001750 0000000003614775415623 0022722xustar0030 atime=1744182234.737133802 openssh-10.0p1/regress/unittests/sshsig/testdata/ed25519010064400017500001750000000006331477541562300213070ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBAAAAJjpGas/6Rmr PwAAAAtzc2gtZWQyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBA AAAEDpSKRA1QKW6kYiQftGRWh+H0fNekzYLG6c3bzseoCpEolizSIN3DQV78VPNjVvvwjg f+P5HqbPYCYu3BOMdjAEAAAAEEVEMjU1MTkgdGVzdCBrZXkBAgMEBQ== -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ed25519.pub100644 001750 001750 0000000003614775415623 0023507xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/ed25519.pub010064400017500001750000000001421477541562300220670ustar00djmdjmssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIlizSIN3DQV78VPNjVvvwjgf+P5HqbPYCYu3BOMdjAE ED25519 test key openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ed25519.sig100644 001750 001750 0000000003614775415623 0023503xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/ed25519.sig010064400017500001750000000004561477541562300220730ustar00djmdjm-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgiWLNIg3cNBXvxU82NW+/COB/4/ keps9gJi7cE4x2MAQAAAAIdW5pdHRlc3QAAAAAAAAABnNoYTUxMgAAAFMAAAALc3NoLWVk MjU1MTkAAABAihQsbUzuNEFflk5Tw1+H9aLS7tZQk0RG8KW1DtOmDYYnWe3D3UKiG3fcJa DNg4vBWp1j1gLRiBMOF+gwYNegDg== -----END SSH SIGNATURE----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ed25519_sk100644 001750 001750 0000000003614775415623 0023417xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/ed25519_sk010064400017500001750000000007441477541562300220070ustar00djmdjm-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCbGg2F0GK7nOm4pQmAyCuGEjnhvs5q0TtjPbdN //+yxwAAAARzc2g6AAAAuBw56jAcOeowAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 9tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDoBAAAAQFXc 6dCwWewIk1EBofAouGZApW8+s0XekXenxtb78+x0mxoNhdBiu5zpuKUJgMgrhhI54b7Oat E7Yz23Tf//sscAAAAAAAAAE0VEMjU1MTktU0sgdGVzdCBrZXkBAgMEBQY= -----END OPENSSH PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ed25519_sk.pub100644 001750 001750 0000000003614775415623 0024204xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/ed25519_sk.pub010064400017500001750000000002241477541562300225650ustar00djmdjmsk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDo= ED25519-SK test key openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/ed25519_sk.sig100644 001750 001750 0000000003614775415623 0024200xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/ed25519_sk.sig010064400017500001750000000005471477541562300225710ustar00djmdjm-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAAEoAAAAac2stc3NoLWVkMjU1MTlAb3BlbnNzaC5jb20AAAAgmxoNhd Biu5zpuKUJgMgrhhI54b7OatE7Yz23Tf//sscAAAAEc3NoOgAAAAh1bml0dGVzdAAAAAAA AAAGc2hhNTEyAAAAZwAAABpzay1zc2gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAAEAi+7eTjW /+LQ2M+sCD+KFtH1n7VFFJon/SZFsxODyV8cWTlFKj617Ys1Ur5TV6uaEXQhck8rBA2oQI HTPANLIPARI0Vng= -----END SSH SIGNATURE----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/namespace100644 001750 001750 0000000003614775415623 0023660xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/namespace010064400017500001750000000000101477541562300222320ustar00djmdjmunittestopenssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/rsa100644 001750 001750 0000000003614775415623 0022511xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/rsa010064400017500001750000000046271477541562300211050ustar00djmdjm-----BEGIN RSA PRIVATE KEY----- MIIG4wIBAAKCAYEA386lmjRHtJpyj87BrS+ssMmtvc/1SPN0gXTPs9jZ1hYAq98P ca3/RYVM4HaSu6COztQJ2ZnZD3Te/XeBnIU2mfuvQEl+DiwisGeNglVyRCi7787f PFFfcxzZfDa7EB2qY8S3oaSGZK8QqzuGwmGAImjlQXz6J+HCd/eD/58GoCSSirIE CFWCAt+uNrOC/EmgAzsbfcfaIbbVzA40tlgU3hO2J42kddz8CisDTtDKQABFcOaQ ZycSfn7HDP+WgXLXXBUI9wVM1Tif1f+9MX08xIsvCvGzo7yLgbbTFLSGr5SkA+tO rYuoA7V8fge0id/3pnVtG1Ui3I7vejeAwf0HZqtFeBEnOwkIJFmZeMtFeOVf+4ki 4h1rDqAvSscNvMtLp6OXpbAATATAuEWEkIQBl1rngnEe0iC9iU9itKMW6qJ4FtIb 4ACH1EoU1x8vqrFecg2hvqfk5CZBJIbV28JFuGjac3OxBZ17Fqb8ljomUir1GrET 2z66NMgb5TjDD7BVAgMBAAECggGACfjDGCPMLhfTkuS7bGP7ZcUWoKZrX1y5jCsQ NgsraYaBcSb3ITGHdimCS139G68DreN0rOVV7oJejRyOAdNNo367SDn+C9ObmBCF FZGJDdBiz0SAXceiYRaf+hDWNNmdheR16hXShxnlvDtivbZqZx4VWN2gp7Y/W+kD UJhdSzVV8igMVfK5YDdnI7jL1UHSh1JS3z/QUEA9NmJLpvQ1uc9XBlwhP78g27Me 6pwS5tccQPOE65OqF0i+xa19nzbmnC940Y34yZeI/UE+PYaO2+asapvOfu/sboBH Yb5BuWXVEkSeRWI23SpuZbmfNTtVgiRoRqOvqM4G88LkhYjZ6xpDggxQwJiShiiD oWCucs0v3pX8H8/LbGs8l50SGI5nzUqAdZ7/QQucU/GuDiQtampntkLEDgf9KIw/ SDrtCw1E9fnCWj4Z71IYfepY9bVY6QUEcfTdnDcYSY1Z5tVpzeMHVLeo0lbNVZv9 2qmPnjjP/IvWbjjwu/PHpUWkUs0BAoHBAPx4YwPXWYgWnesMKXkjAHyO5KA4EyBr +rcEmOZkZDibC8PKYzIK2ztptuthahVovW20R/QJhJkO5teGZMeGPFq+floCeC5P la9CEYGYcTrzgSe1QM9IGMr1vGI1KIWck7VkJ0bkKoY40uIJSVZxnyG9pEpcwYSp tnOqA/f5YZUFctWvXUz46OfiLKstXLrcrGIU7YRmLv2rW9twnpJYTzE98g3KpVJ2 TI1pyvrDTdGeAQUTGCAjpviY6XR5d020vQKBwQDi76wsGLQ3XLI+OAE95Ljo0Mcl +KdJPVVQPq/VcjKgZQndFloflMRrmgNHme9gmsHOrf8DLZvEDbtT+gbmWslMFZQ9 om1kR404gfuGmfIYdBdOwWjuBLsZs3pfqDB4Xa3NkxljwOMYTp035n0r2UMFaSy3 gvpW7fsdPOGAJsqNhSw/JNHcokHeBm7VbV0aD7tSyIghmARb5c98fmrSPbiEo8mP ITIZlgbfZCq2KuXY4q16R3QvlpuSwitVobLR/3kCgcEAueH5JM7dQHFGe9RMhL/c j9i1Q7GFg4183lsoKBkqIPMmylSsjB+qIihHYS4r6O9g6PCfOXH4iqiKFY0BjlWr AjTW2naO/aniz1KZiQ0v8PNv2Eh/Gx4+AtDCjpwM5bLOnfLLaEp9dK1JttqXgGnP fAwgdg+s+3votWgr29tkmU+VqPagfxeUg4Xm1XFkoL/wu5Yk+iIx3trXms1kMuOK CvtMyBK3fetTmZqWs+Iv3XGz1oSkcqVNPiN3XyY/TJsRAoG/Q17jvjOXTNg4EkCO HdHJE1Tnyl4HS7bpnOj/Sl6cqQFV7Ey2dKm1pjwSvS714bgP0UvWaRshIxLwif2w DrLlD7FYUPPnhd24Dw6HnW4WcSwFv1uryv2cjgS6T6ueuB0Xe/AvmW2p/Y1ZHz9N 6baWLwUKQXCg4S3FXui0CVd6yoi+mgBUTSveYguG29WbziDde7YMs+xtXtravhrJ m6C3Jql5LQSt2uqvH6KdC3ewxLKGzcZot7f+d5MtSj6216ECgcEA9PGmWeUkhVuW Xz2c9iBeHwCtmDso7gVwxNnHqdqirB4f1nDCGbrJS7hz5Ss7/wfzekP2W5if2P6U JPUdfykAQgALNn1twAtj1a+UAp31ZWu8JK/Qzt4hLJPBxzMo7MenJq189JmYmDnm 6D5d9vDLCW15gCZua89GZa8K8V50lYyeHBOHAyzNTfNlnMBkHyP645+nqpuEWzIT 3mCe2OAbl60o8VvvVUlAQyQ/ObLq37HHEoDu0U/YAnP157cxpa84 -----END RSA PRIVATE KEY----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/rsa.pub100644 001750 001750 0000000003614775415623 0023276xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/rsa.pub010064400017500001750000000010621477541562300216600ustar00djmdjmssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfzqWaNEe0mnKPzsGtL6ywya29z/VI83SBdM+z2NnWFgCr3w9xrf9FhUzgdpK7oI7O1AnZmdkPdN79d4GchTaZ+69ASX4OLCKwZ42CVXJEKLvvzt88UV9zHNl8NrsQHapjxLehpIZkrxCrO4bCYYAiaOVBfPon4cJ394P/nwagJJKKsgQIVYIC3642s4L8SaADOxt9x9ohttXMDjS2WBTeE7YnjaR13PwKKwNO0MpAAEVw5pBnJxJ+fscM/5aBctdcFQj3BUzVOJ/V/70xfTzEiy8K8bOjvIuBttMUtIavlKQD606ti6gDtXx+B7SJ3/emdW0bVSLcju96N4DB/Qdmq0V4ESc7CQgkWZl4y0V45V/7iSLiHWsOoC9Kxw28y0uno5elsABMBMC4RYSQhAGXWueCcR7SIL2JT2K0oxbqongW0hvgAIfUShTXHy+qsV5yDaG+p+TkJkEkhtXbwkW4aNpzc7EFnXsWpvyWOiZSKvUasRPbPro0yBvlOMMPsFU= RSA test openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/rsa.sig100644 001750 001750 0000000003614775415623 0023272xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/rsa.sig010064400017500001750000000022771477541562300216650ustar00djmdjm-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAN/OpZo0R7Saco/Owa0vrL DJrb3P9UjzdIF0z7PY2dYWAKvfD3Gt/0WFTOB2krugjs7UCdmZ2Q903v13gZyFNpn7r0BJ fg4sIrBnjYJVckQou+/O3zxRX3Mc2Xw2uxAdqmPEt6GkhmSvEKs7hsJhgCJo5UF8+ifhwn f3g/+fBqAkkoqyBAhVggLfrjazgvxJoAM7G33H2iG21cwONLZYFN4TtieNpHXc/AorA07Q ykAARXDmkGcnEn5+xwz/loFy11wVCPcFTNU4n9X/vTF9PMSLLwrxs6O8i4G20xS0hq+UpA PrTq2LqAO1fH4HtInf96Z1bRtVItyO73o3gMH9B2arRXgRJzsJCCRZmXjLRXjlX/uJIuId aw6gL0rHDbzLS6ejl6WwAEwEwLhFhJCEAZda54JxHtIgvYlPYrSjFuqieBbSG+AAh9RKFN cfL6qxXnINob6n5OQmQSSG1dvCRbho2nNzsQWdexam/JY6JlIq9RqxE9s+ujTIG+U4ww+w VQAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAABlAAAAAxyc2Etc2hhMi01MTIAAAGACi nEpBrQxZi0yOrrT6h98JFfZh0XXioih4fzmvtoV0yOReWClS+otGgXoJyZHcbaKNOjDwSM rIkUoX6OUJmtHYP0HRELnKw35m33LdBPXpFGS4tRS7NeSpvc04KtjT6jYXY9FjWy5hcn17 Sxc/3DnJqLgJBur8acY7FeIzpWmKixPd/dGkEjdWoD9gO6szLczGuQgrOdYmSRL4yKadTJ lVjz5OSeKSYYGQy33US2XQassRRNYf4e9byTA3DKvHa/OcTt7lFerea0kZdDpAboqffz7T Yaw/hFskAYLIEdTW3aoXBGHSOvu8AkDOtb7qwuxGSQ27pjkDLDNsp1ceCFaCaQ6X83RZuK ACv9JUBI5KaSf81e0bs0KezJKkhB9czeZ6dk96qISbgayEBnvhYgXvUDKtHn7HzNlCJKfK 5ABhNxfGG2CD+NKqcrndwFgS1sQO3hbA84zPQb26ShBovT8ytHBmW1F8ZK4O9Bz61Q6EZK vs/u6xP6LUean/so5daa -----END SSH SIGNATURE----- openssh-10.0p1/regress/unittests/sshsig/testdata/PaxHeaders.10889/signed-data100644 001750 001750 0000000003614775415623 0024104xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/testdata/signed-data010064400017500001750000000000431477541562300224640ustar00djmdjmThis is a test, this is only a testopenssh-10.0p1/regress/unittests/sshsig/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021476xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/tests.c010064400017500001750000000061101477541562300200570ustar00djmdjm/* $OpenBSD: tests.c,v 1.4 2024/01/11 01:45:59 djm Exp $ */ /* * Regress test for sshbuf.h buffer API * * Placed in the public domain */ #include "includes.h" #include #include #include #include #ifdef HAVE_STDINT_H #include #endif #include #include #include #ifdef WITH_OPENSSL #include #include #endif #include "ssherr.h" #include "authfile.h" #include "sshkey.h" #include "sshbuf.h" #include "sshsig.h" #include "log.h" #include "../test_helper/test_helper.h" static struct sshbuf * load_file(const char *name) { struct sshbuf *ret = NULL; ASSERT_INT_EQ(sshbuf_load_file(test_data_file(name), &ret), 0); ASSERT_PTR_NE(ret, NULL); return ret; } static struct sshkey * load_key(const char *name) { struct sshkey *ret = NULL; ASSERT_INT_EQ(sshkey_load_public(test_data_file(name), &ret, NULL), 0); ASSERT_PTR_NE(ret, NULL); return ret; } static void check_sig(const char *keyname, const char *signame, const struct sshbuf *msg, const char *namespace) { struct sshkey *k, *sign_key; struct sshbuf *sig, *rawsig; struct sshkey_sig_details *sig_details; k = load_key(keyname); sig = load_file(signame); sign_key = NULL; sig_details = NULL; rawsig = NULL; ASSERT_INT_EQ(sshsig_dearmor(sig, &rawsig), 0); ASSERT_INT_EQ(sshsig_verifyb(rawsig, msg, namespace, &sign_key, &sig_details), 0); ASSERT_INT_EQ(sshkey_equal(k, sign_key), 1); sshkey_free(k); sshkey_free(sign_key); sshkey_sig_details_free(sig_details); sshbuf_free(sig); sshbuf_free(rawsig); } void tests(void) { struct sshbuf *msg; char *namespace; #if 0 log_init("test_sshsig", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); #endif #ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); #endif TEST_START("load data"); msg = load_file("namespace"); namespace = sshbuf_dup_string(msg); ASSERT_PTR_NE(namespace, NULL); sshbuf_free(msg); msg = load_file("signed-data"); TEST_DONE(); #ifdef WITH_OPENSSL TEST_START("check RSA signature"); check_sig("rsa.pub", "rsa.sig", msg, namespace); TEST_DONE(); #ifdef WITH_DSA TEST_START("check DSA signature"); check_sig("dsa.pub", "dsa.sig", msg, namespace); TEST_DONE(); #endif #ifdef OPENSSL_HAS_ECC TEST_START("check ECDSA signature"); check_sig("ecdsa.pub", "ecdsa.sig", msg, namespace); TEST_DONE(); #endif #endif TEST_START("check ED25519 signature"); check_sig("ed25519.pub", "ed25519.sig", msg, namespace); TEST_DONE(); #ifdef ENABLE_SK #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) TEST_START("check ECDSA-SK signature"); check_sig("ecdsa_sk.pub", "ecdsa_sk.sig", msg, namespace); TEST_DONE(); #endif TEST_START("check ED25519-SK signature"); check_sig("ed25519_sk.pub", "ed25519_sk.sig", msg, namespace); TEST_DONE(); #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) TEST_START("check ECDSA-SK webauthn signature"); check_sig("ecdsa_sk_webauthn.pub", "ecdsa_sk_webauthn.sig", msg, namespace); TEST_DONE(); #endif #endif /* ENABLE_SK */ sshbuf_free(msg); free(namespace); } openssh-10.0p1/regress/unittests/sshsig/PaxHeaders.10889/webauthn.html100644 001750 001750 0000000003614775415623 0022673xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/sshsig/webauthn.html010064400017500001750000000540661477541562300212710ustar00djmdjm webauthn test

webauthn test

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

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

Lots of debugging is printed along the way.

Enroll

Username:
openssh-10.0p1/regress/unittests/PaxHeaders.10889/test_helper040755 001750 001750 0000000003614775415623 0021137xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/test_helper004075500017500001750000000000001477541562300175155ustar00djmdjmopenssh-10.0p1/regress/unittests/test_helper/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0022646xustar0030 atime=1744182234.738109508 openssh-10.0p1/regress/unittests/test_helper/Makefile010064400017500001750000000003661477541562300212360ustar00djmdjm# $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 openssh-10.0p1/regress/unittests/test_helper/PaxHeaders.10889/fuzz.c100644 001750 001750 0000000003614775415623 0022350xustar0030 atime=1744182234.739086696 openssh-10.0p1/regress/unittests/test_helper/fuzz.c010064400017500001750000000242361477541562300207420ustar00djmdjm/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 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. */ /* Utility functions/framework for fuzz tests */ #include "includes.h" #include #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #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(1, sizeof(*ret)); 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(); } } openssh-10.0p1/regress/unittests/test_helper/PaxHeaders.10889/test_helper.c100644 001750 001750 0000000003614775415623 0023670xustar0030 atime=1744182234.739086696 openssh-10.0p1/regress/unittests/test_helper/test_helper.c010064400017500001750000000326401477541562300222600ustar00djmdjm/* $OpenBSD: test_helper.c,v 1.13 2021/12/14 21:25:27 deraadt 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. */ /* Utility functions/framework for regress tests */ #include "includes.h" #include #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #endif #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) # include #endif #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) #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 ? "" : 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, MINIMUM(l, 256)); aa2_tohex = tohex(aa2, MINIMUM(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, MINIMUM(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(); } openssh-10.0p1/regress/unittests/test_helper/PaxHeaders.10889/test_helper.h100644 001750 001750 0000000003614775415623 0023675xustar0030 atime=1744182234.739086696 openssh-10.0p1/regress/unittests/test_helper/test_helper.h010064400017500001750000000325651477541562300222730ustar00djmdjm/* $OpenBSD: test_helper.h,v 1.9 2018/10/17 23:28:05 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. */ /* Utility functions/framework for regress tests */ #ifndef _TEST_HELPER_H #define _TEST_HELPER_H #include "includes.h" #include #ifdef HAVE_STDINT_H # include #endif #ifdef WITH_OPENSSL #include #include #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 */ openssh-10.0p1/regress/unittests/PaxHeaders.10889/utf8040755 001750 001750 0000000003614775415623 0017507xustar0030 atime=1744182234.739086696 openssh-10.0p1/regress/unittests/utf8004075500017500001750000000000001477541562300160655ustar00djmdjmopenssh-10.0p1/regress/unittests/utf8/PaxHeaders.10889/Makefile100644 001750 001750 0000000003614775415623 0021216xustar0030 atime=1744182234.739086696 openssh-10.0p1/regress/unittests/utf8/Makefile010064400017500001750000000003731477541562300176040ustar00djmdjm# $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 openssh-10.0p1/regress/unittests/utf8/PaxHeaders.10889/tests.c100644 001750 001750 0000000003614775415623 0021064xustar0030 atime=1744182234.740062832 openssh-10.0p1/regress/unittests/utf8/tests.c010064400017500001750000000057161477541562300174600ustar00djmdjm/* $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 in 2016 * and placed in the public domain. */ #include "includes.h" #include #include #include #include #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"); } openssh-10.0p1/regress/PaxHeaders.10889/try-ciphers.sh100644 001750 001750 0000000003614775415623 0017433xustar0030 atime=1744182234.722485204 openssh-10.0p1/regress/try-ciphers.sh010064400017500001750000000013131477541562300160140ustar00djmdjm# $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 openssh-10.0p1/regress/PaxHeaders.10889/valgrind-unit.sh100755 001750 001750 0000000003614775415623 0017750xustar0030 atime=1744182234.740062832 openssh-10.0p1/regress/valgrind-unit.sh010075500017500001750000000012001477541562300163240ustar00djmdjm#!/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 mkdir -p "$OBJ/valgrind-out" exec $VG_PATH $VG_OPTS $UNIT_BINARY $UNIT_ARGS openssh-10.0p1/regress/PaxHeaders.10889/yes-head.sh100644 001750 001750 0000000003614775415623 0016661xustar0030 atime=1744182234.740062832 openssh-10.0p1/regress/yes-head.sh010064400017500001750000000006221477541562300152440ustar00djmdjm# $OpenBSD: yes-head.sh,v 1.7 2023/01/14 10:05:54 dtucker 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 openssh-10.0p1/PaxHeaders.10889/rijndael.c100644 001750 001750 0000000003614775415623 0015110xustar0030 atime=1744182234.740062832 openssh-10.0p1/rijndael.c010064400017500001750000001471121477541562300135010ustar00djmdjm/* $OpenBSD: rijndael.c,v 1.20 2015/03/16 11:09:52 djm Exp $ */ /** * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include "rijndael.h" #undef FULL_UNROLL /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01]; */ static const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; static const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; static const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; static const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; #if 0 static const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; static const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; static const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; static const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; static const u8 Td4[256] = { 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; #endif static const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) #define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int i = 0; u32 temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); if (keyBits == 128) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te0[(temp ) & 0xff] & 0x0000ff00) ^ (Te1[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { return 10; } rk += 4; } } rk[4] = GETU32(cipherKey + 16); rk[5] = GETU32(cipherKey + 20); if (keyBits == 192) { for (;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te0[(temp ) & 0xff] & 0x0000ff00) ^ (Te1[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if (++i == 8) { return 12; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } rk[6] = GETU32(cipherKey + 24); rk[7] = GETU32(cipherKey + 28); if (keyBits == 256) { for (;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te0[(temp ) & 0xff] & 0x0000ff00) ^ (Te1[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if (++i == 7) { return 14; } temp = rk[11]; rk[12] = rk[ 4] ^ (Te2[(temp >> 24) ] & 0xff000000) ^ (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(temp ) & 0xff] & 0x000000ff); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } #if 0 /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int Nr, i, j; u32 temp; /* expand the cipher key: */ Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te1[(rk[0] >> 24) ] & 0xff] ^ Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[0] ) & 0xff] & 0xff]; rk[1] = Td0[Te1[(rk[1] >> 24) ] & 0xff] ^ Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[1] ) & 0xff] & 0xff]; rk[2] = Td0[Te1[(rk[2] >> 24) ] & 0xff] ^ Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[2] ) & 0xff] & 0xff]; rk[3] = Td0[Te1[(rk[3] >> 24) ] & 0xff] ^ Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[3] ) & 0xff] & 0xff]; } return Nr; } #endif void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[4]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[5]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[6]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Te0[(t0 >> 24) ] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[(t3 ) & 0xff] ^ rk[0]; s1 = Te0[(t1 >> 24) ] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[(t0 ) & 0xff] ^ rk[1]; s2 = Te0[(t2 >> 24) ] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[(t1 ) & 0xff] ^ rk[2]; s3 = Te0[(t3 >> 24) ] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[(t2 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Te2[(t0 >> 24) ] & 0xff000000) ^ (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t3 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(ct , s0); s1 = (Te2[(t1 >> 24) ] & 0xff000000) ^ (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t0 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(ct + 4, s1); s2 = (Te2[(t2 >> 24) ] & 0xff000000) ^ (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t1 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(ct + 8, s2); s3 = (Te2[(t3 >> 24) ] & 0xff000000) ^ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t2 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(ct + 12, s3); } #if 0 static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; /* round 3: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; /* round 4: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; /* round 5: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; /* round 6: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; /* round 7: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; /* round 8: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; /* round 9: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; /* round 11: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; /* round 13: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[4]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[5]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[6]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Td0[(t0 >> 24) ] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[(t1 ) & 0xff] ^ rk[0]; s1 = Td0[(t1 >> 24) ] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[(t2 ) & 0xff] ^ rk[1]; s2 = Td0[(t2 >> 24) ] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[(t3 ) & 0xff] ^ rk[2]; s3 = Td0[(t3 >> 24) ] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[(t0 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Td4[(t0 >> 24) ] << 24) ^ (Td4[(t3 >> 16) & 0xff] << 16) ^ (Td4[(t2 >> 8) & 0xff] << 8) ^ (Td4[(t1 ) & 0xff]) ^ rk[0]; PUTU32(pt , s0); s1 = (Td4[(t1 >> 24) ] << 24) ^ (Td4[(t0 >> 16) & 0xff] << 16) ^ (Td4[(t3 >> 8) & 0xff] << 8) ^ (Td4[(t2 ) & 0xff]) ^ rk[1]; PUTU32(pt + 4, s1); s2 = (Td4[(t2 >> 24) ] << 24) ^ (Td4[(t1 >> 16) & 0xff] << 16) ^ (Td4[(t0 >> 8) & 0xff] << 8) ^ (Td4[(t3 ) & 0xff]) ^ rk[2]; PUTU32(pt + 8, s2); s3 = (Td4[(t3 >> 24) ] << 24) ^ (Td4[(t2 >> 16) & 0xff] << 16) ^ (Td4[(t1 >> 8) & 0xff] << 8) ^ (Td4[(t0 ) & 0xff]) ^ rk[3]; PUTU32(pt + 12, s3); } #endif openssh-10.0p1/PaxHeaders.10889/rijndael.h100644 001750 001750 0000000003614775415623 0015115xustar0030 atime=1744182234.740062832 openssh-10.0p1/rijndael.h010064400017500001750000000040571477541562300135060ustar00djmdjm/* $OpenBSD: rijndael.h,v 1.15 2021/09/28 11:14:50 dtucker Exp $ */ /** * rijndael-alg-fst.h * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. */ #ifndef _PRIVATE_RIJNDAEL_H #define _PRIVATE_RIJNDAEL_H #define AES_MAXKEYBITS (256) #define AES_MAXKEYBYTES (AES_MAXKEYBITS/8) /* for 256-bit keys, fewer for less */ #define AES_MAXROUNDS 14 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int); void rijndaelEncrypt(const unsigned int [], int, const u8 [16], u8 [16]); /* The structure for key information */ typedef struct { int decrypt; int Nr; /* key-length-dependent number of rounds */ u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */ } rijndael_ctx; void rijndael_set_key(rijndael_ctx *, u_char *, int, int); void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *); void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *); #endif /* _PRIVATE_RIJNDAEL_H */ openssh-10.0p1/PaxHeaders.10889/sandbox-capsicum.c100644 001750 001750 0000000003614775415623 0016560xustar0030 atime=1744182234.741039309 openssh-10.0p1/sandbox-capsicum.c010064400017500001750000000061411477541562300151450ustar00djmdjm/* * Copyright (c) 2011 Dag-Erling Smorgrav * * 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_CAPSICUM #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CAPSICUM_HELPERS_H #include #endif #include "log.h" #include "monitor.h" #include "ssh-sandbox.h" #include "xmalloc.h" /* * Capsicum sandbox that sets zero nfiles, nprocs and filesize rlimits, * limits rights on stdout, stdin, stderr, monitor and switches to * capability mode. */ struct ssh_sandbox { int m_recvfd; int m_log_sendfd; }; struct ssh_sandbox * ssh_sandbox_init(struct monitor *monitor) { struct ssh_sandbox *box; debug3("%s: preparing capsicum sandbox", __func__); box = xcalloc(1, sizeof(*box)); box->m_recvfd = monitor->m_recvfd; box->m_log_sendfd = monitor->m_log_sendfd; return box; } void ssh_sandbox_child(struct ssh_sandbox *box) { struct rlimit rl_zero; cap_rights_t rights; #ifdef HAVE_CAPH_CACHE_TZDATA caph_cache_tzdata(); #endif rl_zero.rlim_cur = rl_zero.rlim_max = 0; if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", __func__, strerror(errno)); #ifndef SANDBOX_SKIP_RLIMIT_NOFILE if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", __func__, strerror(errno)); #endif if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", __func__, strerror(errno)); cap_rights_init(&rights); if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) fatal("can't limit stdin: %m"); if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) fatal("can't limit stdout: %m"); if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) fatal("can't limit stderr: %m"); cap_rights_init(&rights, CAP_READ, CAP_WRITE); if (cap_rights_limit(box->m_recvfd, &rights) < 0 && errno != ENOSYS) fatal("%s: failed to limit the network socket", __func__); cap_rights_init(&rights, CAP_WRITE); if (cap_rights_limit(box->m_log_sendfd, &rights) < 0 && errno != ENOSYS) fatal("%s: failed to limit the logging socket", __func__); if (cap_enter() < 0 && errno != ENOSYS) fatal("%s: failed to enter capability mode", __func__); } #endif /* SANDBOX_CAPSICUM */ openssh-10.0p1/PaxHeaders.10889/sandbox-darwin.c100644 001750 001750 0000000003614775415623 0016240xustar0030 atime=1744182234.741039309 openssh-10.0p1/sandbox-darwin.c010064400017500001750000000044051477541562300146260ustar00djmdjm/* * 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" #ifdef SANDBOX_DARWIN #include #include #include #include #include #include #include #include #include "log.h" #include "ssh-sandbox.h" #include "monitor.h" #include "xmalloc.h" /* Darwin/OS X sandbox */ struct ssh_sandbox { int junk; }; struct ssh_sandbox * ssh_sandbox_init(struct monitor *monitor) { struct ssh_sandbox *box; /* * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ debug3("%s: preparing Darwin sandbox", __func__); box = xcalloc(1, sizeof(*box)); return box; } void ssh_sandbox_child(struct ssh_sandbox *box) { char *errmsg; struct rlimit rl_zero; debug3("%s: starting Darwin sandbox", __func__); if (sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED, &errmsg) == -1) fatal("%s: sandbox_init: %s", __func__, errmsg); /* * The kSBXProfilePureComputation still allows sockets, so * we must disable these using rlimit. */ rl_zero.rlim_cur = rl_zero.rlim_max = 0; if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", __func__, strerror(errno)); if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", __func__, strerror(errno)); if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", __func__, strerror(errno)); } #endif /* SANDBOX_DARWIN */ openssh-10.0p1/PaxHeaders.10889/sandbox-null.c100644 001750 001750 0000000003614775415623 0015726xustar0030 atime=1744182234.741039309 openssh-10.0p1/sandbox-null.c010064400017500001750000000027101477541562300143110ustar00djmdjm/* $OpenBSD$ */ /* * 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" #ifdef SANDBOX_NULL #include #include #include #include #include #include #include #include "log.h" #include "ssh-sandbox.h" #include "xmalloc.h" /* dummy sandbox */ struct ssh_sandbox { int junk; }; struct ssh_sandbox * ssh_sandbox_init(struct monitor *monitor) { struct ssh_sandbox *box; /* * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ box = xcalloc(1, sizeof(*box)); return box; } void ssh_sandbox_child(struct ssh_sandbox *box) { /* Nothing to do here */ } #endif /* SANDBOX_NULL */ openssh-10.0p1/PaxHeaders.10889/sandbox-rlimit.c100644 001750 001750 0000000003614775415623 0016254xustar0030 atime=1744182234.741039309 openssh-10.0p1/sandbox-rlimit.c010064400017500001750000000042161477541562300146420ustar00djmdjm/* $OpenBSD: sandbox-rlimit.c,v 1.5 2020/10/18 11:32:01 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" #ifdef SANDBOX_RLIMIT #include #include #include #include #include #include #include #include #include #include "log.h" #include "ssh-sandbox.h" #include "xmalloc.h" /* Minimal sandbox that sets zero nfiles, nprocs and filesize rlimits */ struct ssh_sandbox { int junk; }; struct ssh_sandbox * ssh_sandbox_init(struct monitor *monitor) { struct ssh_sandbox *box; /* * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ debug3_f("preparing rlimit sandbox"); box = xcalloc(1, sizeof(*box)); return box; } void ssh_sandbox_child(struct ssh_sandbox *box) { struct rlimit rl_zero; rl_zero.rlim_cur = rl_zero.rlim_max = 0; #ifndef SANDBOX_SKIP_RLIMIT_FSIZE if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) fatal_f("setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", strerror(errno)); #endif #ifndef SANDBOX_SKIP_RLIMIT_NOFILE if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) fatal_f("setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", strerror(errno)); #endif #ifdef HAVE_RLIMIT_NPROC if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) fatal_f("setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", strerror(errno)); #endif } #endif /* SANDBOX_RLIMIT */ openssh-10.0p1/PaxHeaders.10889/sandbox-seccomp-filter.c100644 001750 001750 0000000003614775415623 0017670xustar0030 atime=1744182234.741039309 openssh-10.0p1/sandbox-seccomp-filter.c010064400017500001750000000370271477541562300162640ustar00djmdjm/* * Copyright (c) 2012 Will Drewry * Copyright (c) 2015,2017,2019,2020,2023 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. */ /* * Uncomment the SANDBOX_SECCOMP_FILTER_DEBUG macro below to help diagnose * filter breakage during development. *Do not* use this in production, * as it relies on making library calls that are unsafe in signal context. * * Instead, live systems the auditctl(8) may be used to monitor failures. * E.g. * auditctl -a task,always -F uid= */ /* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ #if 0 /* * For older toolchains, it may be necessary to use the kernel * headers directly. */ #ifdef SANDBOX_SECCOMP_FILTER_DEBUG # include # define __have_siginfo_t 1 # define __have_sigval_t 1 # define __have_sigevent_t 1 #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ #endif #include "includes.h" #ifdef SANDBOX_SECCOMP_FILTER #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __s390__ #include #endif #include #include #include #include /* for offsetof */ #include #include #include #include #include "log.h" #include "ssh-sandbox.h" #include "xmalloc.h" /* Linux seccomp_filter sandbox */ #define SECCOMP_FILTER_FAIL SECCOMP_RET_KILL /* Use a signal handler to emit violations when debugging */ #ifdef SANDBOX_SECCOMP_FILTER_DEBUG # undef SECCOMP_FILTER_FAIL # 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), 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), 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)) /* Deny unless syscall argument contains only values in mask */ #define SC_DENY_UNLESS_ARG_MASK(_nr, _arg_nr, _arg_mask, _errno) \ 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, 3), \ /* 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, 1, 0), \ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno)), \ /* reload syscall number; all rules expect it in accumulator */ \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ offsetof(struct seccomp_data, nr)) #define SC_DENY_UNLESS_MASK(_nr, _arg_nr, _arg_val, _errno) \ /* Special handling for futex(2) that combines a bitmap and operation number */ #if defined(__NR_futex) || defined(__NR_futex_time64) #define SC_FUTEX_MASK (FUTEX_PRIVATE_FLAG|FUTEX_CLOCK_REALTIME) #define SC_ALLOW_FUTEX_OP(_nr, _op) \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \ /* load syscall argument, low word */ \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ offsetof(struct seccomp_data, args[1]) + ARG_LO_OFFSET), \ /* mask off allowed bitmap values, low word */ \ BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~(SC_FUTEX_MASK & 0xFFFFFFFF)), \ /* test operation number, low word */ \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((_op) & 0xFFFFFFFF), 0, 4), \ /* load syscall argument, high word */ \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ offsetof(struct seccomp_data, args[1]) + ARG_HI_OFFSET), \ /* mask off allowed bitmap values, high word */ \ BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \ ~(((uint32_t)((uint64_t)SC_FUTEX_MASK >> 32)) & 0xFFFFFFFF)), \ /* test operation number, high word */ \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ (((uint32_t)((uint64_t)(_op) >> 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)) /* Use this for both __NR_futex and __NR_futex_time64 */ # define SC_FUTEX(_nr) \ SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT), \ SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT_BITSET), \ SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE), \ SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE_BITSET), \ SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_REQUEUE), \ SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_CMP_REQUEUE) #endif /* __NR_futex || __NR_futex_time64 */ #if defined(__NR_mmap) || defined(__NR_mmap2) # ifdef MAP_FIXED_NOREPLACE # define SC_MMAP_FLAGS MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|MAP_FIXED_NOREPLACE # else # define SC_MMAP_FLAGS MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED # endif /* MAP_FIXED_NOREPLACE */ /* Use this for both __NR_mmap and __NR_mmap2 variants */ # define SC_MMAP(_nr) \ SC_DENY_UNLESS_ARG_MASK(_nr, 3, SC_MMAP_FLAGS, EINVAL), \ SC_ALLOW_ARG_MASK(_nr, 2, PROT_READ|PROT_WRITE|PROT_NONE) #endif /* __NR_mmap || __NR_mmap2 */ /* Syscall filtering set for preauth. */ static const struct sock_filter preauth_insns[] = { /* Ensure the syscall arch convention is as expected. */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, arch)), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0), BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), /* Load the syscall number for checking. */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)), /* 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_fstatat64 SC_DENY(__NR_fstatat64, 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 #ifdef __NR_statx SC_DENY(__NR_statx, 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_FUTEX(__NR_futex), #endif #ifdef __NR_futex_time64 SC_FUTEX(__NR_futex_time64), #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 #ifdef __NR_getpid SC_ALLOW(__NR_getpid), #endif #ifdef __NR_getrandom SC_ALLOW(__NR_getrandom), #endif #ifdef __NR_gettid SC_ALLOW(__NR_gettid), #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_ARG(__NR_madvise, 2, MADV_NORMAL), # ifdef MADV_FREE SC_ALLOW_ARG(__NR_madvise, 2, MADV_FREE), # endif # ifdef MADV_DONTNEED SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTNEED), # endif # ifdef MADV_DONTFORK SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTFORK), # endif # ifdef MADV_DONTDUMP SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTDUMP), # endif # ifdef MADV_WIPEONFORK SC_ALLOW_ARG(__NR_madvise, 2, MADV_WIPEONFORK), # endif SC_DENY(__NR_madvise, EINVAL), #endif #ifdef __NR_mmap SC_MMAP(__NR_mmap), #endif #ifdef __NR_mmap2 SC_MMAP(__NR_mmap2), #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 __NR_ppoll SC_ALLOW(__NR_ppoll), #endif #ifdef __NR_ppoll_time64 SC_ALLOW(__NR_ppoll_time64), #endif #ifdef __NR_poll SC_ALLOW(__NR_poll), #endif #ifdef __NR_pselect6 SC_ALLOW(__NR_pselect6), #endif #ifdef __NR_pselect6_time64 SC_ALLOW(__NR_pselect6_time64), #endif #ifdef __NR_read SC_ALLOW(__NR_read), #endif #ifdef __NR_rt_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_writev SC_ALLOW(__NR_writev), #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), }; static const struct sock_fprog preauth_program = { .len = (unsigned short)(sizeof(preauth_insns)/sizeof(preauth_insns[0])), .filter = (struct sock_filter *)preauth_insns, }; struct ssh_sandbox { int junk; }; struct ssh_sandbox * ssh_sandbox_init(struct monitor *monitor) { struct ssh_sandbox *box; /* * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ debug3("%s: preparing seccomp filter sandbox", __func__); box = xcalloc(1, sizeof(*box)); return box; } #ifdef SANDBOX_SECCOMP_FILTER_DEBUG extern struct monitor *pmonitor; void mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx); static void ssh_sandbox_violation(int signum, siginfo_t *info, void *void_context) { char msg[256]; snprintf(msg, sizeof(msg), "%s: unexpected system call (arch:0x%x,syscall:%d @ %p)", __func__, info->si_arch, info->si_syscall, info->si_call_addr); mm_log_handler(SYSLOG_LEVEL_FATAL, 0, msg, pmonitor); _exit(1); } static void ssh_sandbox_child_debugging(void) { struct sigaction act; sigset_t mask; debug3("%s: installing SIGSYS handler", __func__); memset(&act, 0, sizeof(act)); sigemptyset(&mask); sigaddset(&mask, SIGSYS); act.sa_sigaction = &ssh_sandbox_violation; act.sa_flags = SA_SIGINFO; if (sigaction(SIGSYS, &act, NULL) == -1) fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno)); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) fatal("%s: sigprocmask(SIGSYS): %s", __func__, strerror(errno)); } #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ void ssh_sandbox_child(struct ssh_sandbox *box) { struct rlimit rl_zero, rl_one = {.rlim_cur = 1, .rlim_max = 1}; int nnp_failed = 0; /* Set rlimits for completeness if possible. */ rl_zero.rlim_cur = rl_zero.rlim_max = 0; if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", __func__, strerror(errno)); /* * Cannot use zero for nfds, because poll(2) will fail with * errno=EINVAL if npfds>RLIMIT_NOFILE. */ if (setrlimit(RLIMIT_NOFILE, &rl_one) == -1) fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", __func__, strerror(errno)); if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", __func__, strerror(errno)); #ifdef SANDBOX_SECCOMP_FILTER_DEBUG ssh_sandbox_child_debugging(); #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__); if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { debug("%s: prctl(PR_SET_NO_NEW_PRIVS): %s", __func__, strerror(errno)); nnp_failed = 1; } debug3("%s: attaching seccomp filter program", __func__); if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1) debug("%s: prctl(PR_SET_SECCOMP): %s", __func__, strerror(errno)); else if (nnp_failed) fatal("%s: SECCOMP_MODE_FILTER activated but " "PR_SET_NO_NEW_PRIVS failed", __func__); } #endif /* SANDBOX_SECCOMP_FILTER */ openssh-10.0p1/PaxHeaders.10889/sandbox-solaris.c100644 001750 001750 0000000003614775415623 0016430xustar0030 atime=1744182234.741039309 openssh-10.0p1/sandbox-solaris.c010064400017500001750000000052701477541562300150170ustar00djmdjm/* * Copyright (c) 2015 Joyent, Inc * Author: Alex Wilson * * 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 #include #include #include #include #include #include #ifdef HAVE_PRIV_H # include #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)); } #endif /* SANDBOX_SOLARIS */ openssh-10.0p1/PaxHeaders.10889/scp.0100644 001750 001750 0000000003614775415623 0014022xustar0030 atime=1744182234.742015466 openssh-10.0p1/scp.0010064400017500001750000000253631477541562300124160ustar00djmdjmSCP(1) General Commands Manual SCP(1) NAME scp M-bM-^@M-^S OpenSSH secure file copy SYNOPSIS scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-J destination] [-l limit] [-o ssh_option] [-P port] [-S program] [-X sftp_option] source ... target DESCRIPTION scp copies files between hosts on a network. scp uses the SFTP protocol over a ssh(1) connection for data transfer, and uses the same authentication and provides the same security as a login session. scp will ask for passwords or passphrases if they are needed for authentication. The source and target may be specified as a local pathname, a remote host with optional path in the form [user@]host:[path], or a URI in the form scp://[user@]host[:port][/path]. 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. When copying between two remote hosts, if the URI format is used, a port cannot be specified on the target if the -R option is used. The options are as follows: -3 Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between the two remote hosts. Note that, when using the legacy SCP protocol (via the -O flag), this option selects batch mode for the second host as scp cannot ask for passwords or passphrases for both hosts. This mode is the default. -4 Forces scp to use IPv4 addresses only. -6 Forces scp to use IPv6 addresses only. -A Allows forwarding of ssh-agent(1) to the remote system. The default is not to forward an authentication agent. -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). -D sftp_server_path Connect directly to a local SFTP server program rather than a remote one 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. 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). -J destination Connect to the target host by first making an scp connection to the jump host described by 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 ProxyJump configuration directive. This option is directly passed to ssh(1). -l limit Limits the used bandwidth, specified in Kbit/s. -O Use the legacy SCP protocol for file transfers instead of the SFTP protocol. Forcing the use of the SCP protocol may be necessary for servers that do not implement SFTP, for backwards- compatibility for particular filename wildcard patterns and for expanding paths with a M-bM-^@M-^X~M-bM-^@M-^Y prefix for older SFTP servers. -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). AddKeysToAgent AddressFamily BatchMode BindAddress BindInterface CASignatureAlgorithms CanonicalDomains CanonicalizeFallbackLocal CanonicalizeHostname CanonicalizeMaxDots CanonicalizePermittedCNAMEs CertificateFile ChannelTimeout CheckHostIP Ciphers ClearAllForwardings Compression ConnectTimeout ConnectionAttempts ControlMaster ControlPath ControlPersist DynamicForward EnableEscapeCommandline EnableSSHKeysign EscapeChar ExitOnForwardFailure FingerprintHash ForkAfterAuthentication ForwardAgent ForwardX11 ForwardX11Timeout ForwardX11Trusted GSSAPIAuthentication GSSAPIDelegateCredentials GatewayPorts GlobalKnownHostsFile HashKnownHosts Host HostKeyAlgorithms HostKeyAlias HostbasedAcceptedAlgorithms HostbasedAuthentication Hostname IPQoS IdentitiesOnly IdentityAgent IdentityFile IgnoreUnknown Include KbdInteractiveAuthentication KbdInteractiveDevices KexAlgorithms KnownHostsCommand LocalCommand LocalForward LogLevel LogVerbose MACs NoHostAuthenticationForLocalhost NumberOfPasswordPrompts ObscureKeystrokeTiming PKCS11Provider PasswordAuthentication PermitLocalCommand PermitRemoteOpen Port PreferredAuthentications ProxyCommand ProxyJump ProxyUseFdpass PubkeyAcceptedAlgorithms PubkeyAuthentication RekeyLimit RemoteCommand RemoteForward RequestTTY RequiredRSASize RevokedHostKeys SecurityKeyProvider SendEnv ServerAliveCountMax ServerAliveInterval SessionType SetEnv StdinNull StreamLocalBindMask StreamLocalBindUnlink StrictHostKeyChecking SyslogFacility TCPKeepAlive Tag Tunnel TunnelDevice UpdateHostKeys User UserKnownHostsFile VerifyHostKeyDNS VisualHostKey XAuthLocation -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 mode bits of the file. -p Preserves modification times, access times, and file mode bits from the source file. -q Quiet mode: disables the progress meter as well as warning and diagnostic messages from ssh(1). -R Copies between two remote hosts are performed by connecting to the origin host and executing scp there. This requires that scp running on the origin host can authenticate to the destination host without requiring a password. -r 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. -T Disable strict filename checking. By default when copying files from a remote host to a local directory scp 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. -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. -X sftp_option Specify an option that controls aspects of SFTP protocol behaviour. The valid options are: nrequests=value Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download or upload. By default 64 requests may be active concurrently. buffer=value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By default a 32KB buffer is used. 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), sftp-server(8), sshd(8) HISTORY scp is based on the rcp program in BSD source code from the Regents of the University of California. Since OpenSSH 9.0, scp has used the SFTP protocol for transfers by default. AUTHORS Timo Rinne Tatu Ylonen CAVEATS The legacy SCP protocol (selected by the -O flag) requires execution of the remote user's shell to perform glob(3) pattern matching. This requires careful quoting of any characters that have special meaning to the remote shell, such as quote characters. OpenBSD 7.6 December 6, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/scp.1100644 001750 001750 0000000003614775415623 0014023xustar0030 atime=1744182234.742015466 openssh-10.0p1/scp.1010064400017500001750000000212621477541562300124110ustar00djmdjm.\" .\" scp.1 .\" .\" Author: Tatu Ylonen .\" .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" .\" $OpenBSD: scp.1,v 1.113 2024/12/06 15:12:56 djm Exp $ .\" .Dd $Mdocdate: December 6 2024 $ .Dt SCP 1 .Os .Sh NAME .Nm scp .Nd OpenSSH secure file copy .Sh SYNOPSIS .Nm scp .Op Fl 346ABCOpqRrsTv .Op Fl c Ar cipher .Op Fl D Ar sftp_server_path .Op Fl F Ar ssh_config .Op Fl i Ar identity_file .Op Fl J Ar destination .Op Fl l Ar limit .Op Fl o Ar ssh_option .Op Fl P Ar port .Op Fl S Ar program .Op Fl X Ar sftp_option .Ar source ... target .Sh DESCRIPTION .Nm copies files between hosts on a network. .Pp .Nm uses the SFTP protocol over a .Xr ssh 1 connection for data transfer, and uses the same authentication and provides the same security as a login session. .Pp .Nm will ask for passwords or passphrases if they are needed for authentication. .Pp 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. .Pp When copying between two remote hosts, if the URI format is used, a .Ar port cannot be specified on the .Ar target if the .Fl R option is used. .Pp The options are as follows: .Bl -tag -width Ds .It Fl 3 Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between the two remote hosts. Note that, when using the legacy SCP protocol (via the .Fl O flag), this option selects batch mode for the second host as .Nm cannot ask for passwords or passphrases for both hosts. This mode is the default. .It Fl 4 Forces .Nm to use IPv4 addresses only. .It Fl 6 Forces .Nm to use IPv6 addresses only. .It Fl A Allows forwarding of .Xr ssh-agent 1 to the remote system. The default is not to forward an authentication agent. .It Fl B Selects batch mode (prevents asking for passwords or passphrases). .It Fl C Compression enable. Passes the .Fl C flag to .Xr ssh 1 to enable compression. .It Fl c Ar cipher Selects the cipher to use for encrypting the data transfer. This option is directly passed to .Xr ssh 1 . .It Fl D Ar sftp_server_path Connect directly to a local SFTP server program rather than a remote one via .Xr ssh 1 . This option may be useful in debugging the client and server. .It Fl F Ar ssh_config Specifies an alternative per-user configuration file for .Nm ssh . This option is directly passed to .Xr ssh 1 . .It Fl i Ar identity_file 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 Use the legacy SCP protocol for file transfers instead of the SFTP protocol. Forcing the use of the SCP protocol may be necessary for servers that do not implement SFTP, for backwards-compatibility for particular filename wildcard patterns and for expanding paths with a .Sq ~ prefix for older SFTP servers. .It Fl o Ar ssh_option Can be used to pass options to .Nm ssh in the format used in .Xr ssh_config 5 . This is useful for specifying options for which there is no separate .Nm scp command-line flag. For full details of the options listed below, and their possible values, see .Xr ssh_config 5 . .Pp .Bl -tag -width Ds -offset indent -compact .It AddKeysToAgent .It AddressFamily .It BatchMode .It BindAddress .It BindInterface .It CASignatureAlgorithms .It CanonicalDomains .It CanonicalizeFallbackLocal .It CanonicalizeHostname .It CanonicalizeMaxDots .It CanonicalizePermittedCNAMEs .It CertificateFile .It ChannelTimeout .It CheckHostIP .It Ciphers .It ClearAllForwardings .It Compression .It ConnectTimeout .It ConnectionAttempts .It ControlMaster .It ControlPath .It ControlPersist .It DynamicForward .It EnableEscapeCommandline .It EnableSSHKeysign .It EscapeChar .It ExitOnForwardFailure .It FingerprintHash .It ForkAfterAuthentication .It ForwardAgent .It ForwardX11 .It ForwardX11Timeout .It ForwardX11Trusted .It GSSAPIAuthentication .It GSSAPIDelegateCredentials .It GatewayPorts .It GlobalKnownHostsFile .It HashKnownHosts .It Host .It HostKeyAlgorithms .It HostKeyAlias .It HostbasedAcceptedAlgorithms .It HostbasedAuthentication .It Hostname .It IPQoS .It IdentitiesOnly .It IdentityAgent .It IdentityFile .It IgnoreUnknown .It Include .It KbdInteractiveAuthentication .It KbdInteractiveDevices .It KexAlgorithms .It KnownHostsCommand .It LocalCommand .It LocalForward .It LogLevel .It LogVerbose .It MACs .It NoHostAuthenticationForLocalhost .It NumberOfPasswordPrompts .It ObscureKeystrokeTiming .It PKCS11Provider .It PasswordAuthentication .It PermitLocalCommand .It PermitRemoteOpen .It Port .It PreferredAuthentications .It ProxyCommand .It ProxyJump .It ProxyUseFdpass .It PubkeyAcceptedAlgorithms .It PubkeyAuthentication .It RekeyLimit .It RemoteCommand .It RemoteForward .It RequestTTY .It RequiredRSASize .It RevokedHostKeys .It SecurityKeyProvider .It SendEnv .It ServerAliveCountMax .It ServerAliveInterval .It SessionType .It SetEnv .It StdinNull .It StreamLocalBindMask .It StreamLocalBindUnlink .It StrictHostKeyChecking .It SyslogFacility .It TCPKeepAlive .It Tag .It Tunnel .It TunnelDevice .It UpdateHostKeys .It User .It UserKnownHostsFile .It VerifyHostKeyDNS .It VisualHostKey .It XAuthLocation .El .It Fl P Ar port Specifies the port to connect to on the remote host. Note that this option is written with a capital .Sq P , because .Fl p is already reserved for preserving the times and mode bits of the file. .It Fl p Preserves modification times, access times, and file mode bits from the source file. .It Fl q Quiet mode: disables the progress meter as well as warning and diagnostic messages from .Xr ssh 1 . .It Fl R Copies between two remote hosts are performed by connecting to the origin host and executing .Nm there. This requires that .Nm running on the origin host can authenticate to the destination host without requiring a password. .It Fl r Recursively copy entire directories. Note that .Nm follows symbolic links encountered in the tree traversal. .It Fl S Ar program Name of .Ar program 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 .Nm and .Xr ssh 1 to print debugging messages about their progress. This is helpful in debugging connection, authentication, and configuration problems. .It Fl X Ar sftp_option Specify an option that controls aspects of SFTP protocol behaviour. The valid options are: .Bl -tag -width Ds .It Cm nrequests Ns = Ns Ar value Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download or upload. By default 64 requests may be active concurrently. .It Cm buffer Ns = Ns Ar value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By default a 32KB buffer is used. .El .El .Sh EXIT STATUS .Ex -std scp .Sh SEE ALSO .Xr sftp 1 , .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 , .Xr ssh_config 5 , .Xr sftp-server 8 , .Xr sshd 8 .Sh HISTORY .Nm is based on the rcp program in .Bx source code from the Regents of the University of California. .Pp Since OpenSSH 9.0, .Nm has used the SFTP protocol for transfers by default. .Sh AUTHORS .An Timo Rinne Aq Mt tri@iki.fi .An Tatu Ylonen Aq Mt ylo@cs.hut.fi .Sh CAVEATS The legacy SCP protocol (selected by the .Fl O flag) requires execution of the remote user's shell to perform .Xr glob 3 pattern matching. This requires careful quoting of any characters that have special meaning to the remote shell, such as quote characters. openssh-10.0p1/PaxHeaders.10889/scp.c100644 001750 001750 0000000003614775415623 0014105xustar0030 atime=1744182234.744945097 openssh-10.0p1/scp.c010064400017500001750000001531161477541562300124770ustar00djmdjm/* $OpenBSD: scp.c,v 1.263 2025/03/28 06:04:07 dtucker Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). * * NOTE: This version should NOT be suid root. (This uses ssh to * do the transfer and ssh has the necessary privileges.) * * 1995 Timo Rinne , Tatu Ylonen * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 1999 Theo de Raadt. All rights reserved. * Copyright (c) 1999 Aaron Campbell. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Parts from: * * Copyright (c) 1983, 1990, 1992, 1993, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "includes.h" #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #ifdef HAVE_FNMATCH_H #include #endif #ifdef USE_SYSTEM_GLOB # include #else # include "openbsd-compat/glob.h" #endif #ifdef HAVE_LIBGEN_H #include #endif #include #ifdef HAVE_UTIL_H # include #endif #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) #include #endif #include "xmalloc.h" #include "ssh.h" #include "atomicio.h" #include "pathnames.h" #include "log.h" #include "misc.h" #include "progressmeter.h" #include "utf8.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" extern char *__progname; #define COPY_BUFLEN 16384 int do_cmd(char *, char *, char *, int, int, char *, int *, int *, pid_t *); int do_cmd2(char *, char *, int, char *, int, int); /* Struct for addargs */ arglist args; arglist remote_remote_args; /* Bandwidth limit */ long long limit_kbps = 0; struct bwlimit bwlimit; /* Name of current file being transferred. */ char *curfile; /* This is set to non-zero to enable verbose mode. */ int verbose_mode = 0; LogLevel log_level = SYSLOG_LEVEL_INFO; /* This is set to zero if the progressmeter is not desired. */ int showprogress = 1; /* * This is set to non-zero if remote-remote copy should be piped * through this process. */ int throughlocal = 1; /* Non-standard port to use for the ssh connection or -1. */ int sshport = -1; /* This is the program to execute for the secured connection. ("ssh" or -S) */ char *ssh_program = _PATH_SSH_PROGRAM; /* This is used to store the pid of ssh_program */ pid_t do_cmd_pid = -1; pid_t do_cmd_pid2 = -1; /* SFTP copy parameters */ size_t sftp_copy_buflen; size_t sftp_nrequests; /* Needed for sftp */ volatile sig_atomic_t interrupted = 0; int sftp_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ static void killchild(int signo) { if (do_cmd_pid > 1) { kill(do_cmd_pid, signo ? signo : SIGTERM); (void)waitpid(do_cmd_pid, NULL, 0); } if (do_cmd_pid2 > 1) { kill(do_cmd_pid2, signo ? signo : SIGTERM); (void)waitpid(do_cmd_pid2, NULL, 0); } if (signo) _exit(1); exit(1); } static void suspone(int pid, int signo) { int status; if (pid > 1) { kill(pid, signo); while (waitpid(pid, &status, WUNTRACED) == -1 && errno == EINTR) ; } } static void suspchild(int signo) { int save_errno = errno; suspone(do_cmd_pid, signo); suspone(do_cmd_pid2, signo); kill(getpid(), SIGSTOP); errno = save_errno; } static int do_local_cmd(arglist *a) { u_int i; int status; pid_t pid; if (a->num == 0) fatal("do_local_cmd: no arguments"); if (verbose_mode) { fprintf(stderr, "Executing:"); for (i = 0; i < a->num; i++) fmprintf(stderr, " %s", a->list[i]); fprintf(stderr, "\n"); } if ((pid = fork()) == -1) fatal("do_local_cmd: fork: %s", strerror(errno)); if (pid == 0) { execvp(a->list[0], a->list); perror(a->list[0]); exit(1); } do_cmd_pid = pid; ssh_signal(SIGTERM, killchild); ssh_signal(SIGINT, killchild); ssh_signal(SIGHUP, killchild); while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("do_local_cmd: waitpid: %s", strerror(errno)); do_cmd_pid = -1; if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return (-1); return (0); } /* * This function executes the given command as the specified user on the * given host. This returns < 0 if execution fails, and >= 0 otherwise. This * assigns the input and output file descriptors on success. */ int do_cmd(char *program, char *host, char *remuser, int port, int subsystem, char *cmd, int *fdin, int *fdout, pid_t *pid) { #ifdef USE_PIPES int pin[2], pout[2]; #else int sv[2]; #endif if (verbose_mode) fmprintf(stderr, "Executing: program %s host %s, user %s, command %s\n", program, host, remuser ? remuser : "(unspecified)", cmd); if (port == -1) port = sshport; #ifdef USE_PIPES if (pipe(pin) == -1 || pipe(pout) == -1) fatal("pipe: %s", strerror(errno)); #else /* Create a socket pair for communicating with ssh. */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) fatal("socketpair: %s", strerror(errno)); #endif ssh_signal(SIGTSTP, suspchild); ssh_signal(SIGTTIN, suspchild); ssh_signal(SIGTTOU, suspchild); /* Fork a child to execute the command on the remote host using ssh. */ *pid = fork(); switch (*pid) { case -1: fatal("fork: %s", strerror(errno)); case 0: /* Child. */ #ifdef USE_PIPES if (dup2(pin[0], STDIN_FILENO) == -1 || dup2(pout[1], STDOUT_FILENO) == -1) { error("dup2: %s", strerror(errno)); _exit(1); } close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); #else if (dup2(sv[0], STDIN_FILENO) == -1 || dup2(sv[0], STDOUT_FILENO) == -1) { error("dup2: %s", strerror(errno)); _exit(1); } close(sv[0]); close(sv[1]); #endif replacearg(&args, 0, "%s", program); if (port != -1) { addargs(&args, "-p"); addargs(&args, "%d", port); } if (remuser != NULL) { addargs(&args, "-l"); addargs(&args, "%s", remuser); } if (subsystem) addargs(&args, "-s"); addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", cmd); execvp(program, args.list); perror(program); _exit(1); default: /* Parent. Close the other side, and return the local side. */ #ifdef USE_PIPES close(pin[0]); close(pout[1]); *fdout = pin[1]; *fdin = pout[0]; #else close(sv[0]); *fdin = sv[1]; *fdout = sv[1]; #endif ssh_signal(SIGTERM, killchild); ssh_signal(SIGINT, killchild); ssh_signal(SIGHUP, killchild); return 0; } } /* * This function executes a command similar to do_cmd(), but expects the * input and output descriptors to be setup by a previous call to do_cmd(). * This way the input and output of two commands can be connected. */ int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout) { int status; pid_t pid; if (verbose_mode) fmprintf(stderr, "Executing: 2nd program %s host %s, user %s, command %s\n", ssh_program, host, remuser ? remuser : "(unspecified)", cmd); if (port == -1) port = sshport; /* Fork a child to execute the command on the remote host using ssh. */ pid = fork(); if (pid == 0) { if (dup2(fdin, 0) == -1) perror("dup2"); if (dup2(fdout, 1) == -1) perror("dup2"); replacearg(&args, 0, "%s", ssh_program); if (port != -1) { addargs(&args, "-p"); addargs(&args, "%d", port); } if (remuser != NULL) { addargs(&args, "-l"); addargs(&args, "%s", remuser); } addargs(&args, "-oBatchMode=yes"); addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", cmd); execvp(ssh_program, args.list); perror(ssh_program); exit(1); } else if (pid == -1) { fatal("fork: %s", strerror(errno)); } while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("do_cmd2: waitpid: %s", strerror(errno)); return 0; } typedef struct { size_t cnt; char *buf; } BUF; BUF *allocbuf(BUF *, int, int); void lostconn(int); int okname(char *); void run_err(const char *,...) __attribute__((__format__ (printf, 1, 2))) __attribute__((__nonnull__ (1))); int note_err(const char *,...) __attribute__((__format__ (printf, 1, 2))); void verifydir(char *); struct passwd *pwd; uid_t userid; int errs, remin, remout, remin2, remout2; int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory; #define CMDNEEDS 64 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ enum scp_mode_e { MODE_SCP, MODE_SFTP }; int response(void); void rsource(char *, struct stat *); void sink(int, char *[], const char *); void source(int, char *[]); void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct); void toremote(int, char *[], enum scp_mode_e, char *sftp_direct); void usage(void); void source_sftp(int, char *, char *, struct sftp_conn *); void sink_sftp(int, char *, const char *, struct sftp_conn *); void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *, char *, char *); int main(int argc, char **argv) { int ch, fflag, tflag, status, r, n; char **newargv, *argv0; const char *errstr; extern char *optarg; extern int optind; enum scp_mode_e mode = MODE_SFTP; char *sftp_direct = NULL; long long llv; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); msetlocale(); /* Copy argv, because we modify it */ argv0 = argv[0]; newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); for (n = 0; n < argc; n++) newargv[n] = xstrdup(argv[n]); argv = newargv; __progname = ssh_get_progname(argv[0]); log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); memset(&args, '\0', sizeof(args)); memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); args.list = remote_remote_args.list = NULL; addargs(&args, "%s", ssh_program); addargs(&args, "-x"); addargs(&args, "-oPermitLocalCommand=no"); addargs(&args, "-oClearAllForwardings=yes"); addargs(&args, "-oRemoteCommand=none"); addargs(&args, "-oRequestTTY=no"); addargs(&args, "-oControlMaster=no"); fflag = Tflag = tflag = 0; while ((ch = getopt(argc, argv, "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:X:")) != -1) { switch (ch) { /* User-visible flags. */ case '1': fatal("SSH protocol v.1 is no longer supported"); break; case '2': /* Ignored */ break; case 'A': case '4': case '6': case 'C': addargs(&args, "-%c", ch); addargs(&remote_remote_args, "-%c", ch); break; case 'D': sftp_direct = optarg; break; case '3': throughlocal = 1; break; case 'R': throughlocal = 0; break; case 'o': case 'c': case 'i': case 'F': case 'J': addargs(&remote_remote_args, "-%c", ch); addargs(&remote_remote_args, "%s", optarg); addargs(&args, "-%c", ch); addargs(&args, "%s", optarg); break; case 'O': mode = MODE_SCP; break; case 's': mode = MODE_SFTP; break; case 'P': sshport = a2port(optarg); if (sshport <= 0) fatal("bad port \"%s\"\n", optarg); break; case 'B': addargs(&remote_remote_args, "-oBatchmode=yes"); addargs(&args, "-oBatchmode=yes"); break; case 'l': limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, &errstr); if (errstr != NULL) usage(); limit_kbps *= 1024; /* kbps */ bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); break; case 'p': pflag = 1; break; case 'r': iamrecursive = 1; break; case 'S': ssh_program = xstrdup(optarg); break; case 'v': addargs(&args, "-v"); addargs(&remote_remote_args, "-v"); if (verbose_mode == 0) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; verbose_mode = 1; break; case 'q': addargs(&args, "-q"); addargs(&remote_remote_args, "-q"); showprogress = 0; break; case 'X': /* Please keep in sync with sftp.c -X */ if (strncmp(optarg, "buffer=", 7) == 0) { r = scan_scaled(optarg + 7, &llv); if (r == 0 && (llv <= 0 || llv > 256 * 1024)) { r = -1; errno = EINVAL; } if (r == -1) { fatal("Invalid buffer size \"%s\": %s", optarg + 7, strerror(errno)); } sftp_copy_buflen = (size_t)llv; } else if (strncmp(optarg, "nrequests=", 10) == 0) { llv = strtonum(optarg + 10, 1, 256 * 1024, &errstr); if (errstr != NULL) { fatal("Invalid number of requests " "\"%s\": %s", optarg + 10, errstr); } sftp_nrequests = (size_t)llv; } else { fatal("Invalid -X option"); } break; /* Server options. */ case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ iamremote = 1; fflag = 1; break; case 't': /* "to" */ iamremote = 1; tflag = 1; #ifdef HAVE_CYGWIN setmode(0, O_BINARY); #endif break; case 'T': Tflag = 1; break; default: usage(); } } argc -= optind; argv += optind; log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); /* Do this last because we want the user to be able to override it */ addargs(&args, "-oForwardAgent=no"); if (iamremote) mode = MODE_SCP; if ((pwd = getpwuid(userid = getuid())) == NULL) fatal("unknown user %u", (u_int) userid); if (!isatty(STDOUT_FILENO)) showprogress = 0; if (pflag) { /* Cannot pledge: -p allows setuid/setgid files... */ } else { if (pledge("stdio rpath wpath cpath fattr tty proc exec", NULL) == -1) { perror("pledge"); exit(1); } } remin = STDIN_FILENO; remout = STDOUT_FILENO; if (fflag) { /* Follow "protocol", send data. */ (void) response(); source(argc, argv); exit(errs != 0); } if (tflag) { /* Receive data. */ sink(argc, argv, NULL); exit(errs != 0); } if (argc < 2) usage(); if (argc > 2) targetshouldbedirectory = 1; remin = remout = -1; do_cmd_pid = -1; /* Command to be executed on remote system using "ssh". */ (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); (void) ssh_signal(SIGPIPE, lostconn); if (colon(argv[argc - 1])) /* Dest is remote host. */ toremote(argc, argv, mode, sftp_direct); else { if (targetshouldbedirectory) verifydir(argv[argc - 1]); tolocal(argc, argv, mode, sftp_direct); /* Dest is local host. */ } /* * Finally check the exit status of the ssh process, if one was forked * and no error has occurred yet */ if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) { if (remin != -1) (void) close(remin); if (remout != -1) (void) close(remout); if (waitpid(do_cmd_pid, &status, 0) == -1) errs = 1; else { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errs = 1; } } exit(errs != 0); } /* Callback from atomicio6 to update progress meter and limit bandwidth */ static int scpio(void *_cnt, size_t s) { off_t *cnt = (off_t *)_cnt; *cnt += s; refresh_progress_meter(0); if (limit_kbps > 0) bandwidth_limit(&bwlimit, s); return 0; } static int do_times(int fd, int verb, const struct stat *sb) { /* strlen(2^64) == 20; strlen(10^6) == 7 */ char buf[(20 + 7 + 2) * 2 + 2]; (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n", (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime), (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime)); if (verb) { fprintf(stderr, "File mtime %lld atime %lld\n", (long long)sb->st_mtime, (long long)sb->st_atime); fprintf(stderr, "Sending file timestamps: %s", buf); } (void) atomicio(vwrite, fd, buf, strlen(buf)); return (response()); } static int parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp, char **pathp) { int r; r = parse_uri("scp", uri, userp, hostp, portp, pathp); if (r == 0 && *pathp == NULL) *pathp = xstrdup("."); return r; } /* Appends a string to an array; returns 0 on success, -1 on alloc failure */ static int append(char *cp, char ***ap, size_t *np) { char **tmp; if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL) return -1; tmp[(*np)] = cp; (*np)++; *ap = tmp; return 0; } /* * Finds the start and end of the first brace pair in the pattern. * returns 0 on success or -1 for invalid patterns. */ static int find_brace(const char *pattern, int *startp, int *endp) { int i; int in_bracket, brace_level; *startp = *endp = -1; in_bracket = brace_level = 0; for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) { switch (pattern[i]) { case '\\': /* skip next character */ if (pattern[i + 1] != '\0') i++; break; case '[': in_bracket = 1; break; case ']': in_bracket = 0; break; case '{': if (in_bracket) break; if (pattern[i + 1] == '}') { /* Protect a single {}, for find(1), like csh */ i++; /* skip */ break; } if (*startp == -1) *startp = i; brace_level++; break; case '}': if (in_bracket) break; if (*startp < 0) { /* Unbalanced brace */ return -1; } if (--brace_level <= 0) *endp = i; break; } } /* unbalanced brackets/braces */ if (*endp < 0 && (*startp >= 0 || in_bracket)) return -1; return 0; } /* * Assembles and records a successfully-expanded pattern, returns -1 on * alloc failure. */ static int emit_expansion(const char *pattern, int brace_start, int brace_end, int sel_start, int sel_end, char ***patternsp, size_t *npatternsp) { char *cp; size_t pattern_len; int o = 0, tail_len; if ((pattern_len = strlen(pattern)) == 0 || pattern_len >= INT_MAX) return -1; tail_len = strlen(pattern + brace_end + 1); if ((cp = malloc(brace_start + (sel_end - sel_start) + tail_len + 1)) == NULL) return -1; /* Pattern before initial brace */ if (brace_start > 0) { memcpy(cp, pattern, brace_start); o = brace_start; } /* Current braced selection */ if (sel_end - sel_start > 0) { memcpy(cp + o, pattern + sel_start, sel_end - sel_start); o += sel_end - sel_start; } /* Remainder of pattern after closing brace */ if (tail_len > 0) { memcpy(cp + o, pattern + brace_end + 1, tail_len); o += tail_len; } cp[o] = '\0'; if (append(cp, patternsp, npatternsp) != 0) { free(cp); return -1; } return 0; } /* * Expand the first encountered brace in pattern, appending the expanded * patterns it yielded to the *patternsp array. * * Returns 0 on success or -1 on allocation failure. * * Signals whether expansion was performed via *expanded and whether * pattern was invalid via *invalid. */ static int brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp, int *expanded, int *invalid) { int i; int in_bracket, brace_start, brace_end, brace_level; int sel_start, sel_end; *invalid = *expanded = 0; if (find_brace(pattern, &brace_start, &brace_end) != 0) { *invalid = 1; return 0; } else if (brace_start == -1) return 0; in_bracket = brace_level = 0; for (i = sel_start = brace_start + 1; i < brace_end; i++) { switch (pattern[i]) { case '{': if (in_bracket) break; brace_level++; break; case '}': if (in_bracket) break; brace_level--; break; case '[': in_bracket = 1; break; case ']': in_bracket = 0; break; case '\\': if (i < brace_end - 1) i++; /* skip */ break; } if (pattern[i] == ',' || i == brace_end - 1) { if (in_bracket || brace_level > 0) continue; /* End of a selection, emit an expanded pattern */ /* Adjust end index for last selection */ sel_end = (i == brace_end - 1) ? brace_end : i; if (emit_expansion(pattern, brace_start, brace_end, sel_start, sel_end, patternsp, npatternsp) != 0) return -1; /* move on to the next selection */ sel_start = i + 1; continue; } } if (in_bracket || brace_level > 0) { *invalid = 1; return 0; } /* success */ *expanded = 1; return 0; } /* Expand braces from pattern. Returns 0 on success, -1 on failure */ static int brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp) { char *cp, *cp2, **active = NULL, **done = NULL; size_t i, nactive = 0, ndone = 0; int ret = -1, invalid = 0, expanded = 0; *patternsp = NULL; *npatternsp = 0; /* Start the worklist with the original pattern */ if ((cp = strdup(pattern)) == NULL) return -1; if (append(cp, &active, &nactive) != 0) { free(cp); return -1; } while (nactive > 0) { cp = active[nactive - 1]; nactive--; if (brace_expand_one(cp, &active, &nactive, &expanded, &invalid) == -1) { free(cp); goto fail; } if (invalid) fatal_f("invalid brace pattern \"%s\"", cp); if (expanded) { /* * Current entry expanded to new entries on the * active list; discard the progenitor pattern. */ free(cp); continue; } /* * Pattern did not expand; append the finename component to * the completed list */ if ((cp2 = strrchr(cp, '/')) != NULL) *cp2++ = '\0'; else cp2 = cp; if (append(xstrdup(cp2), &done, &ndone) != 0) { free(cp); goto fail; } free(cp); } /* success */ *patternsp = done; *npatternsp = ndone; done = NULL; ndone = 0; ret = 0; fail: for (i = 0; i < nactive; i++) free(active[i]); free(active); for (i = 0; i < ndone; i++) free(done[i]); free(done); return ret; } static struct sftp_conn * do_sftp_connect(char *host, char *user, int port, char *sftp_direct, int *reminp, int *remoutp, int *pidp) { if (sftp_direct == NULL) { if (do_cmd(ssh_program, host, user, port, 1, "sftp", reminp, remoutp, pidp) < 0) return NULL; } else { freeargs(&args); addargs(&args, "sftp-server"); if (do_cmd(sftp_direct, host, NULL, -1, 0, "sftp", reminp, remoutp, pidp) < 0) return NULL; } return sftp_init(*reminp, *remoutp, sftp_copy_buflen, sftp_nrequests, limit_kbps); } void toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) { char *suser = NULL, *host = NULL, *src = NULL; char *bp, *tuser, *thost, *targ; int sport = -1, tport = -1; struct sftp_conn *conn = NULL, *conn2 = NULL; arglist alist; int i, r, status; struct stat sb; u_int j; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; /* Parse target */ r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]); ++errs; goto out; } if (r != 0) { if (parse_user_host_path(argv[argc - 1], &tuser, &thost, &targ) == -1) { fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]); ++errs; goto out; } } /* Parse source files */ for (i = 0; i < argc - 1; i++) { free(suser); free(host); free(src); r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[i]); ++errs; continue; } if (r != 0) { parse_user_host_path(argv[i], &suser, &host, &src); } if (suser != NULL && !okname(suser)) { ++errs; continue; } if (host && throughlocal) { /* extended remote to remote */ if (mode == MODE_SFTP) { if (remin == -1 || conn == NULL) { /* Connect to dest now */ conn = do_sftp_connect(thost, tuser, tport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { fatal("Unable to open " "destination connection"); } debug3_f("origin in %d out %d pid %ld", remin, remout, (long)do_cmd_pid); } /* * XXX remember suser/host/sport and only * reconnect if they change between arguments. * would save reconnections for cases like * scp -3 hosta:/foo hosta:/bar hostb: */ /* Connect to origin now */ conn2 = do_sftp_connect(host, suser, sport, sftp_direct, &remin2, &remout2, &do_cmd_pid2); if (conn2 == NULL) { fatal("Unable to open " "source connection"); } debug3_f("destination in %d out %d pid %ld", remin2, remout2, (long)do_cmd_pid2); throughlocal_sftp(conn2, conn, src, targ); (void) close(remin2); (void) close(remout2); remin2 = remout2 = -1; if (waitpid(do_cmd_pid2, &status, 0) == -1) ++errs; else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++errs; do_cmd_pid2 = -1; continue; } else { xasprintf(&bp, "%s -f %s%s", cmd, *src == '-' ? "-- " : "", src); if (do_cmd(ssh_program, host, suser, sport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) exit(1); free(bp); xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0) exit(1); free(bp); (void) close(remin); (void) close(remout); remin = remout = -1; } } else if (host) { /* standard remote to remote */ /* * Second remote user is passed to first remote side * via scp command-line. Ensure it contains no obvious * shell characters. */ if (tuser != NULL && !okname(tuser)) { ++errs; continue; } if (tport != -1 && tport != SSH_DEFAULT_PORT) { /* This would require the remote support URIs */ fatal("target port not supported with two " "remote hosts and the -R option"); } freeargs(&alist); addargs(&alist, "%s", ssh_program); addargs(&alist, "-x"); addargs(&alist, "-oClearAllForwardings=yes"); addargs(&alist, "-n"); for (j = 0; j < remote_remote_args.num; j++) { addargs(&alist, "%s", remote_remote_args.list[j]); } if (sport != -1) { addargs(&alist, "-p"); addargs(&alist, "%d", sport); } if (suser) { addargs(&alist, "-l"); addargs(&alist, "%s", suser); } addargs(&alist, "--"); addargs(&alist, "%s", host); addargs(&alist, "%s", cmd); addargs(&alist, "%s", src); addargs(&alist, "%s%s%s:%s", tuser ? tuser : "", tuser ? "@" : "", thost, targ); if (do_local_cmd(&alist) != 0) errs = 1; } else { /* local to remote */ if (mode == MODE_SFTP) { /* no need to glob: already done by shell */ if (stat(argv[i], &sb) != 0) { fatal("stat local \"%s\": %s", argv[i], strerror(errno)); } if (remin == -1) { /* Connect to remote now */ conn = do_sftp_connect(thost, tuser, tport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { fatal("Unable to open sftp " "connection"); } } /* The protocol */ source_sftp(1, argv[i], targ, conn); continue; } /* SCP */ if (remin == -1) { xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd(ssh_program, thost, tuser, tport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) exit(1); if (response() < 0) exit(1); free(bp); } source(1, argv + i); } } out: if (mode == MODE_SFTP) free(conn); free(tuser); free(thost); free(targ); free(suser); free(host); free(src); } void tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) { char *bp, *host = NULL, *src = NULL, *suser = NULL; arglist alist; struct sftp_conn *conn = NULL; int i, r, sport = -1; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; for (i = 0; i < argc - 1; i++) { free(suser); free(host); free(src); r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[i]); ++errs; continue; } if (r != 0) parse_user_host_path(argv[i], &suser, &host, &src); if (suser != NULL && !okname(suser)) { ++errs; continue; } if (!host) { /* Local to local. */ freeargs(&alist); addargs(&alist, "%s", _PATH_CP); if (iamrecursive) addargs(&alist, "-r"); if (pflag) addargs(&alist, "-p"); addargs(&alist, "--"); addargs(&alist, "%s", argv[i]); addargs(&alist, "%s", argv[argc-1]); if (do_local_cmd(&alist)) ++errs; continue; } /* Remote to local. */ if (mode == MODE_SFTP) { conn = do_sftp_connect(host, suser, sport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { error("sftp connection failed"); ++errs; continue; } /* The protocol */ sink_sftp(1, argv[argc - 1], src, conn); free(conn); (void) close(remin); (void) close(remout); remin = remout = -1; continue; } /* SCP */ xasprintf(&bp, "%s -f %s%s", cmd, *src == '-' ? "-- " : "", src); if (do_cmd(ssh_program, host, suser, sport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) { free(bp); ++errs; continue; } free(bp); sink(1, argv + argc - 1, src); (void) close(remin); remin = remout = -1; } free(suser); free(host); free(src); } /* Prepare remote path, handling ~ by assuming cwd is the homedir */ static char * prepare_remote_path(struct sftp_conn *conn, const char *path) { size_t nslash; /* Handle ~ prefixed paths */ if (*path == '\0' || strcmp(path, "~") == 0) return xstrdup("."); if (*path != '~') return xstrdup(path); if (strncmp(path, "~/", 2) == 0) { if ((nslash = strspn(path + 2, "/")) == strlen(path + 2)) return xstrdup("."); return xstrdup(path + 2 + nslash); } if (sftp_can_expand_path(conn)) return sftp_expand_path(conn, path); /* No protocol extension */ error("server expand-path extension is required " "for ~user paths in SFTP mode"); return NULL; } void source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) { char *target = NULL, *filename = NULL, *abs_dst = NULL; int src_is_dir, target_is_dir; Attrib a; struct stat st; memset(&a, '\0', sizeof(a)); if (stat(src, &st) != 0) fatal("stat local \"%s\": %s", src, strerror(errno)); src_is_dir = S_ISDIR(st.st_mode); if ((filename = basename(src)) == NULL) fatal("basename \"%s\": %s", src, strerror(errno)); /* * No need to glob here - the local shell already took care of * the expansions */ if ((target = prepare_remote_path(conn, targ)) == NULL) cleanup_exit(255); target_is_dir = sftp_remote_is_dir(conn, target); if (targetshouldbedirectory && !target_is_dir) { debug("target directory \"%s\" does not exist", target); a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = st.st_mode | 0700; /* ensure writable */ if (sftp_mkdir(conn, target, &a, 1) != 0) cleanup_exit(255); /* error already logged */ target_is_dir = 1; } if (target_is_dir) abs_dst = sftp_path_append(target, filename); else { abs_dst = target; target = NULL; } debug3_f("copying local %s to remote %s", src, abs_dst); if (src_is_dir && iamrecursive) { if (sftp_upload_dir(conn, src, abs_dst, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { error("failed to upload directory %s to %s", src, targ); errs = 1; } } else if (sftp_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { error("failed to upload file %s to %s", src, targ); errs = 1; } free(abs_dst); free(target); } void source(int argc, char **argv) { struct stat stb; static BUF buffer; BUF *bp; off_t i, statbytes; size_t amt, nr; int fd = -1, haderr, indx; char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX]; int len; for (indx = 0; indx < argc; ++indx) { name = argv[indx]; statbytes = 0; len = strlen(name); while (len > 1 && name[len-1] == '/') name[--len] = '\0'; if ((fd = open(name, O_RDONLY|O_NONBLOCK)) == -1) goto syserr; if (strchr(name, '\n') != NULL) { strnvis(encname, name, sizeof(encname), VIS_NL); name = encname; } if (fstat(fd, &stb) == -1) { syserr: run_err("%s: %s", name, strerror(errno)); goto next; } if (stb.st_size < 0) { run_err("%s: %s", name, "Negative file size"); goto next; } unset_nonblock(fd); switch (stb.st_mode & S_IFMT) { case S_IFREG: break; case S_IFDIR: if (iamrecursive) { rsource(name, &stb); goto next; } /* FALLTHROUGH */ default: run_err("%s: not a regular file", name); goto next; } if ((last = strrchr(name, '/')) == NULL) last = name; else ++last; curfile = last; if (pflag) { if (do_times(remout, verbose_mode, &stb) < 0) goto next; } #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) snprintf(buf, sizeof buf, "C%04o %lld %s\n", (u_int) (stb.st_mode & FILEMODEMASK), (long long)stb.st_size, last); if (verbose_mode) fmprintf(stderr, "Sending file modes: %s", buf); (void) atomicio(vwrite, remout, buf, strlen(buf)); if (response() < 0) goto next; if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) { next: if (fd != -1) { (void) close(fd); fd = -1; } continue; } if (showprogress) start_progress_meter(curfile, stb.st_size, &statbytes); set_nonblock(remout); for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { amt = bp->cnt; if (i + (off_t)amt > stb.st_size) amt = stb.st_size - i; if (!haderr) { if ((nr = atomicio(read, fd, bp->buf, amt)) != amt) { haderr = errno; memset(bp->buf + nr, 0, amt - nr); } } /* Keep writing after error to retain sync */ if (haderr) { (void)atomicio(vwrite, remout, bp->buf, amt); memset(bp->buf, 0, amt); continue; } if (atomicio6(vwrite, remout, bp->buf, amt, scpio, &statbytes) != amt) haderr = errno; } unset_nonblock(remout); if (fd != -1) { if (close(fd) == -1 && !haderr) haderr = errno; fd = -1; } if (!haderr) (void) atomicio(vwrite, remout, "", 1); else run_err("%s: %s", name, strerror(haderr)); (void) response(); if (showprogress) stop_progress_meter(); } } void rsource(char *name, struct stat *statp) { DIR *dirp; struct dirent *dp; char *last, *vect[1], path[PATH_MAX]; if (!(dirp = opendir(name))) { run_err("%s: %s", name, strerror(errno)); return; } last = strrchr(name, '/'); if (last == NULL) last = name; else last++; if (pflag) { if (do_times(remout, verbose_mode, statp) < 0) { closedir(dirp); return; } } (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", (u_int) (statp->st_mode & FILEMODEMASK), 0, last); if (verbose_mode) fmprintf(stderr, "Entering directory: %s", path); (void) atomicio(vwrite, remout, path, strlen(path)); if (response() < 0) { closedir(dirp); return; } while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) { run_err("%s/%s: name too long", name, dp->d_name); continue; } (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name); vect[0] = path; source(1, vect); } (void) closedir(dirp); (void) atomicio(vwrite, remout, "E\n", 2); (void) response(); } void sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) { char *abs_src = NULL; char *abs_dst = NULL; glob_t g; char *filename, *tmp = NULL; int i, r, err = 0, dst_is_dir; struct stat st; memset(&g, 0, sizeof(g)); /* * Here, we need remote glob as SFTP can not depend on remote shell * expansions */ if ((abs_src = prepare_remote_path(conn, src)) == NULL) { err = -1; goto out; } debug3_f("copying remote %s to local %s", abs_src, dst); if ((r = sftp_glob(conn, abs_src, GLOB_NOCHECK|GLOB_MARK, NULL, &g)) != 0) { if (r == GLOB_NOSPACE) error("%s: too many glob matches", src); else error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } /* Did we actually get any matches back from the glob? */ if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) { /* * If nothing matched but a path returned, then it's probably * a GLOB_NOCHECK result. Check whether the unglobbed path * exists so we can give a nice error message early. */ if (sftp_stat(conn, g.gl_pathv[0], 1, NULL) != 0) { error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } } if ((r = stat(dst, &st)) != 0) debug2_f("stat local \"%s\": %s", dst, strerror(errno)); dst_is_dir = r == 0 && S_ISDIR(st.st_mode); if (g.gl_matchc > 1 && !dst_is_dir) { if (r == 0) { error("Multiple files match pattern, but destination " "\"%s\" is not a directory", dst); err = -1; goto out; } debug2_f("creating destination \"%s\"", dst); if (mkdir(dst, 0777) != 0) { error("local mkdir \"%s\": %s", dst, strerror(errno)); err = -1; goto out; } dst_is_dir = 1; } for (i = 0; g.gl_pathv[i] && !interrupted; i++) { tmp = xstrdup(g.gl_pathv[i]); if ((filename = basename(tmp)) == NULL) { error("basename %s: %s", tmp, strerror(errno)); err = -1; goto out; } if (dst_is_dir) abs_dst = sftp_path_append(dst, filename); else abs_dst = xstrdup(dst); debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst, NULL, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) err = -1; } else { if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL, pflag, 0, 0, 1) == -1) err = -1; } free(abs_dst); abs_dst = NULL; free(tmp); tmp = NULL; } out: free(abs_src); free(tmp); globfree(&g); if (err == -1) errs = 1; } #define TYPE_OVERFLOW(type, val) \ ((sizeof(type) == 4 && (val) > INT32_MAX) || \ (sizeof(type) == 8 && (val) > INT64_MAX) || \ (sizeof(type) != 4 && sizeof(type) != 8)) void sink(int argc, char **argv, const char *src) { static BUF buffer; struct stat stb; BUF *bp; off_t i; size_t j, count; int amt, exists, first, ofd; mode_t mode, omode, mask; off_t size, statbytes; unsigned long long ull; int setimes, targisdir, wrerr; char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; char **patterns = NULL; size_t n, npatterns = 0; struct timeval tv[2]; #define atime tv[0] #define mtime tv[1] #define SCREWUP(str) { why = str; goto screwup; } if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0)) SCREWUP("Unexpected off_t/time_t size"); setimes = targisdir = 0; mask = umask(0); if (!pflag) (void) umask(mask); if (argc != 1) { run_err("ambiguous target"); exit(1); } targ = *argv; if (targetshouldbedirectory) verifydir(targ); (void) atomicio(vwrite, remout, "", 1); if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) targisdir = 1; if (src != NULL && !iamrecursive && !Tflag) { /* * Prepare to try to restrict incoming filenames to match * the requested destination file glob. */ if (brace_expand(src, &patterns, &npatterns) != 0) fatal_f("could not expand pattern"); } for (first = 1;; first = 0) { cp = buf; if (atomicio(read, remin, cp, 1) != 1) goto done; if (*cp++ == '\n') SCREWUP("unexpected "); do { if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) SCREWUP("lost connection"); *cp++ = ch; } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); *cp = 0; if (verbose_mode) fmprintf(stderr, "Sink: %s", buf); if (buf[0] == '\01' || buf[0] == '\02') { if (iamremote == 0) { (void) snmprintf(visbuf, sizeof(visbuf), NULL, "%s", buf + 1); (void) atomicio(vwrite, STDERR_FILENO, visbuf, strlen(visbuf)); } if (buf[0] == '\02') exit(1); ++errs; continue; } if (buf[0] == 'E') { (void) atomicio(vwrite, remout, "", 1); goto done; } if (ch == '\n') *--cp = 0; cp = buf; if (*cp == 'T') { setimes++; cp++; if (!isdigit((unsigned char)*cp)) SCREWUP("mtime.sec not present"); ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("mtime.sec not delimited"); if (TYPE_OVERFLOW(time_t, ull)) setimes = 0; /* out of range */ mtime.tv_sec = ull; mtime.tv_usec = strtol(cp, &cp, 10); if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 || mtime.tv_usec > 999999) SCREWUP("mtime.usec not delimited"); if (!isdigit((unsigned char)*cp)) SCREWUP("atime.sec not present"); ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("atime.sec not delimited"); if (TYPE_OVERFLOW(time_t, ull)) setimes = 0; /* out of range */ atime.tv_sec = ull; atime.tv_usec = strtol(cp, &cp, 10); if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || atime.tv_usec > 999999) SCREWUP("atime.usec not delimited"); (void) atomicio(vwrite, remout, "", 1); continue; } if (*cp != 'C' && *cp != 'D') { /* * Check for the case "rcp remote:foo\* local:bar". * In this case, the line "No match." can be returned * by the shell before the rcp command on the remote is * executed so the ^Aerror_message convention isn't * followed. */ if (first) { run_err("%s", cp); exit(1); } SCREWUP("expected control record"); } mode = 0; for (++cp; cp < buf + 5; cp++) { if (*cp < '0' || *cp > '7') SCREWUP("bad mode"); mode = (mode << 3) | (*cp - '0'); } if (!pflag) mode &= ~mask; if (*cp++ != ' ') SCREWUP("mode not delimited"); if (!isdigit((unsigned char)*cp)) SCREWUP("size not present"); ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("size not delimited"); if (TYPE_OVERFLOW(off_t, ull)) SCREWUP("size out of range"); size = (off_t)ull; if (*cp == '\0' || strchr(cp, '/') != NULL || strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) { run_err("error: unexpected filename: %s", cp); exit(1); } if (npatterns > 0) { for (n = 0; n < npatterns; n++) { if (strcmp(patterns[n], cp) == 0 || fnmatch(patterns[n], cp, 0) == 0) break; } if (n >= npatterns) { debug2_f("incoming filename \"%s\" does not " "match any of %zu expected patterns", cp, npatterns); for (n = 0; n < npatterns; n++) { debug3_f("expected pattern %zu: \"%s\"", n, patterns[n]); } SCREWUP("filename does not match request"); } } if (targisdir) { static char *namebuf; static size_t cursize; size_t need; need = strlen(targ) + strlen(cp) + 250; if (need > cursize) { free(namebuf); namebuf = xmalloc(need); cursize = need; } (void) snprintf(namebuf, need, "%s%s%s", targ, strcmp(targ, "/") ? "/" : "", cp); np = namebuf; } else np = targ; curfile = cp; exists = stat(np, &stb) == 0; if (buf[0] == 'D') { int mod_flag = pflag; if (!iamrecursive) SCREWUP("received directory without -r"); if (exists) { if (!S_ISDIR(stb.st_mode)) { errno = ENOTDIR; goto bad; } if (pflag) (void) chmod(np, mode); } else { /* Handle copying from a read-only directory */ mod_flag = 1; if (mkdir(np, mode | S_IRWXU) == -1) goto bad; } vect[0] = xstrdup(np); sink(1, vect, src); if (setimes) { setimes = 0; (void) utimes(vect[0], tv); } if (mod_flag) (void) chmod(vect[0], mode); free(vect[0]); continue; } omode = mode; mode |= S_IWUSR; if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { bad: run_err("%s: %s", np, strerror(errno)); continue; } (void) atomicio(vwrite, remout, "", 1); if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { (void) close(ofd); continue; } cp = bp->buf; wrerr = 0; /* * NB. do not use run_err() unless immediately followed by * exit() below as it may send a spurious reply that might * desyncronise us from the peer. Use note_err() instead. */ statbytes = 0; if (showprogress) start_progress_meter(curfile, size, &statbytes); set_nonblock(remin); for (count = i = 0; i < size; i += bp->cnt) { amt = bp->cnt; if (i + amt > size) amt = size - i; count += amt; do { j = atomicio6(read, remin, cp, amt, scpio, &statbytes); if (j == 0) { run_err("%s", j != EPIPE ? strerror(errno) : "dropped connection"); exit(1); } amt -= j; cp += j; } while (amt > 0); if (count == bp->cnt) { /* Keep reading so we stay sync'd up. */ if (!wrerr) { if (atomicio(vwrite, ofd, bp->buf, count) != count) { note_err("%s: %s", np, strerror(errno)); wrerr = 1; } } count = 0; cp = bp->buf; } } unset_nonblock(remin); if (count != 0 && !wrerr && atomicio(vwrite, ofd, bp->buf, count) != count) { note_err("%s: %s", np, strerror(errno)); wrerr = 1; } if (!wrerr && (!exists || S_ISREG(stb.st_mode)) && ftruncate(ofd, size) != 0) note_err("%s: truncate: %s", np, strerror(errno)); if (pflag) { if (exists || omode != mode) #ifdef HAVE_FCHMOD if (fchmod(ofd, omode)) { #else /* HAVE_FCHMOD */ if (chmod(np, omode)) { #endif /* HAVE_FCHMOD */ note_err("%s: set mode: %s", np, strerror(errno)); } } else { if (!exists && omode != mode) #ifdef HAVE_FCHMOD if (fchmod(ofd, omode & ~mask)) { #else /* HAVE_FCHMOD */ if (chmod(np, omode & ~mask)) { #endif /* HAVE_FCHMOD */ note_err("%s: set mode: %s", np, strerror(errno)); } } if (close(ofd) == -1) note_err("%s: close: %s", np, strerror(errno)); (void) response(); if (showprogress) stop_progress_meter(); if (setimes && !wrerr) { setimes = 0; if (utimes(np, tv) == -1) { note_err("%s: set times: %s", np, strerror(errno)); } } /* If no error was noted then signal success for this file */ if (note_err(NULL) == 0) (void) atomicio(vwrite, remout, "", 1); } done: for (n = 0; n < npatterns; n++) free(patterns[n]); free(patterns); return; screwup: for (n = 0; n < npatterns; n++) free(patterns[n]); free(patterns); run_err("protocol error: %s", why); exit(1); } void throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, char *src, char *targ) { char *target = NULL, *filename = NULL, *abs_dst = NULL; char *abs_src = NULL, *tmp = NULL; glob_t g; int i, r, targetisdir, err = 0; if ((filename = basename(src)) == NULL) fatal("basename %s: %s", src, strerror(errno)); if ((abs_src = prepare_remote_path(from, src)) == NULL || (target = prepare_remote_path(to, targ)) == NULL) cleanup_exit(255); memset(&g, 0, sizeof(g)); targetisdir = sftp_remote_is_dir(to, target); if (!targetisdir && targetshouldbedirectory) { error("%s: destination is not a directory", targ); err = -1; goto out; } debug3_f("copying remote %s to remote %s", abs_src, target); if ((r = sftp_glob(from, abs_src, GLOB_NOCHECK|GLOB_MARK, NULL, &g)) != 0) { if (r == GLOB_NOSPACE) error("%s: too many glob matches", src); else error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } /* Did we actually get any matches back from the glob? */ if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) { /* * If nothing matched but a path returned, then it's probably * a GLOB_NOCHECK result. Check whether the unglobbed path * exists so we can give a nice error message early. */ if (sftp_stat(from, g.gl_pathv[0], 1, NULL) != 0) { error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } } for (i = 0; g.gl_pathv[i] && !interrupted; i++) { tmp = xstrdup(g.gl_pathv[i]); if ((filename = basename(tmp)) == NULL) { error("basename %s: %s", tmp, strerror(errno)); err = -1; goto out; } if (targetisdir) abs_dst = sftp_path_append(target, filename); else abs_dst = xstrdup(target); debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { if (sftp_crossload_dir(from, to, g.gl_pathv[i], abs_dst, NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1) err = -1; } else { if (sftp_crossload(from, to, g.gl_pathv[i], abs_dst, NULL, pflag) == -1) err = -1; } free(abs_dst); abs_dst = NULL; free(tmp); tmp = NULL; } out: free(abs_src); free(abs_dst); free(target); free(tmp); globfree(&g); if (err == -1) errs = 1; } int response(void) { char ch, *cp, resp, rbuf[2048], visbuf[2048]; if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) lostconn(0); cp = rbuf; switch (resp) { case 0: /* ok */ return (0); default: *cp++ = resp; /* FALLTHROUGH */ case 1: /* error, followed by error msg */ case 2: /* fatal error, "" */ do { if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) lostconn(0); *cp++ = ch; } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); if (!iamremote) { cp[-1] = '\0'; (void) snmprintf(visbuf, sizeof(visbuf), NULL, "%s\n", rbuf); (void) atomicio(vwrite, STDERR_FILENO, visbuf, strlen(visbuf)); } ++errs; if (resp == 1) return (-1); exit(1); } /* NOTREACHED */ } void usage(void) { (void) fprintf(stderr, "usage: scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" " [-i identity_file] [-J destination] [-l limit] [-o ssh_option]\n" " [-P port] [-S program] [-X sftp_option] source ... target\n"); exit(1); } void run_err(const char *fmt,...) { static FILE *fp; va_list ap; ++errs; if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) { (void) fprintf(fp, "%c", 0x01); (void) fprintf(fp, "scp: "); va_start(ap, fmt); (void) vfprintf(fp, fmt, ap); va_end(ap); (void) fprintf(fp, "\n"); (void) fflush(fp); } if (!iamremote) { va_start(ap, fmt); vfmprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); } } /* * Notes a sink error for sending at the end of a file transfer. Returns 0 if * no error has been noted or -1 otherwise. Use note_err(NULL) to flush * any active error at the end of the transfer. */ int note_err(const char *fmt, ...) { static char *emsg; va_list ap; /* Replay any previously-noted error */ if (fmt == NULL) { if (emsg == NULL) return 0; run_err("%s", emsg); free(emsg); emsg = NULL; return -1; } errs++; /* Prefer first-noted error */ if (emsg != NULL) return -1; va_start(ap, fmt); vasnmprintf(&emsg, INT_MAX, NULL, fmt, ap); va_end(ap); return -1; } void verifydir(char *cp) { struct stat stb; if (!stat(cp, &stb)) { if (S_ISDIR(stb.st_mode)) return; errno = ENOTDIR; } run_err("%s: %s", cp, strerror(errno)); killchild(0); } int okname(char *cp0) { int c; char *cp; cp = cp0; do { c = (int)*cp; if (c & 0200) goto bad; if (!isalpha(c) && !isdigit((unsigned char)c)) { switch (c) { case '\'': case '"': case '`': case ' ': case '#': goto bad; default: break; } } } while (*++cp); return (1); bad: fmprintf(stderr, "%s: invalid user name\n", cp0); return (0); } BUF * allocbuf(BUF *bp, int fd, int blksize) { size_t size; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE struct stat stb; if (fstat(fd, &stb) == -1) { run_err("fstat: %s", strerror(errno)); return (0); } size = ROUNDUP(stb.st_blksize, blksize); if (size == 0) size = blksize; #else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ size = blksize; #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ if (bp->cnt >= size) return (bp); bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1); bp->cnt = size; return (bp); } void lostconn(int signo) { if (!iamremote) (void)write(STDERR_FILENO, "lost connection\n", 16); if (signo) _exit(1); else exit(1); } void cleanup_exit(int i) { if (remin > 0) close(remin); if (remout > 0) close(remout); if (remin2 > 0) close(remin2); if (remout2 > 0) close(remout2); if (do_cmd_pid > 0) (void)waitpid(do_cmd_pid, NULL, 0); if (do_cmd_pid2 > 0) (void)waitpid(do_cmd_pid2, NULL, 0); exit(i); } openssh-10.0p1/PaxHeaders.10889/servconf.c100644 001750 001750 0000000003614775415623 0015145xustar0030 atime=1744182234.751782941 openssh-10.0p1/servconf.c010064400017500001750000003166411477541562300135430ustar00djmdjm/* $OpenBSD: servconf.c,v 1.425 2025/02/25 06:25:30 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #ifdef __OpenBSD__ #include #endif #include #include #include #ifdef HAVE_NET_ROUTE_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_UTIL_H #include #endif #ifdef USE_SYSTEM_GLOB # include #else # include "openbsd-compat/glob.h" #endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "servconf.h" #include "pathnames.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "mac.h" #include "match.h" #include "channels.h" #include "groupaccess.h" #include "canohost.h" #include "packet.h" #include "ssherr.h" #include "hostfile.h" #include "auth.h" #include "myproposal.h" #include "digest.h" #include "version.h" #if !defined(SSHD_PAM_SERVICE) # define SSHD_PAM_SERVICE "sshd" #endif static void add_listen_addr(ServerOptions *, const char *, const char *, int); static void add_one_listen_addr(ServerOptions *, const char *, const char *, int); static void parse_server_config_depth(ServerOptions *options, const char *filename, struct sshbuf *conf, struct include_list *includes, struct connection_info *connectinfo, int flags, int *activep, int depth); extern struct sshbuf *cfg; /* Initializes the server options to their default values. */ void initialize_server_options(ServerOptions *options) { memset(options, 0, sizeof(*options)); /* Portable-specific options */ options->use_pam = -1; options->pam_service_name = NULL; /* Standard Options */ options->num_ports = 0; options->ports_from_cmdline = 0; options->queued_listen_addrs = NULL; options->num_queued_listens = 0; options->listen_addrs = NULL; options->num_listen_addrs = 0; options->address_family = -1; options->routing_domain = NULL; options->num_host_key_files = 0; options->num_host_cert_files = 0; options->host_key_agent = NULL; options->pid_file = NULL; options->login_grace_time = -1; options->permit_root_login = PERMIT_NOT_SET; options->ignore_rhosts = -1; options->ignore_user_known_hosts = -1; options->print_motd = -1; options->print_lastlog = -1; options->x11_forwarding = -1; options->x11_display_offset = -1; options->x11_use_localhost = -1; options->permit_tty = -1; options->permit_user_rc = -1; options->xauth_location = NULL; options->strict_modes = -1; options->tcp_keep_alive = -1; options->log_facility = SYSLOG_FACILITY_NOT_SET; options->log_level = SYSLOG_LEVEL_NOT_SET; options->num_log_verbose = 0; options->log_verbose = NULL; options->hostbased_authentication = -1; options->hostbased_uses_name_from_packet_only = -1; options->hostbased_accepted_algos = NULL; options->hostkeyalgorithms = NULL; options->pubkey_authentication = -1; options->pubkey_auth_options = -1; options->pubkey_accepted_algos = NULL; options->kerberos_authentication = -1; options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; options->gss_cleanup_creds = -1; options->gss_strict_acceptor = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; options->permit_user_env = -1; options->permit_user_env_allowlist = NULL; options->compression = -1; options->rekey_limit = -1; options->rekey_interval = -1; options->allow_tcp_forwarding = -1; options->allow_streamlocal_forwarding = -1; options->allow_agent_forwarding = -1; options->num_allow_users = 0; options->num_deny_users = 0; options->num_allow_groups = 0; options->num_deny_groups = 0; options->ciphers = NULL; options->macs = NULL; options->kex_algorithms = NULL; options->ca_sign_algorithms = NULL; options->fwd_opts.gateway_ports = -1; options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; options->fwd_opts.streamlocal_bind_unlink = -1; options->num_subsystems = 0; options->max_startups_begin = -1; options->max_startups_rate = -1; options->max_startups = -1; options->per_source_max_startups = -1; options->per_source_masklen_ipv4 = -1; options->per_source_masklen_ipv6 = -1; options->per_source_penalty_exempt = NULL; options->per_source_penalty.enabled = -1; options->per_source_penalty.max_sources4 = -1; options->per_source_penalty.max_sources6 = -1; options->per_source_penalty.overflow_mode = -1; options->per_source_penalty.overflow_mode6 = -1; options->per_source_penalty.penalty_crash = -1; options->per_source_penalty.penalty_authfail = -1; options->per_source_penalty.penalty_noauth = -1; options->per_source_penalty.penalty_grace = -1; options->per_source_penalty.penalty_refuseconnection = -1; options->per_source_penalty.penalty_max = -1; options->per_source_penalty.penalty_min = -1; options->max_authtries = -1; options->max_sessions = -1; options->banner = NULL; options->use_dns = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; options->num_authkeys_files = 0; options->num_accept_env = 0; options->num_setenv = 0; options->permit_tun = -1; options->permitted_opens = NULL; options->permitted_listens = NULL; options->adm_forced_command = NULL; options->chroot_directory = NULL; options->authorized_keys_command = NULL; options->authorized_keys_command_user = NULL; options->revoked_keys_file = NULL; options->sk_provider = NULL; options->trusted_user_ca_keys = NULL; options->authorized_principals_file = NULL; options->authorized_principals_command = NULL; options->authorized_principals_command_user = NULL; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->version_addendum = NULL; options->fingerprint_hash = -1; options->disable_forwarding = -1; options->expose_userauth_info = -1; options->required_rsa_size = -1; options->channel_timeouts = NULL; options->num_channel_timeouts = 0; options->unused_connection_timeout = -1; options->sshd_session_path = NULL; options->sshd_auth_path = NULL; options->refuse_connection = -1; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ static int option_clear_or_none(const char *o) { return o == NULL || strcasecmp(o, "none") == 0; } static void assemble_algorithms(ServerOptions *o) { char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; int r; all_cipher = cipher_alg_list(',', 0); all_mac = mac_alg_list(','); all_kex = kex_alg_list(','); all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* remove unsupported algos from default lists */ def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher); def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac); def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex); def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); #define ASSEMBLE(what, defaults, all) \ do { \ if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ fatal_fr(r, "%s", #what); \ } while (0) ASSEMBLE(ciphers, def_cipher, all_cipher); ASSEMBLE(macs, def_mac, all_mac); ASSEMBLE(kex_algorithms, def_kex, all_kex); ASSEMBLE(hostkeyalgorithms, def_key, all_key); ASSEMBLE(hostbased_accepted_algos, def_key, all_key); ASSEMBLE(pubkey_accepted_algos, def_key, all_key); ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); #undef ASSEMBLE free(all_cipher); free(all_mac); free(all_kex); free(all_key); free(all_sig); free(def_cipher); free(def_mac); free(def_kex); free(def_key); free(def_sig); } void servconf_add_hostkey(const char *file, const int line, ServerOptions *options, const char *path, int userprovided) { char *apath = derelativise_path(path); opt_array_append2(file, line, "HostKey", &options->host_key_files, &options->host_key_file_userprovided, &options->num_host_key_files, apath, userprovided); free(apath); } void servconf_add_hostcert(const char *file, const int line, ServerOptions *options, const char *path) { char *apath = derelativise_path(path); opt_array_append(file, line, "HostCertificate", &options->host_cert_files, &options->num_host_cert_files, apath); free(apath); } void fill_default_server_options(ServerOptions *options) { u_int i; /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 0; if (options->pam_service_name == NULL) options->pam_service_name = xstrdup(SSHD_PAM_SERVICE); /* Standard Options */ if (options->num_host_key_files == 0) { /* fill default hostkeys for protocols */ servconf_add_hostkey("[default]", 0, options, _PATH_HOST_RSA_KEY_FILE, 0); #ifdef OPENSSL_HAS_ECC servconf_add_hostkey("[default]", 0, options, _PATH_HOST_ECDSA_KEY_FILE, 0); #endif servconf_add_hostkey("[default]", 0, options, _PATH_HOST_ED25519_KEY_FILE, 0); #ifdef WITH_XMSS servconf_add_hostkey("[default]", 0, options, _PATH_HOST_XMSS_KEY_FILE, 0); #endif /* WITH_XMSS */ } /* No certificates by default */ if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; if (options->address_family == -1) options->address_family = AF_UNSPEC; if (options->listen_addrs == NULL) add_listen_addr(options, NULL, NULL, 0); if (options->pid_file == NULL) options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); if (options->moduli_file == NULL) options->moduli_file = xstrdup(_PATH_DH_MODULI); if (options->login_grace_time == -1) options->login_grace_time = 120; if (options->permit_root_login == PERMIT_NOT_SET) options->permit_root_login = PERMIT_NO_PASSWD; if (options->ignore_rhosts == -1) options->ignore_rhosts = 1; if (options->ignore_user_known_hosts == -1) options->ignore_user_known_hosts = 0; if (options->print_motd == -1) options->print_motd = 1; if (options->print_lastlog == -1) options->print_lastlog = 1; if (options->x11_forwarding == -1) options->x11_forwarding = 0; if (options->x11_display_offset == -1) options->x11_display_offset = 10; if (options->x11_use_localhost == -1) options->x11_use_localhost = 1; if (options->xauth_location == NULL) options->xauth_location = xstrdup(_PATH_XAUTH); if (options->permit_tty == -1) options->permit_tty = 1; if (options->permit_user_rc == -1) options->permit_user_rc = 1; if (options->strict_modes == -1) options->strict_modes = 1; if (options->tcp_keep_alive == -1) options->tcp_keep_alive = 1; if (options->log_facility == SYSLOG_FACILITY_NOT_SET) options->log_facility = SYSLOG_FACILITY_AUTH; if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; if (options->hostbased_authentication == -1) options->hostbased_authentication = 0; if (options->hostbased_uses_name_from_packet_only == -1) options->hostbased_uses_name_from_packet_only = 0; if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; if (options->pubkey_auth_options == -1) options->pubkey_auth_options = 0; if (options->kerberos_authentication == -1) options->kerberos_authentication = 0; if (options->kerberos_or_local_passwd == -1) options->kerberos_or_local_passwd = 1; if (options->kerberos_ticket_cleanup == -1) options->kerberos_ticket_cleanup = 1; if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_cleanup_creds == -1) options->gss_cleanup_creds = 1; if (options->gss_strict_acceptor == -1) options->gss_strict_acceptor = 1; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) options->kbd_interactive_authentication = 1; if (options->permit_empty_passwd == -1) options->permit_empty_passwd = 0; if (options->permit_user_env == -1) { options->permit_user_env = 0; options->permit_user_env_allowlist = NULL; } if (options->compression == -1) #ifdef WITH_ZLIB options->compression = COMP_DELAYED; #else options->compression = COMP_NONE; #endif if (options->rekey_limit == -1) options->rekey_limit = 0; if (options->rekey_interval == -1) options->rekey_interval = 0; if (options->allow_tcp_forwarding == -1) options->allow_tcp_forwarding = FORWARD_ALLOW; if (options->allow_streamlocal_forwarding == -1) options->allow_streamlocal_forwarding = FORWARD_ALLOW; if (options->allow_agent_forwarding == -1) options->allow_agent_forwarding = 1; if (options->fwd_opts.gateway_ports == -1) options->fwd_opts.gateway_ports = 0; if (options->max_startups == -1) options->max_startups = 100; if (options->max_startups_rate == -1) options->max_startups_rate = 30; /* 30% */ if (options->max_startups_begin == -1) options->max_startups_begin = 10; if (options->per_source_max_startups == -1) options->per_source_max_startups = INT_MAX; if (options->per_source_masklen_ipv4 == -1) options->per_source_masklen_ipv4 = 32; if (options->per_source_masklen_ipv6 == -1) options->per_source_masklen_ipv6 = 128; if (options->per_source_penalty.enabled == -1) options->per_source_penalty.enabled = 1; if (options->per_source_penalty.max_sources4 == -1) options->per_source_penalty.max_sources4 = 65536; if (options->per_source_penalty.max_sources6 == -1) options->per_source_penalty.max_sources6 = 65536; if (options->per_source_penalty.overflow_mode == -1) options->per_source_penalty.overflow_mode = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; if (options->per_source_penalty.overflow_mode6 == -1) options->per_source_penalty.overflow_mode6 = options->per_source_penalty.overflow_mode; if (options->per_source_penalty.penalty_crash == -1) options->per_source_penalty.penalty_crash = 90; if (options->per_source_penalty.penalty_grace == -1) options->per_source_penalty.penalty_grace = 10; if (options->per_source_penalty.penalty_authfail == -1) options->per_source_penalty.penalty_authfail = 5; if (options->per_source_penalty.penalty_noauth == -1) options->per_source_penalty.penalty_noauth = 1; if (options->per_source_penalty.penalty_refuseconnection == -1) options->per_source_penalty.penalty_refuseconnection = 10; if (options->per_source_penalty.penalty_min == -1) options->per_source_penalty.penalty_min = 15; if (options->per_source_penalty.penalty_max == -1) options->per_source_penalty.penalty_max = 600; if (options->max_authtries == -1) options->max_authtries = DEFAULT_AUTH_FAIL_MAX; if (options->max_sessions == -1) options->max_sessions = DEFAULT_SESSIONS_MAX; if (options->use_dns == -1) options->use_dns = 0; if (options->client_alive_interval == -1) options->client_alive_interval = 0; if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; if (options->num_authkeys_files == 0) { opt_array_append("[default]", 0, "AuthorizedKeysFiles", &options->authorized_keys_files, &options->num_authkeys_files, _PATH_SSH_USER_PERMITTED_KEYS); opt_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_DSCP_AF21; if (options->ip_qos_bulk == -1) 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) options->fwd_opts.streamlocal_bind_mask = 0177; if (options->fwd_opts.streamlocal_bind_unlink == -1) options->fwd_opts.streamlocal_bind_unlink = 0; if (options->fingerprint_hash == -1) options->fingerprint_hash = SSH_FP_HASH_DEFAULT; if (options->disable_forwarding == -1) options->disable_forwarding = 0; if (options->expose_userauth_info == -1) options->expose_userauth_info = 0; if (options->sk_provider == NULL) options->sk_provider = xstrdup("internal"); if (options->required_rsa_size == -1) options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; if (options->unused_connection_timeout == -1) options->unused_connection_timeout = 0; if (options->sshd_session_path == NULL) options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION); if (options->sshd_auth_path == NULL) options->sshd_auth_path = xstrdup(_PATH_SSHD_AUTH); if (options->refuse_connection == -1) options->refuse_connection = 0; assemble_algorithms(options); #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ free(v); \ v = NULL; \ } \ } while(0) #define CLEAR_ON_NONE_ARRAY(v, nv, none) \ do { \ if (options->nv == 1 && \ strcasecmp(options->v[0], none) == 0) { \ free(options->v[0]); \ free(options->v); \ options->v = NULL; \ options->nv = 0; \ } \ } while (0) CLEAR_ON_NONE(options->pid_file); CLEAR_ON_NONE(options->xauth_location); CLEAR_ON_NONE(options->banner); CLEAR_ON_NONE(options->trusted_user_ca_keys); CLEAR_ON_NONE(options->revoked_keys_file); CLEAR_ON_NONE(options->sk_provider); CLEAR_ON_NONE(options->authorized_principals_file); CLEAR_ON_NONE(options->adm_forced_command); CLEAR_ON_NONE(options->chroot_directory); CLEAR_ON_NONE(options->routing_domain); CLEAR_ON_NONE(options->host_key_agent); CLEAR_ON_NONE(options->per_source_penalty_exempt); for (i = 0; i < options->num_host_key_files; i++) CLEAR_ON_NONE(options->host_key_files[i]); for (i = 0; i < options->num_host_cert_files; i++) CLEAR_ON_NONE(options->host_cert_files[i]); CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); CLEAR_ON_NONE_ARRAY(auth_methods, num_auth_methods, "any"); #undef CLEAR_ON_NONE #undef CLEAR_ON_NONE_ARRAY } /* Keyword tokens. */ typedef enum { sBadOption, /* == unknown option */ /* Portable-specific options */ sUsePAM, sPAMServiceName, /* Standard Options */ sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, sKerberosGetAFSToken, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, sPermitUserEnvironment, sAllowTcpForwarding, sCompression, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sModuliFile, sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms, sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms, sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, sHostCertificate, sInclude, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sStreamLocalBindMask, sStreamLocalBindUnlink, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, sSshdSessionPath, sSshdAuthPath, sRefuseConnection, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; #define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */ #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) #define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ #define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */ /* Textual representation of the tokens. */ static struct { const char *name; ServerOpCodes opcode; u_int flags; } keywords[] = { /* Portable-specific options */ #ifdef USE_PAM { "usepam", sUsePAM, SSHCFG_GLOBAL }, { "pamservicename", sPAMServiceName, SSHCFG_ALL }, #else { "usepam", sUnsupported, SSHCFG_GLOBAL }, { "pamservicename", sUnsupported, SSHCFG_ALL }, #endif { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, /* Standard Options */ { "port", sPort, SSHCFG_GLOBAL }, { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, { "pidfile", sPidFile, SSHCFG_GLOBAL }, { "modulifile", sModuliFile, SSHCFG_GLOBAL }, { "serverkeybits", sDeprecated, SSHCFG_GLOBAL }, { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL }, { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, { "loglevel", sLogLevel, SSHCFG_ALL }, { "logverbose", sLogVerbose, SSHCFG_ALL }, { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL }, { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, { "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, { "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, { "rsaauthentication", sDeprecated, SSHCFG_ALL }, { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, { "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, { "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL }, { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ #ifdef KRB5 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, #ifdef USE_AFS { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, #else { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif #else { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, #endif { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ { "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ { "checkmail", sDeprecated, SSHCFG_GLOBAL }, { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, #ifdef DISABLE_LASTLOG { "printlastlog", sUnsupported, SSHCFG_GLOBAL }, #else { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, #endif { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL }, { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, { "uselogin", sDeprecated, SSHCFG_GLOBAL }, { "compression", sCompression, SSHCFG_GLOBAL }, { "rekeylimit", sRekeyLimit, SSHCFG_ALL }, { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, { "allowusers", sAllowUsers, SSHCFG_ALL }, { "denyusers", sDenyUsers, SSHCFG_ALL }, { "allowgroups", sAllowGroups, SSHCFG_ALL }, { "denygroups", sDenyGroups, SSHCFG_ALL }, { "ciphers", sCiphers, SSHCFG_GLOBAL }, { "macs", sMacs, SSHCFG_GLOBAL }, { "protocol", sIgnore, SSHCFG_GLOBAL }, { "gatewayports", sGatewayPorts, SSHCFG_ALL }, { "subsystem", sSubsystem, SSHCFG_ALL }, { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL }, { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL }, { "persourcepenalties", sPerSourcePenalties, SSHCFG_GLOBAL }, { "persourcepenaltyexemptlist", sPerSourcePenaltyExemptList, SSHCFG_GLOBAL }, { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, { "maxsessions", sMaxSessions, SSHCFG_ALL }, { "banner", sBanner, SSHCFG_ALL }, { "usedns", sUseDNS, SSHCFG_GLOBAL }, { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL }, { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL }, { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL}, { "acceptenv", sAcceptEnv, SSHCFG_ALL }, { "setenv", sSetEnv, SSHCFG_ALL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, { "permittty", sPermitTTY, SSHCFG_ALL }, { "permituserrc", sPermitUserRC, SSHCFG_ALL }, { "match", sMatch, SSHCFG_ALL }, { "permitopen", sPermitOpen, SSHCFG_ALL }, { "permitlisten", sPermitListen, SSHCFG_ALL }, { "forcecommand", sForceCommand, SSHCFG_ALL }, { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, { "include", sInclude, SSHCFG_ALL }, { "ipqos", sIPQoS, SSHCFG_ALL }, { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL }, { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL }, { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, { "rdomain", sRDomain, SSHCFG_ALL }, { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, { "sshdauthpath", sSshdAuthPath, SSHCFG_GLOBAL }, { "refuseconnection", sRefuseConnection, SSHCFG_ALL }, { NULL, sBadOption, 0 } }; static struct { int val; char *text; } tunmode_desc[] = { { SSH_TUNMODE_NO, "no" }, { SSH_TUNMODE_POINTOPOINT, "point-to-point" }, { SSH_TUNMODE_ETHERNET, "ethernet" }, { SSH_TUNMODE_YES, "yes" }, { -1, NULL } }; /* Returns an opcode name from its number */ static const char * lookup_opcode_name(ServerOpCodes code) { u_int i; for (i = 0; keywords[i].name != NULL; i++) if (keywords[i].opcode == code) return(keywords[i].name); return "UNKNOWN"; } /* * Returns the number of the token pointed to by cp or sBadOption. */ static ServerOpCodes parse_token(const char *cp, const char *filename, int linenum, u_int *flags) { u_int i; for (i = 0; keywords[i].name; i++) if (strcasecmp(cp, keywords[i].name) == 0) { *flags = keywords[i].flags; return keywords[i].opcode; } error("%s: line %d: Bad configuration option: %s", filename, linenum, cp); return sBadOption; } char * derelativise_path(const char *path) { char *expanded, *ret, cwd[PATH_MAX]; if (strcasecmp(path, "none") == 0) return xstrdup("none"); expanded = tilde_expand_filename(path, getuid()); if (path_absolute(expanded)) return expanded; if (getcwd(cwd, sizeof(cwd)) == NULL) fatal_f("getcwd: %s", strerror(errno)); xasprintf(&ret, "%s/%s", cwd, expanded); free(expanded); return ret; } static void add_listen_addr(ServerOptions *options, const char *addr, const char *rdomain, int port) { u_int i; if (port > 0) add_one_listen_addr(options, addr, rdomain, port); else { for (i = 0; i < options->num_ports; i++) { add_one_listen_addr(options, addr, rdomain, options->ports[i]); } } } static void add_one_listen_addr(ServerOptions *options, const char *addr, const char *rdomain, int port) { struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr; u_int i; /* Find listen_addrs entry for this rdomain */ for (i = 0; i < options->num_listen_addrs; i++) { if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL) break; if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL) continue; if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0) break; } if (i >= options->num_listen_addrs) { /* No entry for this rdomain; allocate one */ if (i >= INT_MAX) fatal_f("too many listen addresses"); options->listen_addrs = xrecallocarray(options->listen_addrs, options->num_listen_addrs, options->num_listen_addrs + 1, sizeof(*options->listen_addrs)); i = options->num_listen_addrs++; if (rdomain != NULL) options->listen_addrs[i].rdomain = xstrdup(rdomain); } /* options->listen_addrs[i] points to the addresses for this rdomain */ memset(&hints, 0, sizeof(hints)); hints.ai_family = options->address_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) fatal("bad addr or host: %s (%s)", addr ? addr : "", ssh_gai_strerror(gaierr)); for (ai = aitop; ai->ai_next; ai = ai->ai_next) ; ai->ai_next = options->listen_addrs[i].addrs; options->listen_addrs[i].addrs = aitop; } /* Returns nonzero if the routing domain name is valid */ static int valid_rdomain(const char *name) { #if defined(HAVE_SYS_VALID_RDOMAIN) return sys_valid_rdomain(name); #elif defined(__OpenBSD__) const char *errstr; long long num; struct rt_tableinfo info; int mib[6]; size_t miblen = sizeof(mib); if (name == NULL) return 1; num = strtonum(name, 0, 255, &errstr); if (errstr != NULL) return 0; /* Check whether the table actually exists */ memset(mib, 0, sizeof(mib)); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[4] = NET_RT_TABLE; mib[5] = (int)num; if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1) return 0; return 1; #else /* defined(__OpenBSD__) */ error("Routing domains are not supported on this platform"); return 0; #endif } /* * Queue a ListenAddress to be processed once we have all of the Ports * and AddressFamily options. */ static void queue_listen_addr(ServerOptions *options, const char *addr, const char *rdomain, int port) { struct queued_listenaddr *qla; options->queued_listen_addrs = xrecallocarray( options->queued_listen_addrs, options->num_queued_listens, options->num_queued_listens + 1, sizeof(*options->queued_listen_addrs)); qla = &options->queued_listen_addrs[options->num_queued_listens++]; qla->addr = xstrdup(addr); qla->port = port; qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain); } /* * Process queued (text) ListenAddress entries. */ static void process_queued_listen_addrs(ServerOptions *options) { u_int i; struct queued_listenaddr *qla; if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; if (options->address_family == -1) options->address_family = AF_UNSPEC; for (i = 0; i < options->num_queued_listens; i++) { qla = &options->queued_listen_addrs[i]; add_listen_addr(options, qla->addr, qla->rdomain, qla->port); free(qla->addr); free(qla->rdomain); } free(options->queued_listen_addrs); options->queued_listen_addrs = NULL; options->num_queued_listens = 0; } /* * The strategy for the Match blocks is that the config file is parsed twice. * * The first time is at startup. activep is initialized to 1 and the * directives in the global context are processed and acted on. Hitting a * Match directive unsets activep and the directives inside the block are * checked for syntax only. * * The second time is after a connection has been established but before * authentication. activep is initialized to 2 and global config directives * are ignored since they have already been processed. If the criteria in a * Match block is met, activep is set and the subsequent directives * processed and actioned until EOF or another Match block unsets it. Any * options set are copied into the main server config. * * Potential additions/improvements: * - Add Match support for pre-kex directives, eg. Ciphers. * * - Add a Tag directive (idea from David Leonard) ala pf, eg: * Match Address 192.168.0.* * Tag trusted * Match Group wheel * Tag trusted * Match Tag trusted * AllowTcpForwarding yes * GatewayPorts clientspecified * [...] * * - Add a PermittedChannelRequests directive * Match Group shell * PermittedChannelRequests session,forwarded-tcpip */ static int match_cfg_line_group(const char *grps, int line, const char *user) { int result = 0; struct passwd *pw; if (user == NULL) goto out; if ((pw = getpwnam(user)) == NULL) { debug("Can't match group at line %d because user %.100s does " "not exist", line, user); } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { debug("Can't Match group because user %.100s not in any group " "at line %d", user, line); } else if (ga_match_pattern_list(grps) != 1) { debug("user %.100s does not match group list %.100s at line %d", user, grps, line); } else { debug("user %.100s matched group list %.100s at line %d", user, grps, line); result = 1; } out: ga_free(); return result; } static void match_test_missing_fatal(const char *criteria, const char *attrib) { fatal("'Match %s' in configuration but '%s' not in connection " "test specification.", criteria, attrib); } /* * All of the attributes on a single Match line are ANDed together, so we need * to check every attribute and set the result to zero if any attribute does * not match. */ static int match_cfg_line(const char *full_line, int *acp, char ***avp, int line, struct connection_info *ci) { int result = 1, attributes = 0, port; char *arg, *attrib = NULL, *oattrib; if (ci == NULL) { debug3("checking syntax for 'Match %s' on line %d", full_line, line); } else { debug3("checking match for '%s' user %s%s host %s addr %s " "laddr %s lport %d on line %d", full_line, ci->user ? ci->user : "(null)", ci->user_invalid ? " (invalid)" : "", ci->host ? ci->host : "(null)", ci->address ? ci->address : "(null)", ci->laddress ? ci->laddress : "(null)", ci->lport, line); } while ((oattrib = argv_next(acp, avp)) != NULL) { attrib = xstrdup(oattrib); /* Terminate on comment */ if (*attrib == '#') { argv_consume(acp); /* mark all arguments consumed */ break; } arg = NULL; attributes++; /* Criterion "all" has no argument and must appear alone */ if (strcasecmp(attrib, "all") == 0) { if (attributes > 1 || ((arg = argv_next(acp, avp)) != NULL && *arg != '\0' && *arg != '#')) { error("'all' cannot be combined with other " "Match attributes"); result = -1; goto out; } if (arg != NULL && *arg == '#') argv_consume(acp); /* consume remaining args */ result = 1; goto out; } /* Criterion "invalid-user" also has no argument */ if (strcasecmp(attrib, "invalid-user") == 0) { if (ci == NULL) { result = 0; continue; } if (ci->user_invalid == 0) result = 0; else debug("matched invalid-user at line %d", line); continue; } /* Keep this list in sync with below */ if (strprefix(attrib, "user=", 1) != NULL || strprefix(attrib, "group=", 1) != NULL || strprefix(attrib, "host=", 1) != NULL || strprefix(attrib, "address=", 1) != NULL || strprefix(attrib, "localaddress=", 1) != NULL || strprefix(attrib, "localport=", 1) != NULL || strprefix(attrib, "rdomain=", 1) != NULL || strprefix(attrib, "version=", 1) != NULL) { arg = strchr(attrib, '='); *(arg++) = '\0'; } else { arg = argv_next(acp, avp); } /* All other criteria require an argument */ if (arg == NULL || *arg == '\0' || *arg == '#') { error("Missing Match criteria for %s", attrib); result = -1; goto out; } if (strcasecmp(attrib, "user") == 0) { if (ci == NULL || (ci->test && ci->user == NULL)) { result = 0; continue; } if (ci->user == NULL) match_test_missing_fatal("User", "user"); if (match_usergroup_pattern_list(ci->user, arg) != 1) result = 0; else debug("user %.100s matched 'User %.100s' at " "line %d", ci->user, arg, line); } else if (strcasecmp(attrib, "group") == 0) { if (ci == NULL || (ci->test && ci->user == NULL)) { result = 0; continue; } if (ci->user == NULL) match_test_missing_fatal("Group", "user"); switch (match_cfg_line_group(arg, line, ci->user)) { case -1: result = -1; goto out; case 0: result = 0; } } else if (strcasecmp(attrib, "host") == 0) { if (ci == NULL || (ci->test && ci->host == NULL)) { result = 0; continue; } if (ci->host == NULL) match_test_missing_fatal("Host", "host"); if (match_hostname(ci->host, arg) != 1) result = 0; else debug("connection from %.100s matched 'Host " "%.100s' at line %d", ci->host, arg, line); } else if (strcasecmp(attrib, "address") == 0) { if (ci == NULL || (ci->test && ci->address == NULL)) { if (addr_match_list(NULL, arg) != 0) fatal("Invalid Match address argument " "'%s' at line %d", arg, line); result = 0; continue; } if (ci->address == NULL) match_test_missing_fatal("Address", "addr"); switch (addr_match_list(ci->address, arg)) { case 1: debug("connection from %.100s matched 'Address " "%.100s' at line %d", ci->address, arg, line); break; case 0: case -1: result = 0; break; case -2: result = -1; goto out; } } else if (strcasecmp(attrib, "localaddress") == 0){ if (ci == NULL || (ci->test && ci->laddress == NULL)) { if (addr_match_list(NULL, arg) != 0) fatal("Invalid Match localaddress " "argument '%s' at line %d", arg, line); result = 0; continue; } if (ci->laddress == NULL) match_test_missing_fatal("LocalAddress", "laddr"); switch (addr_match_list(ci->laddress, arg)) { case 1: debug("connection from %.100s matched " "'LocalAddress %.100s' at line %d", ci->laddress, arg, line); break; case 0: case -1: result = 0; break; case -2: result = -1; goto out; } } else if (strcasecmp(attrib, "localport") == 0) { if ((port = a2port(arg)) == -1) { error("Invalid LocalPort '%s' on Match line", arg); result = -1; goto out; } if (ci == NULL || (ci->test && ci->lport == -1)) { result = 0; continue; } if (ci->lport == 0) match_test_missing_fatal("LocalPort", "lport"); /* TODO support port lists */ if (port == ci->lport) debug("connection from %.100s matched " "'LocalPort %d' at line %d", ci->laddress, port, line); else result = 0; } else if (strcasecmp(attrib, "rdomain") == 0) { if (ci == NULL || (ci->test && ci->rdomain == NULL)) { result = 0; continue; } if (ci->rdomain == NULL) match_test_missing_fatal("RDomain", "rdomain"); if (match_pattern_list(ci->rdomain, arg, 0) != 1) result = 0; else debug("connection RDomain %.100s matched " "'RDomain %.100s' at line %d", ci->rdomain, arg, line); } else if (strcasecmp(attrib, "version") == 0) { if (match_pattern_list(SSH_RELEASE, arg, 0) != 1) result = 0; else debug("version %.100s matched " "'version %.100s' at line %d", SSH_RELEASE, arg, line); } else { error("Unsupported Match attribute %s", oattrib); result = -1; goto out; } free(attrib); attrib = NULL; } if (attributes == 0) { error("One or more attributes required for Match"); return -1; } out: if (ci != NULL && result != -1) debug3("match %sfound on line %d", result ? "" : "not ", line); free(attrib); return result; } #define WHITESPACE " \t\r\n" /* Multistate option parsing */ struct multistate { char *key; int value; }; static const struct multistate multistate_flag[] = { { "yes", 1 }, { "no", 0 }, { NULL, -1 } }; static const struct multistate multistate_ignore_rhosts[] = { { "yes", IGNORE_RHOSTS_YES }, { "no", IGNORE_RHOSTS_NO }, { "shosts-only", IGNORE_RHOSTS_SHOSTS }, { NULL, -1 } }; static const struct multistate multistate_addressfamily[] = { { "inet", AF_INET }, { "inet6", AF_INET6 }, { "any", AF_UNSPEC }, { NULL, -1 } }; static const struct multistate multistate_permitrootlogin[] = { { "without-password", PERMIT_NO_PASSWD }, { "prohibit-password", PERMIT_NO_PASSWD }, { "forced-commands-only", PERMIT_FORCED_ONLY }, { "yes", PERMIT_YES }, { "no", PERMIT_NO }, { NULL, -1 } }; static const struct multistate multistate_compression[] = { #ifdef WITH_ZLIB { "yes", COMP_DELAYED }, { "delayed", COMP_DELAYED }, #endif { "no", COMP_NONE }, { NULL, -1 } }; static const struct multistate multistate_gatewayports[] = { { "clientspecified", 2 }, { "yes", 1 }, { "no", 0 }, { NULL, -1 } }; static const struct multistate multistate_tcpfwd[] = { { "yes", FORWARD_ALLOW }, { "all", FORWARD_ALLOW }, { "no", FORWARD_DENY }, { "remote", FORWARD_REMOTE }, { "local", FORWARD_LOCAL }, { NULL, -1 } }; static int process_server_config_line_depth(ServerOptions *options, char *line, const char *filename, int linenum, int *activep, struct connection_info *connectinfo, int *inc_flags, int depth, struct include_list *includes) { char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword; int cmdline = 0, *intptr, value, value2, n, port, oactive, r; int ca_only = 0, found = 0; SyslogFacility *log_facility_ptr; LogLevel *log_level_ptr; ServerOpCodes opcode; u_int i, *uintptr, flags = 0; size_t len; long long val64; const struct multistate *multistate_ptr; const char *errstr; struct include_item *item; glob_t gbuf; char **oav = NULL, **av; int oac = 0, ac; int ret = -1; char **strs = NULL; /* string array arguments; freed implicitly */ u_int nstrs = 0; /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ if ((len = strlen(line)) == 0) return 0; for (len--; len > 0; len--) { if (strchr(WHITESPACE "\f", line[len]) == NULL) break; line[len] = '\0'; } str = line; if ((keyword = strdelim(&str)) == NULL) return 0; /* Ignore leading whitespace */ if (*keyword == '\0') keyword = strdelim(&str); if (!keyword || !*keyword || *keyword == '#') return 0; if (str == NULL || *str == '\0') { error("%s line %d: no argument after keyword \"%s\"", filename, linenum, keyword); return -1; } intptr = NULL; charptr = NULL; opcode = parse_token(keyword, filename, linenum, &flags); if (argv_split(str, &oac, &oav, 1) != 0) { error("%s line %d: invalid quotes", filename, linenum); return -1; } ac = oac; av = oav; if (activep == NULL) { /* We are processing a command line directive */ cmdline = 1; activep = &cmdline; } if (*activep && opcode != sMatch && opcode != sInclude) debug3("%s:%d setting %s %s", filename, linenum, keyword, str); if (*activep == 0 && !(flags & SSHCFG_MATCH)) { if (connectinfo == NULL) { fatal("%s line %d: Directive '%s' is not allowed " "within a Match block", filename, linenum, keyword); } else { /* this is a directive we have already processed */ ret = 0; goto out; } } switch (opcode) { /* Portable-specific options */ case sUsePAM: intptr = &options->use_pam; goto parse_flag; case sPAMServiceName: charptr = &options->pam_service_name; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { fatal("%s line %d: missing argument.", filename, linenum); } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; /* Standard Options */ case sBadOption: goto out; case sPort: /* ignore ports from configfile if cmdline specifies ports */ if (options->ports_from_cmdline) { argv_consume(&ac); break; } if (options->num_ports >= MAX_PORTS) fatal("%s line %d: too many ports.", filename, linenum); arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing port number.", filename, linenum); options->ports[options->num_ports++] = a2port(arg); if (options->ports[options->num_ports-1] <= 0) fatal("%s line %d: Badly formatted port number.", filename, linenum); break; case sLoginGraceTime: intptr = &options->login_grace_time; parse_time: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing time value.", filename, linenum); if ((value = convtime(arg)) == -1) fatal("%s line %d: invalid time value.", filename, linenum); if (*activep && *intptr == -1) *intptr = value; break; case sListenAddress: arg = argv_next(&ac, &av); if (arg == NULL || *arg == '\0') fatal("%s line %d: missing address", filename, linenum); /* check for bare IPv6 address: no "[]" and 2 or more ":" */ if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL && strchr(p+1, ':') != NULL) { port = 0; p = arg; } else { arg2 = NULL; p = hpdelim(&arg); if (p == NULL) fatal("%s line %d: bad address:port usage", filename, linenum); p = cleanhostname(p); if (arg == NULL) port = 0; else if ((port = a2port(arg)) <= 0) fatal("%s line %d: bad port number", filename, linenum); } /* Optional routing table */ arg2 = NULL; if ((arg = argv_next(&ac, &av)) != NULL) { if (strcmp(arg, "rdomain") != 0 || (arg2 = argv_next(&ac, &av)) == NULL) fatal("%s line %d: bad ListenAddress syntax", filename, linenum); if (!valid_rdomain(arg2)) fatal("%s line %d: bad routing domain", filename, linenum); } queue_listen_addr(options, p, arg2, port); break; case sAddressFamily: intptr = &options->address_family; multistate_ptr = multistate_addressfamily; parse_multistate: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing argument.", filename, linenum); value = -1; for (i = 0; multistate_ptr[i].key != NULL; i++) { if (strcasecmp(arg, multistate_ptr[i].key) == 0) { value = multistate_ptr[i].value; break; } } if (value == -1) fatal("%s line %d: unsupported option \"%s\".", filename, linenum, arg); if (*activep && *intptr == -1) *intptr = value; break; case sHostKeyFile: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep) { servconf_add_hostkey(filename, linenum, options, arg, 1); } break; case sHostKeyAgent: charptr = &options->host_key_agent; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing socket name.", filename, linenum); if (*activep && *charptr == NULL) *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? xstrdup(arg) : derelativise_path(arg); break; case sHostCertificate: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep) servconf_add_hostcert(filename, linenum, options, arg); break; case sPidFile: charptr = &options->pid_file; parse_filename: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep && *charptr == NULL) { *charptr = derelativise_path(arg); /* increase optional counter */ if (intptr != NULL) *intptr = *intptr + 1; } break; case sModuliFile: charptr = &options->moduli_file; goto parse_filename; case sPermitRootLogin: intptr = &options->permit_root_login; multistate_ptr = multistate_permitrootlogin; goto parse_multistate; case sIgnoreRhosts: intptr = &options->ignore_rhosts; multistate_ptr = multistate_ignore_rhosts; goto parse_multistate; case sIgnoreUserKnownHosts: intptr = &options->ignore_user_known_hosts; parse_flag: multistate_ptr = multistate_flag; goto parse_multistate; case sHostbasedAuthentication: intptr = &options->hostbased_authentication; goto parse_flag; case sHostbasedUsesNameFromPacketOnly: intptr = &options->hostbased_uses_name_from_packet_only; goto parse_flag; case sHostbasedAcceptedAlgorithms: charptr = &options->hostbased_accepted_algos; ca_only = 0; parse_pubkey_algos: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: Missing argument.", filename, linenum); if (*arg != '-' && !sshkey_names_valid2(*arg == '+' || *arg == '^' ? arg + 1 : arg, 1, ca_only)) fatal("%s line %d: Bad key types '%s'.", filename, linenum, arg ? arg : ""); if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sHostKeyAlgorithms: charptr = &options->hostkeyalgorithms; ca_only = 0; goto parse_pubkey_algos; case sCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; ca_only = 1; goto parse_pubkey_algos; case sPubkeyAuthentication: intptr = &options->pubkey_authentication; ca_only = 0; goto parse_flag; case sPubkeyAcceptedAlgorithms: charptr = &options->pubkey_accepted_algos; ca_only = 0; goto parse_pubkey_algos; case sPubkeyAuthOptions: intptr = &options->pubkey_auth_options; value = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (strcasecmp(arg, "none") == 0) continue; if (strcasecmp(arg, "touch-required") == 0) value |= PUBKEYAUTH_TOUCH_REQUIRED; else if (strcasecmp(arg, "verify-required") == 0) value |= PUBKEYAUTH_VERIFY_REQUIRED; else { error("%s line %d: unsupported %s option %s", filename, linenum, keyword, arg); goto out; } } if (*activep && *intptr == -1) *intptr = value; break; case sKerberosAuthentication: intptr = &options->kerberos_authentication; goto parse_flag; case sKerberosOrLocalPasswd: intptr = &options->kerberos_or_local_passwd; goto parse_flag; case sKerberosTicketCleanup: intptr = &options->kerberos_ticket_cleanup; goto parse_flag; case sKerberosGetAFSToken: intptr = &options->kerberos_get_afs_token; goto parse_flag; case sGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; case sGssStrictAcceptor: intptr = &options->gss_strict_acceptor; goto parse_flag; case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; case sKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; case sPrintMotd: intptr = &options->print_motd; goto parse_flag; case sPrintLastLog: intptr = &options->print_lastlog; goto parse_flag; case sX11Forwarding: intptr = &options->x11_forwarding; goto parse_flag; case sX11DisplayOffset: intptr = &options->x11_display_offset; parse_int: arg = argv_next(&ac, &av); if ((errstr = atoi_err(arg, &value)) != NULL) fatal("%s line %d: %s integer value %s.", filename, linenum, keyword, errstr); if (*activep && *intptr == -1) *intptr = value; break; case sX11UseLocalhost: intptr = &options->x11_use_localhost; goto parse_flag; case sXAuthLocation: charptr = &options->xauth_location; goto parse_filename; case sPermitTTY: intptr = &options->permit_tty; goto parse_flag; case sPermitUserRC: intptr = &options->permit_user_rc; goto parse_flag; case sStrictModes: intptr = &options->strict_modes; goto parse_flag; case sTCPKeepAlive: intptr = &options->tcp_keep_alive; goto parse_flag; case sEmptyPasswd: intptr = &options->permit_empty_passwd; goto parse_flag; case sPermitUserEnvironment: intptr = &options->permit_user_env; charptr = &options->permit_user_env_allowlist; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); value = 0; p = NULL; if (strcmp(arg, "yes") == 0) value = 1; else if (strcmp(arg, "no") == 0) value = 0; else { /* Pattern-list specified */ value = 1; p = xstrdup(arg); } if (*activep && *intptr == -1) { *intptr = value; *charptr = p; p = NULL; } free(p); break; case sCompression: intptr = &options->compression; multistate_ptr = multistate_compression; goto parse_multistate; case sRekeyLimit: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcmp(arg, "default") == 0) { val64 = 0; } else { if (scan_scaled(arg, &val64) == -1) fatal("%.200s line %d: Bad %s number '%s': %s", filename, linenum, keyword, arg, strerror(errno)); if (val64 != 0 && val64 < 16) fatal("%.200s line %d: %s too small", filename, linenum, keyword); } if (*activep && options->rekey_limit == -1) options->rekey_limit = val64; if (ac != 0) { /* optional rekey interval present */ if (strcmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* discard */ break; } intptr = &options->rekey_interval; goto parse_time; } break; case sGatewayPorts: intptr = &options->fwd_opts.gateway_ports; multistate_ptr = multistate_gatewayports; goto parse_multistate; case sUseDNS: intptr = &options->use_dns; goto parse_flag; case sLogFacility: log_facility_ptr = &options->log_facility; arg = argv_next(&ac, &av); value = log_facility_number(arg); if (value == SYSLOG_FACILITY_NOT_SET) fatal("%.200s line %d: unsupported log facility '%s'", filename, linenum, arg ? arg : ""); if (*log_facility_ptr == -1) *log_facility_ptr = (SyslogFacility) value; break; case sLogLevel: log_level_ptr = &options->log_level; arg = argv_next(&ac, &av); value = log_level_number(arg); if (value == SYSLOG_LEVEL_NOT_SET) fatal("%.200s line %d: unsupported log level '%s'", filename, linenum, arg ? arg : ""); if (*activep && *log_level_ptr == -1) *log_level_ptr = (LogLevel) value; break; case sLogVerbose: found = options->num_log_verbose == 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (nstrs > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->log_verbose = strs; options->num_log_verbose = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case sAllowTcpForwarding: intptr = &options->allow_tcp_forwarding; multistate_ptr = multistate_tcpfwd; goto parse_multistate; case sAllowStreamLocalForwarding: intptr = &options->allow_streamlocal_forwarding; multistate_ptr = multistate_tcpfwd; goto parse_multistate; case sAllowAgentForwarding: intptr = &options->allow_agent_forwarding; goto parse_flag; case sDisableForwarding: intptr = &options->disable_forwarding; goto parse_flag; case sAllowUsers: chararrayptr = &options->allow_users; uintptr = &options->num_allow_users; parse_allowdenyusers: /* XXX appends to list; doesn't respect first-match-wins */ while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || match_user(NULL, NULL, NULL, arg) == -1) fatal("%s line %d: invalid %s pattern: \"%s\"", filename, linenum, keyword, arg); found = 1; if (!*activep) continue; opt_array_append(filename, linenum, keyword, chararrayptr, uintptr, arg); } if (!found) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } break; case sDenyUsers: chararrayptr = &options->deny_users; uintptr = &options->num_deny_users; goto parse_allowdenyusers; case sAllowGroups: chararrayptr = &options->allow_groups; uintptr = &options->num_allow_groups; /* XXX appends to list; doesn't respect first-match-wins */ parse_allowdenygroups: while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') fatal("%s line %d: empty %s pattern", filename, linenum, keyword); found = 1; if (!*activep) continue; opt_array_append(filename, linenum, keyword, chararrayptr, uintptr, arg); } if (!found) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } break; case sDenyGroups: chararrayptr = &options->deny_groups; uintptr = &options->num_deny_groups; goto parse_allowdenygroups; case sCiphers: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : ""); if (options->ciphers == NULL) options->ciphers = xstrdup(arg); break; case sMacs: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 mac spec '%s'.", filename, linenum, arg ? arg : ""); if (options->macs == NULL) options->macs = xstrdup(arg); break; case sKexAlgorithms: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && !kex_names_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : ""); if (options->kex_algorithms == NULL) options->kex_algorithms = xstrdup(arg); break; case sSubsystem: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (!*activep) { argv_consume(&ac); break; } found = 0; for (i = 0; i < options->num_subsystems; i++) { if (strcmp(arg, options->subsystem_name[i]) == 0) { found = 1; break; } } if (found) { debug("%s line %d: Subsystem '%s' already defined.", filename, linenum, arg); argv_consume(&ac); break; } options->subsystem_name = xrecallocarray( options->subsystem_name, options->num_subsystems, options->num_subsystems + 1, sizeof(*options->subsystem_name)); options->subsystem_command = xrecallocarray( options->subsystem_command, options->num_subsystems, options->num_subsystems + 1, sizeof(*options->subsystem_command)); options->subsystem_args = xrecallocarray( options->subsystem_args, options->num_subsystems, options->num_subsystems + 1, sizeof(*options->subsystem_args)); options->subsystem_name[options->num_subsystems] = xstrdup(arg); arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { fatal("%s line %d: Missing subsystem command.", filename, linenum); } options->subsystem_command[options->num_subsystems] = xstrdup(arg); /* Collect arguments (separate to executable) */ arg = argv_assemble(1, &arg); /* quote command correctly */ arg2 = argv_assemble(ac, av); /* rest of command */ xasprintf(&options->subsystem_args[options->num_subsystems], "%s%s%s", arg, *arg2 == '\0' ? "" : " ", arg2); free(arg2); free(arg); argv_consume(&ac); options->num_subsystems++; break; case sMaxStartups: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((n = sscanf(arg, "%d:%d:%d", &options->max_startups_begin, &options->max_startups_rate, &options->max_startups)) == 3) { if (options->max_startups_begin > options->max_startups || options->max_startups_rate > 100 || options->max_startups_rate < 1) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); } else if (n != 1) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); else options->max_startups = options->max_startups_begin; if (options->max_startups <= 0 || options->max_startups_begin <= 0) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); break; case sPerSourceNetBlockSize: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); switch (n = sscanf(arg, "%d:%d", &value, &value2)) { case 2: if (value2 < 0 || value2 > 128) n = -1; /* FALLTHROUGH */ case 1: if (value < 0 || value > 32) n = -1; } if (n != 1 && n != 2) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); if (*activep) { options->per_source_masklen_ipv4 = value; options->per_source_masklen_ipv6 = value2; } break; case sPerSourceMaxStartups: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcmp(arg, "none") == 0) { /* no limit */ value = INT_MAX; } else { if ((errstr = atoi_err(arg, &value)) != NULL) fatal("%s line %d: %s integer value %s.", filename, linenum, keyword, errstr); } if (*activep && options->per_source_max_startups == -1) options->per_source_max_startups = value; break; case sPerSourcePenaltyExemptList: charptr = &options->per_source_penalty_exempt; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing argument.", filename, linenum); if (addr_match_list(NULL, arg) != 0) { fatal("%s line %d: keyword %s " "invalid address argument.", filename, linenum, keyword); } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sPerSourcePenalties: while ((arg = argv_next(&ac, &av)) != NULL) { found = 1; value = -1; value2 = 0; p = NULL; /* Allow no/yes only in first position */ if (strcasecmp(arg, "no") == 0 || (value2 = (strcasecmp(arg, "yes") == 0))) { if (ac > 0) { fatal("%s line %d: keyword %s \"%s\" " "argument must appear alone.", filename, linenum, keyword, arg); } if (*activep && options->per_source_penalty.enabled == -1) options->per_source_penalty.enabled = value2; continue; } else if (strncmp(arg, "crash:", 6) == 0) { p = arg + 6; intptr = &options->per_source_penalty.penalty_crash; } else if (strncmp(arg, "authfail:", 9) == 0) { p = arg + 9; intptr = &options->per_source_penalty.penalty_authfail; } else if (strncmp(arg, "noauth:", 7) == 0) { p = arg + 7; intptr = &options->per_source_penalty.penalty_noauth; } else if (strncmp(arg, "grace-exceeded:", 15) == 0) { p = arg + 15; intptr = &options->per_source_penalty.penalty_grace; } else if (strncmp(arg, "refuseconnection:", 17) == 0) { p = arg + 17; intptr = &options->per_source_penalty.penalty_refuseconnection; } else if (strncmp(arg, "max:", 4) == 0) { p = arg + 4; intptr = &options->per_source_penalty.penalty_max; } else if (strncmp(arg, "min:", 4) == 0) { p = arg + 4; intptr = &options->per_source_penalty.penalty_min; } else if (strncmp(arg, "max-sources4:", 13) == 0) { intptr = &options->per_source_penalty.max_sources4; if ((errstr = atoi_err(arg+13, &value)) != NULL) fatal("%s line %d: %s value %s.", filename, linenum, keyword, errstr); } else if (strncmp(arg, "max-sources6:", 13) == 0) { intptr = &options->per_source_penalty.max_sources6; if ((errstr = atoi_err(arg+13, &value)) != NULL) fatal("%s line %d: %s value %s.", filename, linenum, keyword, errstr); } else if (strcmp(arg, "overflow:deny-all") == 0) { intptr = &options->per_source_penalty.overflow_mode; value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL; } else if (strcmp(arg, "overflow:permissive") == 0) { intptr = &options->per_source_penalty.overflow_mode; value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; } else if (strcmp(arg, "overflow6:deny-all") == 0) { intptr = &options->per_source_penalty.overflow_mode6; value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL; } else if (strcmp(arg, "overflow6:permissive") == 0) { intptr = &options->per_source_penalty.overflow_mode6; value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; } else { fatal("%s line %d: unsupported %s keyword %s", filename, linenum, keyword, arg); } /* If no value was parsed above, assume it's a time */ if (value == -1 && (value = convtime(p)) == -1) { fatal("%s line %d: invalid %s time value.", filename, linenum, keyword); } if (*activep && *intptr == -1) { *intptr = value; /* any option implicitly enables penalties */ options->per_source_penalty.enabled = 1; } } if (!found) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } break; case sMaxAuthTries: intptr = &options->max_authtries; goto parse_int; case sMaxSessions: intptr = &options->max_sessions; goto parse_int; case sBanner: charptr = &options->banner; goto parse_filename; /* * These options can contain %X options expanded at * connect time, so that you can specify paths like: * * AuthorizedKeysFile /etc/ssh_keys/%u */ case sAuthorizedKeysFile: found = options->num_authkeys_files == 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } arg2 = tilde_expand_filename(arg, getuid()); opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg2); free(arg2); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->authorized_keys_files = strs; options->num_authkeys_files = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case sAuthorizedPrincipalsFile: charptr = &options->authorized_principals_file; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*activep && *charptr == NULL) { *charptr = tilde_expand_filename(arg, getuid()); /* increase optional counter */ if (intptr != NULL) *intptr = *intptr + 1; } break; case sClientAliveInterval: intptr = &options->client_alive_interval; goto parse_time; case sClientAliveCountMax: intptr = &options->client_alive_count_max; goto parse_int; case sAcceptEnv: /* XXX appends to list; doesn't respect first-match-wins */ while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || strchr(arg, '=') != NULL) fatal("%s line %d: Invalid environment name.", filename, linenum); found = 1; if (!*activep) continue; opt_array_append(filename, linenum, keyword, &options->accept_env, &options->num_accept_env, arg); } if (!found) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } break; case sSetEnv: found = options->num_setenv == 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || strchr(arg, '=') == NULL) fatal("%s line %d: Invalid environment.", filename, linenum); if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) { debug2("%s line %d: ignoring duplicate env " "name \"%.64s\"", filename, linenum, arg); continue; } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->setenv = strs; options->num_setenv = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case sPermitTunnel: intptr = &options->permit_tun; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); value = -1; for (i = 0; tunmode_desc[i].val != -1; i++) if (strcmp(tunmode_desc[i].text, arg) == 0) { value = tunmode_desc[i].val; break; } if (value == -1) fatal("%s line %d: bad %s argument %s", filename, linenum, keyword, arg); if (*activep && *intptr == -1) *intptr = value; break; case sInclude: if (cmdline) { fatal("Include directive not supported as a " "command-line option"); } value = 0; while ((arg2 = argv_next(&ac, &av)) != NULL) { if (*arg2 == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } value++; found = 0; if (*arg2 != '/' && *arg2 != '~') { xasprintf(&arg, "%s/%s", SSHDIR, arg2); } else arg = xstrdup(arg2); /* * Don't let included files clobber the containing * file's Match state. */ oactive = *activep; /* consult cache of include files */ TAILQ_FOREACH(item, includes, entry) { if (strcmp(item->selector, arg) != 0) continue; if (item->filename != NULL) { parse_server_config_depth(options, item->filename, item->contents, includes, connectinfo, (*inc_flags & SSHCFG_MATCH_ONLY ? SSHCFG_MATCH_ONLY : (oactive ? 0 : SSHCFG_NEVERMATCH)), activep, depth + 1); } found = 1; *activep = oactive; } if (found != 0) { free(arg); continue; } /* requested glob was not in cache */ debug2("%s line %d: new include %s", filename, linenum, arg); if ((r = glob(arg, 0, NULL, &gbuf)) != 0) { if (r != GLOB_NOMATCH) { fatal("%s line %d: include \"%s\" glob " "failed", filename, linenum, arg); } /* * If no entry matched then record a * placeholder to skip later glob calls. */ debug2("%s line %d: no match for %s", filename, linenum, arg); item = xcalloc(1, sizeof(*item)); item->selector = strdup(arg); TAILQ_INSERT_TAIL(includes, item, entry); } if (gbuf.gl_pathc > INT_MAX) fatal_f("too many glob results"); for (n = 0; n < (int)gbuf.gl_pathc; n++) { debug2("%s line %d: including %s", filename, linenum, gbuf.gl_pathv[n]); item = xcalloc(1, sizeof(*item)); item->selector = strdup(arg); item->filename = strdup(gbuf.gl_pathv[n]); if ((item->contents = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); load_server_config(item->filename, item->contents); parse_server_config_depth(options, item->filename, item->contents, includes, connectinfo, (*inc_flags & SSHCFG_MATCH_ONLY ? SSHCFG_MATCH_ONLY : (oactive ? 0 : SSHCFG_NEVERMATCH)), activep, depth + 1); *activep = oactive; TAILQ_INSERT_TAIL(includes, item, entry); } globfree(&gbuf); free(arg); } if (value == 0) { fatal("%s line %d: %s missing filename argument", filename, linenum, keyword); } break; case sMatch: if (cmdline) fatal("Match directive not supported as a command-line " "option"); value = match_cfg_line(str, &ac, &av, linenum, (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo)); if (value < 0) fatal("%s line %d: Bad Match condition", filename, linenum); *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; /* * The MATCH_ONLY flag is applicable only until the first * match block. */ *inc_flags &= ~SSHCFG_MATCH_ONLY; 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; } found = *uintptr == 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { if (nstrs != 0) { fatal("%s line %d: %s must appear " "alone on a %s line.", filename, linenum, arg, keyword); } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg); continue; } if (opcode == sPermitListen && strchr(arg, ':') == NULL) { /* * Allow bare port number for PermitListen * to indicate a wildcard listen host. */ xasprintf(&arg2, "*:%s", arg); } else { arg2 = xstrdup(arg); p = hpdelim(&arg); if (p == NULL) { fatal("%s line %d: %s missing host", filename, linenum, keyword); } p = cleanhostname(p); } if (arg == NULL || ((port = permitopen_port(arg)) < 0)) { fatal("%s line %d: %s bad port number", filename, linenum, keyword); } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg2); free(arg2); } if (nstrs == 0) { fatal("%s line %d: %s missing argument.", filename, linenum, keyword); } if (found && *activep) { *chararrayptr = strs; *uintptr = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case sForceCommand: if (str == NULL || *str == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); len = strspn(str, WHITESPACE); if (*activep && options->adm_forced_command == NULL) options->adm_forced_command = xstrdup(str + len); argv_consume(&ac); break; case sChrootDirectory: charptr = &options->chroot_directory; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sTrustedUserCAKeys: charptr = &options->trusted_user_ca_keys; goto parse_filename; case sRevokedKeys: charptr = &options->revoked_keys_file; goto parse_filename; case sSecurityKeyProvider: charptr = &options->sk_provider; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*activep && *charptr == NULL) { *charptr = strcasecmp(arg, "internal") == 0 ? xstrdup(arg) : derelativise_path(arg); /* increase optional counter */ if (intptr != NULL) *intptr = *intptr + 1; } break; case sIPQoS: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((value = parse_ipqos(arg)) == -1) fatal("%s line %d: Bad %s value: %s", filename, linenum, keyword, arg); arg = argv_next(&ac, &av); if (arg == NULL) value2 = value; else if ((value2 = parse_ipqos(arg)) == -1) fatal("%s line %d: Bad %s value: %s", filename, linenum, keyword, arg); if (*activep) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; } break; case sVersionAddendum: if (str == NULL || *str == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); len = strspn(str, WHITESPACE); if (strchr(str + len, '\r') != NULL) { fatal("%.200s line %d: Invalid %s argument", filename, linenum, keyword); } if ((arg = strchr(line, '#')) != NULL) { *arg = '\0'; rtrim(line); } if (*activep && options->version_addendum == NULL) { if (strcasecmp(str + len, "none") == 0) options->version_addendum = xstrdup(""); else options->version_addendum = xstrdup(str + len); } argv_consume(&ac); break; case sAuthorizedKeysCommand: charptr = &options->authorized_keys_command; parse_command: len = strspn(str, WHITESPACE); if (str[len] != '/' && strcasecmp(str + len, "none") != 0) { fatal("%.200s line %d: %s must be an absolute path", filename, linenum, keyword); } if (*activep && *charptr == NULL) *charptr = xstrdup(str + len); argv_consume(&ac); break; case sAuthorizedKeysCommandUser: charptr = &options->authorized_keys_command_user; parse_localuser: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { fatal("%s line %d: missing %s argument.", filename, linenum, keyword); } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sAuthorizedPrincipalsCommand: charptr = &options->authorized_principals_command; goto parse_command; case sAuthorizedPrincipalsCommandUser: charptr = &options->authorized_principals_command_user; goto parse_localuser; case sAuthenticationMethods: found = options->num_auth_methods == 0; value = 0; /* seen "any" pseudo-method */ while ((arg = argv_next(&ac, &av)) != NULL) { if (strcmp(arg, "any") == 0) { if (nstrs > 0) { fatal("%s line %d: \"any\" must " "appear alone in %s", filename, linenum, keyword); } value = 1; } else if (value) { fatal("%s line %d: \"any\" must appear " "alone in %s", filename, linenum, keyword); } else if (auth2_methods_valid(arg, 0) != 0) { fatal("%s line %d: invalid %s method list.", filename, linenum, keyword); } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->auth_methods = strs; options->num_auth_methods = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case sStreamLocalBindMask: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); /* Parse mode in octal format */ value = strtol(arg, &p, 8); if (arg == p || value < 0 || value > 0777) fatal("%s line %d: Invalid %s.", filename, linenum, keyword); if (*activep) options->fwd_opts.streamlocal_bind_mask = (mode_t)value; break; case sStreamLocalBindUnlink: intptr = &options->fwd_opts.streamlocal_bind_unlink; goto parse_flag; case sFingerprintHash: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((value = ssh_digest_alg_by_name(arg)) == -1) fatal("%.200s line %d: Invalid %s algorithm \"%s\".", filename, linenum, keyword, arg); if (*activep) options->fingerprint_hash = value; break; case sExposeAuthInfo: intptr = &options->expose_userauth_info; goto parse_flag; case sRDomain: #if !defined(__OpenBSD__) && !defined(HAVE_SYS_SET_PROCESS_RDOMAIN) fatal("%s line %d: setting RDomain not supported on this " "platform.", filename, linenum); #endif charptr = &options->routing_domain; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 && !valid_rdomain(arg)) fatal("%s line %d: invalid routing domain", filename, linenum); if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sRequiredRSASize: intptr = &options->required_rsa_size; goto parse_int; case sChannelTimeout: found = options->num_channel_timeouts == 0; while ((arg = argv_next(&ac, &av)) != NULL) { /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (nstrs > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } else if (parse_pattern_interval(arg, NULL, NULL) != 0) { fatal("%s line %d: invalid channel timeout %s", filename, linenum, arg); } opt_array_append(filename, linenum, keyword, &strs, &nstrs, arg); } if (nstrs == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } if (found && *activep) { options->channel_timeouts = strs; options->num_channel_timeouts = nstrs; strs = NULL; /* transferred */ nstrs = 0; } break; case sUnusedConnectionTimeout: intptr = &options->unused_connection_timeout; /* peek at first arg for "none" so we can reuse parse_time */ if (av[0] != NULL && strcasecmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* consume arg */ if (*activep) *intptr = 0; break; } goto parse_time; case sSshdSessionPath: charptr = &options->sshd_session_path; goto parse_filename; case sSshdAuthPath: charptr = &options->sshd_auth_path; goto parse_filename; case sRefuseConnection: intptr = &options->refuse_connection; multistate_ptr = multistate_flag; goto parse_multistate; case sDeprecated: case sIgnore: case sUnsupported: do_log2(opcode == sIgnore ? SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO, "%s line %d: %s option %s", filename, linenum, opcode == sUnsupported ? "Unsupported" : "Deprecated", keyword); argv_consume(&ac); break; default: fatal("%s line %d: Missing handler for opcode %s (%d)", filename, linenum, keyword, opcode); } /* Check that there is no garbage at end of line. */ if (ac > 0) { error("%.200s line %d: keyword %s extra arguments " "at end of line", filename, linenum, keyword); goto out; } /* success */ ret = 0; out: opt_array_free2(strs, NULL, nstrs); argv_free(oav, oac); return ret; } int process_server_config_line(ServerOptions *options, char *line, const char *filename, int linenum, int *activep, struct connection_info *connectinfo, struct include_list *includes) { int inc_flags = 0; return process_server_config_line_depth(options, line, filename, linenum, activep, connectinfo, &inc_flags, 0, includes); } /* Reads the server configuration file. */ void load_server_config(const char *filename, struct sshbuf *conf) { struct stat st; char *line = NULL, *cp; size_t linesize = 0; FILE *f; int r; debug2_f("filename %s", filename); if ((f = fopen(filename, "r")) == NULL) { perror(filename); exit(1); } sshbuf_reset(conf); /* grow buffer, so realloc is avoided for large config files */ if (fstat(fileno(f), &st) == 0 && st.st_size > 0 && (r = sshbuf_allocate(conf, st.st_size)) != 0) fatal_fr(r, "allocate"); while (getline(&line, &linesize, f) != -1) { /* * Strip whitespace * NB - preserve newlines, they are needed to reproduce * line numbers later for error messages */ cp = line + strspn(line, " \t\r"); if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0) fatal_fr(r, "sshbuf_put"); } free(line); if ((r = sshbuf_put_u8(conf, 0)) != 0) fatal_fr(r, "sshbuf_put_u8"); fclose(f); debug2_f("done config len = %zu", sshbuf_len(conf)); } void parse_server_match_config(ServerOptions *options, struct include_list *includes, struct connection_info *connectinfo) { ServerOptions mo; initialize_server_options(&mo); parse_server_config(&mo, "reprocess config", cfg, includes, connectinfo, 0); copy_set_server_options(options, &mo, 0); } int parse_server_match_testspec(struct connection_info *ci, char *spec) { char *p; const char *val; while ((p = strsep(&spec, ",")) && *p != '\0') { if ((val = strprefix(p, "addr=", 0)) != NULL) { ci->address = xstrdup(val); } else if ((val = strprefix(p, "host=", 0)) != NULL) { ci->host = xstrdup(val); } else if ((val = strprefix(p, "user=", 0)) != NULL) { ci->user = xstrdup(val); } else if ((val = strprefix(p, "laddr=", 0)) != NULL) { ci->laddress = xstrdup(val); } else if ((val = strprefix(p, "rdomain=", 0)) != NULL) { ci->rdomain = xstrdup(val); } else if ((val = strprefix(p, "lport=", 0)) != NULL) { ci->lport = a2port(val); if (ci->lport == -1) { fprintf(stderr, "Invalid port '%s' in test mode" " specification %s\n", p+6, p); return -1; } } else if (strcmp(p, "invalid-user") == 0) { ci->user_invalid = 1; } else { fprintf(stderr, "Invalid test mode specification %s\n", p); return -1; } } return 0; } void servconf_merge_subsystems(ServerOptions *dst, ServerOptions *src) { u_int i, j, found; for (i = 0; i < src->num_subsystems; i++) { found = 0; for (j = 0; j < dst->num_subsystems; j++) { if (strcmp(src->subsystem_name[i], dst->subsystem_name[j]) == 0) { found = 1; break; } } if (found) { debug_f("override \"%s\"", dst->subsystem_name[j]); free(dst->subsystem_command[j]); free(dst->subsystem_args[j]); dst->subsystem_command[j] = xstrdup(src->subsystem_command[i]); dst->subsystem_args[j] = xstrdup(src->subsystem_args[i]); continue; } debug_f("add \"%s\"", src->subsystem_name[i]); dst->subsystem_name = xrecallocarray( dst->subsystem_name, dst->num_subsystems, dst->num_subsystems + 1, sizeof(*dst->subsystem_name)); dst->subsystem_command = xrecallocarray( dst->subsystem_command, dst->num_subsystems, dst->num_subsystems + 1, sizeof(*dst->subsystem_command)); dst->subsystem_args = xrecallocarray( dst->subsystem_args, dst->num_subsystems, dst->num_subsystems + 1, sizeof(*dst->subsystem_args)); j = dst->num_subsystems++; dst->subsystem_name[j] = xstrdup(src->subsystem_name[i]); dst->subsystem_command[j] = xstrdup(src->subsystem_command[i]); dst->subsystem_args[j] = xstrdup(src->subsystem_args[i]); } } /* * Copy any supported values that are set. * * If the preauth flag is set, we do not bother copying the string or * array values that are not used pre-authentication, because any that we * do use must be explicitly sent in mm_getpwnamallow(). */ void copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) { #define M_CP_INTOPT(n) do {\ if (src->n != -1) \ dst->n = src->n; \ } while (0) M_CP_INTOPT(password_authentication); M_CP_INTOPT(gss_authentication); M_CP_INTOPT(pubkey_authentication); M_CP_INTOPT(pubkey_auth_options); M_CP_INTOPT(kerberos_authentication); M_CP_INTOPT(hostbased_authentication); M_CP_INTOPT(hostbased_uses_name_from_packet_only); M_CP_INTOPT(kbd_interactive_authentication); M_CP_INTOPT(permit_root_login); M_CP_INTOPT(permit_empty_passwd); M_CP_INTOPT(ignore_rhosts); M_CP_INTOPT(allow_tcp_forwarding); M_CP_INTOPT(allow_streamlocal_forwarding); M_CP_INTOPT(allow_agent_forwarding); M_CP_INTOPT(disable_forwarding); M_CP_INTOPT(expose_userauth_info); M_CP_INTOPT(permit_tun); M_CP_INTOPT(fwd_opts.gateway_ports); M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_forwarding); M_CP_INTOPT(x11_use_localhost); M_CP_INTOPT(permit_tty); M_CP_INTOPT(permit_user_rc); M_CP_INTOPT(max_sessions); M_CP_INTOPT(max_authtries); M_CP_INTOPT(client_alive_count_max); M_CP_INTOPT(client_alive_interval); M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); M_CP_INTOPT(rekey_limit); M_CP_INTOPT(rekey_interval); M_CP_INTOPT(log_level); M_CP_INTOPT(required_rsa_size); M_CP_INTOPT(unused_connection_timeout); M_CP_INTOPT(refuse_connection); /* * The bind_mask is a mode_t that may be unsigned, so we can't use * M_CP_INTOPT - it does a signed comparison that causes compiler * warnings. */ if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) { dst->fwd_opts.streamlocal_bind_mask = src->fwd_opts.streamlocal_bind_mask; } /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ #define M_CP_STROPT(n) do {\ if (src->n != NULL && dst->n != src->n) { \ free(dst->n); \ dst->n = src->n; \ } \ } while(0) #define M_CP_STRARRAYOPT(s, num_s) do {\ u_int i; \ if (src->num_s != 0) { \ for (i = 0; i < dst->num_s; i++) \ free(dst->s[i]); \ free(dst->s); \ dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \ for (i = 0; i < src->num_s; i++) \ dst->s[i] = xstrdup(src->s[i]); \ dst->num_s = src->num_s; \ } \ } while(0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); /* Arguments that accept '+...' need to be expanded */ assemble_algorithms(dst); /* * The only things that should be below this point are string options * which are only used after authentication. */ if (preauth) return; /* These options may be "none" to clear a global setting */ M_CP_STROPT(adm_forced_command); if (option_clear_or_none(dst->adm_forced_command)) { free(dst->adm_forced_command); dst->adm_forced_command = NULL; } M_CP_STROPT(chroot_directory); if (option_clear_or_none(dst->chroot_directory)) { free(dst->chroot_directory); dst->chroot_directory = NULL; } /* Subsystems require merging. */ servconf_merge_subsystems(dst, src); } #undef M_CP_INTOPT #undef M_CP_STROPT #undef M_CP_STRARRAYOPT #define SERVCONF_MAX_DEPTH 16 static void parse_server_config_depth(ServerOptions *options, const char *filename, struct sshbuf *conf, struct include_list *includes, struct connection_info *connectinfo, int flags, int *activep, int depth) { int linenum, bad_options = 0; char *cp, *obuf, *cbuf; if (depth < 0 || depth > SERVCONF_MAX_DEPTH) fatal("Too many recursive configuration includes"); debug2_f("config %s len %zu%s", filename, sshbuf_len(conf), (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : "")); if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) fatal_f("sshbuf_dup_string failed"); linenum = 1; while ((cp = strsep(&cbuf, "\n")) != NULL) { if (process_server_config_line_depth(options, cp, filename, linenum++, activep, connectinfo, &flags, depth, includes) != 0) bad_options++; } free(obuf); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", filename, bad_options); } void parse_server_config(ServerOptions *options, const char *filename, struct sshbuf *conf, struct include_list *includes, struct connection_info *connectinfo, int reexec) { int active = connectinfo ? 0 : 1; parse_server_config_depth(options, filename, conf, includes, connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0); if (!reexec) process_queued_listen_addrs(options); } static const char * fmt_multistate_int(int val, const struct multistate *m) { u_int i; for (i = 0; m[i].key != NULL; i++) { if (m[i].value == val) return m[i].key; } return "UNKNOWN"; } static const char * fmt_intarg(ServerOpCodes code, int val) { if (val == -1) return "unset"; switch (code) { case sAddressFamily: return fmt_multistate_int(val, multistate_addressfamily); case sPermitRootLogin: return fmt_multistate_int(val, multistate_permitrootlogin); case sGatewayPorts: return fmt_multistate_int(val, multistate_gatewayports); case sCompression: return fmt_multistate_int(val, multistate_compression); case sAllowTcpForwarding: return fmt_multistate_int(val, multistate_tcpfwd); case sAllowStreamLocalForwarding: return fmt_multistate_int(val, multistate_tcpfwd); case sIgnoreRhosts: return fmt_multistate_int(val, multistate_ignore_rhosts); case sFingerprintHash: return ssh_digest_alg_name(val); default: switch (val) { case 0: return "no"; case 1: return "yes"; default: return "UNKNOWN"; } } } static void dump_cfg_int(ServerOpCodes code, int val) { if (code == sUnusedConnectionTimeout && val == 0) { printf("%s none\n", lookup_opcode_name(code)); return; } printf("%s %d\n", lookup_opcode_name(code), val); } static void dump_cfg_oct(ServerOpCodes code, int val) { printf("%s 0%o\n", lookup_opcode_name(code), val); } static void dump_cfg_fmtint(ServerOpCodes code, int val) { printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); } static void dump_cfg_string(ServerOpCodes code, const char *val) { printf("%s %s\n", lookup_opcode_name(code), val == NULL ? "none" : val); } static void dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) { u_int i; for (i = 0; i < count; i++) printf("%s %s\n", lookup_opcode_name(code), vals[i]); } static void dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) { u_int i; switch (code) { case sAuthenticationMethods: case sChannelTimeout: break; default: if (count <= 0) return; break; } printf("%s", lookup_opcode_name(code)); for (i = 0; i < count; i++) printf(" %s", vals[i]); if (code == sAuthenticationMethods && count == 0) printf(" any"); else if (code == sChannelTimeout && count == 0) printf(" none"); printf("\n"); } static char * format_listen_addrs(struct listenaddr *la) { int r; struct addrinfo *ai; char addr[NI_MAXHOST], port[NI_MAXSERV]; char *laddr1 = xstrdup(""), *laddr2 = NULL; /* * ListenAddress must be after Port. add_one_listen_addr pushes * addresses onto a stack, so to maintain ordering we need to * print these in reverse order. */ for (ai = la->addrs; ai; ai = ai->ai_next) { if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { error("getnameinfo: %.100s", ssh_gai_strerror(r)); continue; } laddr2 = laddr1; if (ai->ai_family == AF_INET6) { xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s", addr, port, la->rdomain == NULL ? "" : " rdomain ", la->rdomain == NULL ? "" : la->rdomain, laddr2); } else { xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s", addr, port, la->rdomain == NULL ? "" : " rdomain ", la->rdomain == NULL ? "" : la->rdomain, laddr2); } free(laddr2); } return laddr1; } void dump_config(ServerOptions *o) { char *s; u_int i; /* these are usually at the top of the config */ for (i = 0; i < o->num_ports; i++) printf("port %d\n", o->ports[i]); dump_cfg_fmtint(sAddressFamily, o->address_family); for (i = 0; i < o->num_listen_addrs; i++) { s = format_listen_addrs(&o->listen_addrs[i]); printf("%s", s); free(s); } /* integer arguments */ #ifdef USE_PAM dump_cfg_fmtint(sUsePAM, o->use_pam); dump_cfg_string(sPAMServiceName, o->pam_service_name); #endif dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); dump_cfg_int(sMaxAuthTries, o->max_authtries); dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); dump_cfg_int(sRequiredRSASize, o->required_rsa_size); dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); dump_cfg_int(sUnusedConnectionTimeout, o->unused_connection_timeout); /* formatted integer arguments */ dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, o->hostbased_uses_name_from_packet_only); dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); #ifdef KRB5 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); # ifdef USE_AFS dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif #endif #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, o->kbd_interactive_authentication); dump_cfg_fmtint(sPrintMotd, o->print_motd); #ifndef DISABLE_LASTLOG dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); #endif dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); dump_cfg_fmtint(sPermitTTY, o->permit_tty); dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); dump_cfg_fmtint(sStrictModes, o->strict_modes); dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); dump_cfg_fmtint(sCompression, o->compression); dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); dump_cfg_fmtint(sUseDNS, o->use_dns); dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding); dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); dump_cfg_fmtint(sRefuseConnection, o->refuse_connection); /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); dump_cfg_string(sModuliFile, o->moduli_file); dump_cfg_string(sXAuthLocation, o->xauth_location); dump_cfg_string(sCiphers, o->ciphers); dump_cfg_string(sMacs, o->macs); dump_cfg_string(sBanner, o->banner); dump_cfg_string(sForceCommand, o->adm_forced_command); dump_cfg_string(sChrootDirectory, o->chroot_directory); dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); dump_cfg_string(sRevokedKeys, o->revoked_keys_file); dump_cfg_string(sSecurityKeyProvider, o->sk_provider); dump_cfg_string(sAuthorizedPrincipalsFile, o->authorized_principals_file); dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' ? "none" : o->version_addendum); dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); dump_cfg_string(sHostKeyAgent, o->host_key_agent); dump_cfg_string(sKexAlgorithms, o->kex_algorithms); dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms); dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms); dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); #if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN) dump_cfg_string(sRDomain, o->routing_domain); #endif dump_cfg_string(sSshdSessionPath, o->sshd_session_path); dump_cfg_string(sSshdAuthPath, o->sshd_auth_path); dump_cfg_string(sPerSourcePenaltyExemptList, o->per_source_penalty_exempt); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); /* string array arguments */ dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, o->authorized_keys_files); dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, o->host_key_files); dump_cfg_strarray(sHostCertificate, o->num_host_cert_files, o->host_cert_files); dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv); dump_cfg_strarray_oneline(sAuthenticationMethods, o->num_auth_methods, o->auth_methods); dump_cfg_strarray_oneline(sLogVerbose, o->num_log_verbose, o->log_verbose); dump_cfg_strarray_oneline(sChannelTimeout, o->num_channel_timeouts, o->channel_timeouts); /* other arguments */ for (i = 0; i < o->num_subsystems; i++) printf("subsystem %s %s\n", o->subsystem_name[i], o->subsystem_args[i]); printf("maxstartups %d:%d:%d\n", o->max_startups_begin, o->max_startups_rate, o->max_startups); printf("persourcemaxstartups "); if (o->per_source_max_startups == INT_MAX) printf("none\n"); else printf("%d\n", o->per_source_max_startups); printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4, o->per_source_masklen_ipv6); s = NULL; for (i = 0; tunmode_desc[i].val != -1; i++) { if (tunmode_desc[i].val == o->permit_tun) { s = tunmode_desc[i].text; break; } } dump_cfg_string(sPermitTunnel, s); printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); printf("%s\n", iptos2str(o->ip_qos_bulk)); printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, o->rekey_interval); printf("permitopen"); if (o->num_permitted_opens == 0) printf(" any"); else { for (i = 0; i < o->num_permitted_opens; i++) printf(" %s", o->permitted_opens[i]); } printf("\n"); printf("permitlisten"); if (o->num_permitted_listens == 0) printf(" any"); else { for (i = 0; i < o->num_permitted_listens; i++) printf(" %s", o->permitted_listens[i]); } printf("\n"); if (o->permit_user_env_allowlist == NULL) { dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); } else { printf("permituserenvironment %s\n", o->permit_user_env_allowlist); } printf("pubkeyauthoptions"); if (o->pubkey_auth_options == 0) printf(" none"); if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) printf(" touch-required"); if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) printf(" verify-required"); printf("\n"); if (o->per_source_penalty.enabled) { printf("persourcepenalties crash:%d authfail:%d noauth:%d " "grace-exceeded:%d refuseconnection:%d max:%d min:%d " "max-sources4:%d max-sources6:%d " "overflow:%s overflow6:%s\n", o->per_source_penalty.penalty_crash, o->per_source_penalty.penalty_authfail, o->per_source_penalty.penalty_noauth, o->per_source_penalty.penalty_grace, o->per_source_penalty.penalty_refuseconnection, o->per_source_penalty.penalty_max, o->per_source_penalty.penalty_min, o->per_source_penalty.max_sources4, o->per_source_penalty.max_sources6, o->per_source_penalty.overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ? "deny-all" : "permissive", o->per_source_penalty.overflow_mode6 == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ? "deny-all" : "permissive"); } else printf("persourcepenalties no\n"); } openssh-10.0p1/PaxHeaders.10889/servconf.h100644 001750 001750 0000000003614775415623 0015152xustar0030 atime=1744182234.752757504 openssh-10.0p1/servconf.h010064400017500001750000000276051477541562300135470ustar00djmdjm/* $OpenBSD: servconf.h,v 1.168 2024/09/15 01:18:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Definitions for server configuration data and for the functions reading it. * * 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 SERVCONF_H #define SERVCONF_H #include #define MAX_PORTS 256 /* Max # ports. */ /* permit_root_login */ #define PERMIT_NOT_SET -1 #define PERMIT_NO 0 #define PERMIT_FORCED_ONLY 1 #define PERMIT_NO_PASSWD 2 #define PERMIT_YES 3 /* 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 */ /* Magic name for internal sftp-server */ #define INTERNAL_SFTP_NAME "internal-sftp" /* PubkeyAuthOptions flags */ #define PUBKEYAUTH_TOUCH_REQUIRED (1) #define PUBKEYAUTH_VERIFY_REQUIRED (1<<1) struct ssh; /* * 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; }; #define PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL 1 #define PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE 2 struct per_source_penalty { int enabled; int max_sources4; int max_sources6; int overflow_mode; int overflow_mode6; int penalty_crash; int penalty_grace; int penalty_authfail; int penalty_noauth; int penalty_refuseconnection; int penalty_max; int penalty_min; }; typedef struct { u_int num_ports; u_int ports_from_cmdline; int ports[MAX_PORTS]; /* Port number to listen on. */ 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 */ char *moduli_file; /* moduli file for DH-GEX */ int login_grace_time; /* Disconnect if no auth in this time * (sec). */ int permit_root_login; /* PERMIT_*, see above */ int ignore_rhosts; /* Ignore .rhosts and .shosts. */ int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts * for RhostsRsaAuth */ int print_motd; /* If true, print /etc/motd. */ int print_lastlog; /* If true, print lastlog */ int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ int x11_display_offset; /* What DISPLAY number to start * searching at */ int x11_use_localhost; /* If true, use localhost for fake X11 server. */ char *xauth_location; /* Location of xauth program */ int permit_tty; /* If false, deny pty allocation */ int permit_user_rc; /* If false, deny ~/.ssh/rc execution */ int strict_modes; /* If true, require string home dir modes. */ int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */ int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ char *ciphers; /* Supported SSH2 ciphers. */ char *macs; /* Supported SSH2 macs. */ char *kex_algorithms; /* SSH2 kex methods in order of preference. */ struct ForwardOptions fwd_opts; /* forwarding options */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for system logging. */ u_int num_log_verbose; /* Verbose log overrides */ char **log_verbose; int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ int hostbased_uses_name_from_packet_only; /* experimental */ char *hostbased_accepted_algos; /* Algos allowed for hostbased */ char *hostkeyalgorithms; /* SSH2 server key types */ char *ca_sign_algorithms; /* Allowed CA signature algorithms */ int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ char *pubkey_accepted_algos; /* Signature algos allowed for pubkey */ int pubkey_auth_options; /* -1 or mask of PUBKEYAUTH_* flags */ int kerberos_authentication; /* If true, permit Kerberos * authentication. */ int kerberos_or_local_passwd; /* If true, permit kerberos * and any other password * authentication mechanism, * such as SecurID or * /etc/passwd */ int kerberos_ticket_cleanup; /* If true, destroy ticket * file on logout. */ int kerberos_get_afs_token; /* If true, try to get AFS token if * 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 */ int permit_empty_passwd; /* If false, do not permit empty * passwords. */ int permit_user_env; /* If true, read ~/.ssh/environment */ char *permit_user_env_allowlist; /* pattern-list of allowed env names */ int compression; /* If true, compression is allowed */ int allow_tcp_forwarding; /* One of FORWARD_* */ int allow_streamlocal_forwarding; /* One of FORWARD_* */ int allow_agent_forwarding; int disable_forwarding; u_int num_allow_users; char **allow_users; u_int num_deny_users; char **deny_users; u_int num_allow_groups; char **allow_groups; u_int num_deny_groups; char **deny_groups; u_int num_subsystems; char **subsystem_name; char **subsystem_command; char **subsystem_args; u_int num_accept_env; char **accept_env; u_int num_setenv; char **setenv; int max_startups_begin; int max_startups_rate; int max_startups; int per_source_max_startups; int per_source_masklen_ipv4; int per_source_masklen_ipv6; char *per_source_penalty_exempt; struct per_source_penalty per_source_penalty; int max_authtries; int max_sessions; char *banner; /* SSH-2 banner message */ int use_dns; int client_alive_interval; /* * poke the client this often to * see if it's still there */ int client_alive_count_max; /* * If the client is unresponsive * for this many intervals above, * disconnect the session */ u_int num_authkeys_files; /* Files containing public keys */ char **authorized_keys_files; char *adm_forced_command; int use_pam; /* Enable auth via PAM */ char *pam_service_name; int permit_tun; 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_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; char *version_addendum; /* Appended to SSH banner */ u_int num_auth_methods; char **auth_methods; int fingerprint_hash; int expose_userauth_info; u_int64_t timing_secret; char *sk_provider; int required_rsa_size; /* minimum size of RSA keys */ char **channel_timeouts; /* inactivity timeout by channel type */ u_int num_channel_timeouts; int unused_connection_timeout; char *sshd_session_path; char *sshd_auth_path; int refuse_connection; } ServerOptions; /* Information about the incoming connection as used by Match */ struct connection_info { const char *user; int user_invalid; const char *host; /* possibly resolved hostname */ 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); /* * These are string config options that must be copied between the * Match sub-config and the main config, and must be sent from the * privsep child to the privsep master. We use a macro to ensure all * the options are copied and the copies are done in the correct order. * * NB. an option must appear in servconf.c:copy_set_server_options() or * COPY_MATCH_STRING_OPTS here but never both. */ #define COPY_MATCH_STRING_OPTS() do { \ M_CP_STROPT(banner); \ M_CP_STROPT(trusted_user_ca_keys); \ M_CP_STROPT(revoked_keys_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_accepted_algos); \ M_CP_STROPT(pubkey_accepted_algos); \ M_CP_STROPT(ca_sign_algorithms); \ M_CP_STROPT(routing_domain); \ M_CP_STROPT(permit_user_env_allowlist); \ M_CP_STROPT(pam_service_name); \ M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ M_CP_STRARRAYOPT(allow_users, num_allow_users); \ M_CP_STRARRAYOPT(deny_users, num_deny_users); \ M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \ M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \ M_CP_STRARRAYOPT(accept_env, num_accept_env); \ M_CP_STRARRAYOPT(setenv, num_setenv); \ M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \ M_CP_STRARRAYOPT(channel_timeouts, num_channel_timeouts); \ M_CP_STRARRAYOPT(log_verbose, num_log_verbose); \ M_CP_STRARRAYOPT(subsystem_name, num_subsystems); \ M_CP_STRARRAYOPT(subsystem_command, num_subsystems); \ M_CP_STRARRAYOPT(subsystem_args, num_subsystems); \ } while (0) void initialize_server_options(ServerOptions *); void fill_default_server_options(ServerOptions *); int process_server_config_line(ServerOptions *, char *, const char *, int, int *, struct connection_info *, struct include_list *includes); void load_server_config(const char *, struct sshbuf *); void parse_server_config(ServerOptions *, const char *, struct sshbuf *, struct include_list *includes, struct connection_info *, int); void parse_server_match_config(ServerOptions *, struct include_list *includes, struct connection_info *); int parse_server_match_testspec(struct connection_info *, char *); void servconf_merge_subsystems(ServerOptions *, ServerOptions *); 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 */ openssh-10.0p1/PaxHeaders.10889/serverloop.c100644 001750 001750 0000000003614775415623 0015520xustar0030 atime=1744182234.752757504 openssh-10.0p1/serverloop.c010064400017500001750000000673031477541562300141140ustar00djmdjm/* $OpenBSD: serverloop.c,v 1.241 2024/11/26 22:01:37 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Server main loop for handling the interactive session. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 support by Markus Friedl. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "packet.h" #include "sshbuf.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "canohost.h" #include "sshpty.h" #include "channels.h" #include "ssh2.h" #include "sshkey.h" #include "cipher.h" #include "kex.h" #include "hostfile.h" #include "auth.h" #include "session.h" #include "dispatch.h" #include "auth-options.h" #include "serverloop.h" #include "ssherr.h" extern ServerOptions options; /* XXX */ extern Authctxt *the_authctxt; extern struct sshauthopt *auth_opts; static int no_more_sessions = 0; /* Disallow further sessions. */ static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ /* prototypes */ static void server_init_dispatch(struct ssh *); /* requested tunnel forwarding interface(s), shared with session.c */ char *tun_fwd_ifnames = NULL; static void sigchld_handler(int sig) { child_terminated = 1; } static void client_alive_check(struct ssh *ssh) { char remote_id[512]; int r, channel_id; /* timeout, check to see how many we have had */ 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); } /* * send a bogus global/channel request with "wantreply", * we should get back a failure */ 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_fr(r, "compose"); } else { channel_request_start(ssh, channel_id, "keepalive@openssh.com", 1); } if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send"); } /* * Sleep in ppoll() until we can do something. * Optionally, a maximum time can be specified for the duration of * the wait (0 = infinite). */ static void wait_until_can_do_something(struct ssh *ssh, int connection_in, int connection_out, struct pollfd **pfdp, u_int *npfd_allocp, u_int *npfd_activep, sigset_t *sigsetp, int *conn_in_readyp, int *conn_out_readyp) { struct timespec timeout; char remote_id[512]; int ret; int client_alive_scheduled = 0; u_int p; time_t now; static time_t last_client_time, unused_connection_expiry; *conn_in_readyp = *conn_out_readyp = 0; /* Prepare channel poll. First two pollfd entries are reserved */ ptimeout_init(&timeout); channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2, &timeout); now = monotime(); if (*npfd_activep < 2) fatal_f("bad npfd %u", *npfd_activep); /* shouldn't happen */ if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) { ptimeout_deadline_sec(&timeout, ssh_packet_get_rekey_timeout(ssh)); } /* * If no channels are open and UnusedConnectionTimeout is set, then * start the clock to terminate the connection. */ if (options.unused_connection_timeout != 0) { if (channel_still_open(ssh) || unused_connection_expiry == 0) { unused_connection_expiry = now + options.unused_connection_timeout; } ptimeout_deadline_monotime(&timeout, unused_connection_expiry); } /* * if using client_alive, set the max timeout accordingly, * and indicate that this particular timeout was for client * alive by setting the client_alive_scheduled flag. * * this could be randomized somewhat to make traffic * analysis more difficult, but we're not doing it yet. */ if (options.client_alive_interval) { /* Time we last heard from the client OR sent a keepalive */ if (last_client_time == 0) last_client_time = now; ptimeout_deadline_sec(&timeout, options.client_alive_interval); /* XXX ? deadline_monotime(last_client_time + alive_interval) */ client_alive_scheduled = 1; } #if 0 /* wrong: bad condition XXX */ if (channel_not_very_much_buffered_data()) #endif /* Monitor client connection on reserved pollfd entries */ (*pfdp)[0].fd = connection_in; (*pfdp)[0].events = POLLIN; (*pfdp)[1].fd = connection_out; (*pfdp)[1].events = ssh_packet_have_data_to_write(ssh) ? POLLOUT : 0; /* * 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 && ssh_packet_not_very_much_data_to_write(ssh)) ptimeout_deadline_ms(&timeout, 100); /* Wait for something to happen, or the timeout to expire. */ ret = ppoll(*pfdp, *npfd_activep, ptimeout_get_tsp(&timeout), sigsetp); if (ret == -1) { for (p = 0; p < *npfd_activep; p++) (*pfdp)[p].revents = 0; if (errno != EINTR) fatal_f("ppoll: %.100s", strerror(errno)); return; } *conn_in_readyp = (*pfdp)[0].revents != 0; *conn_out_readyp = (*pfdp)[1].revents != 0; now = monotime(); /* need to reset after ppoll() */ /* ClientAliveInterval probing */ if (client_alive_scheduled) { if (ret == 0 && now >= last_client_time + options.client_alive_interval) { /* ppoll timed out and we're due to probe */ client_alive_check(ssh); last_client_time = now; } else if (ret != 0 && *conn_in_readyp) { /* Data from peer; reset probe timer. */ last_client_time = now; } } /* UnusedConnectionTimeout handling */ if (unused_connection_expiry != 0 && now > unused_connection_expiry && !channel_still_open(ssh)) { sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); logit("terminating inactive connection from %s", remote_id); cleanup_exit(255); } } /* * Processes input from the client and the program. Input data is stored * in buffers and processed later. */ static int process_input(struct ssh *ssh, int connection_in) { int r; if ((r = ssh_packet_process_read(ssh, connection_in)) == 0) return 0; /* success */ if (r == SSH_ERR_SYSTEM_ERROR) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) return 0; if (errno == EPIPE) { logit("Connection closed by %.100s port %d", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); return -1; } logit("Read error from remote host %s port %d: %s", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), strerror(errno)); cleanup_exit(255); } return -1; } /* * Sends data from internal buffers to client program stdin. */ static void process_output(struct ssh *ssh, int connection_out) { int r; /* Send any buffered packet data to the client. */ if ((r = ssh_packet_write_poll(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll", __func__); } } static void process_buffered_input_packets(struct ssh *ssh) { ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL); } static void collect_children(struct ssh *ssh) { pid_t pid; int status; if (child_terminated) { debug("Received SIGCHLD."); while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid == -1 && errno == EINTR)) if (pid > 0) session_close_by_pid(ssh, pid, status); child_terminated = 0; } } void server_loop2(struct ssh *ssh, Authctxt *authctxt) { struct pollfd *pfd = NULL; u_int npfd_alloc = 0, npfd_active = 0; int r, conn_in_ready, conn_out_ready; u_int connection_in, connection_out; sigset_t bsigset, osigset; debug("Entering interactive session for SSH2."); if (sigemptyset(&bsigset) == -1 || sigaddset(&bsigset, SIGCHLD) == -1) error_f("bsigset setup: %s", strerror(errno)); ssh_signal(SIGCHLD, sigchld_handler); child_terminated = 0; connection_in = ssh_packet_get_connection_in(ssh); connection_out = ssh_packet_get_connection_out(ssh); server_init_dispatch(ssh); for (;;) { process_buffered_input_packets(ssh); if (!ssh_packet_is_rekeying(ssh) && ssh_packet_not_very_much_data_to_write(ssh)) channel_output_poll(ssh); /* * Block SIGCHLD while we check for dead children, then pass * the old signal mask through to ppoll() so that it'll wake * up immediately if a child exits after we've called waitpid(). */ if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1) error_f("bsigset sigprocmask: %s", strerror(errno)); collect_children(ssh); wait_until_can_do_something(ssh, connection_in, connection_out, &pfd, &npfd_alloc, &npfd_active, &osigset, &conn_in_ready, &conn_out_ready); if (sigprocmask(SIG_SETMASK, &osigset, NULL) == -1) error_f("osigset sigprocmask: %s", strerror(errno)); channel_after_poll(ssh, pfd, npfd_active); if (conn_in_ready && process_input(ssh, connection_in) < 0) break; /* A timeout may have triggered rekeying */ if ((r = ssh_packet_check_rekey(ssh)) != 0) fatal_fr(r, "cannot start rekeying"); if (conn_out_ready) process_output(ssh, connection_out); } collect_children(ssh); free(pfd); /* free all channels, no more reads and writes */ channel_free_all(ssh); /* free remaining sessions, e.g. remove wtmp entries */ session_destroy_all(ssh, NULL); } static int server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh) { debug("Got %d/%u for keepalive", type, seq); /* * reset timeout, since we got a sane answer from the client. * even if this was generated by something other than * the bogus CHANNEL_REQUEST we send for keepalives. */ ssh_packet_set_alive_timeouts(ssh, 0); return 0; } static Channel * server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg) { Channel *c = NULL; 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_f("invalid target port"); *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; goto out; } if (originator_port > 0xFFFF) { error_f("invalid originator port"); *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; goto out; } debug_f("originator %s port %u, target %s port %u", originator, originator_port, target, target_port); /* XXX fine grained permissions */ if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && 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(struct ssh *ssh) { Channel *c = NULL; 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_f("no/invalid user"); 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_f("invalid originator port"); goto out; } debug_f("originator %s port %d, target %s", originator, originator_port, target); /* XXX fine grained permissions */ if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && auth_opts->permit_port_forwarding_flag && !options.disable_forwarding) { c = channel_connect_to_path(ssh, target, "direct-streamlocal@openssh.com", "direct-streamlocal"); } else { logit("refused streamlocal port forward: " "originator %s port %d, target %s", originator, originator_port, target); } out: free(originator); free(target); return c; } static Channel * server_request_tun(struct ssh *ssh) { Channel *c = NULL; u_int mode, tun; int r, sock; char *tmp, *ifname = NULL; 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: ssh_packet_send_debug(ssh, "Unsupported tunnel device mode."); return NULL; } if ((options.permit_tun & mode) == 0) { ssh_packet_send_debug(ssh, "Server has rejected tunnel device " "forwarding"); return NULL; } if ((r = sshpkt_get_u32(ssh, &tun)) != 0) sshpkt_fatal(ssh, r, "%s: parse device", __func__); if (tun > INT_MAX) { debug_f("invalid tun"); goto done; } if (auth_opts->force_tun_device != -1) { if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != (int)tun) goto done; tun = auth_opts->force_tun_device; } sock = tun_open(tun, mode, &ifname); if (sock < 0) goto done; 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(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) ssh_packet_send_debug(ssh, "Failed to open the tunnel device."); return c; } static Channel * server_request_session(struct ssh *ssh) { Channel *c; int r; debug("input_session_request"); if ((r = sshpkt_get_end(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); if (no_more_sessions) { ssh_packet_disconnect(ssh, "Possible attack: attempt to open a " "session after additional sessions disabled"); } /* * A server session has no fd to read or write until a * CHANNEL_REQUEST for a shell is made, so we set the type to * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all * CHANNEL_REQUEST messages is registered. */ 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(ssh, c); return NULL; } 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, struct ssh *ssh) { Channel *c = NULL; 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_f("ctype %s rchan %u win %u max %u", ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "session") == 0) { c = server_request_session(ssh); } else if (strcmp(ctype, "direct-tcpip") == 0) { c = server_request_direct_tcpip(ssh, &reason, &errmsg); } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { c = server_request_direct_streamlocal(ssh); } else if (strcmp(ctype, "tun@openssh.com") == 0) { c = server_request_tun(ssh); } if (c != NULL) { debug_f("confirm %s", ctype); c->remote_id = rchan; c->have_remote_id = 1; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; if (c->type != SSH_CHANNEL_CONNECTING) { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_send(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: send open confirm", __func__); } } } else { debug_f("failure %s", ctype); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, rchan)) != 0 || (r = sshpkt_put_u32(ssh, reason)) != 0 || (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__); } } free(ctype); return 0; } static int server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) { struct sshbuf *resp = NULL; struct sshbuf *sigbuf = NULL; struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; int r, ndx, success = 0; const u_char *blob; const char *sigalg, *kex_rsa_sigalg = NULL; u_char *sig = 0; size_t blen, slen; if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (sshkey_type_plain(sshkey_type_from_name( ssh->kex->hostkey_alg)) == KEY_RSA) kex_rsa_sigalg = ssh->kex->hostkey_alg; while (ssh_packet_remaining(ssh) > 0) { sshkey_free(key); key = NULL; if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 || (r = sshkey_from_blob(blob, blen, &key)) != 0) { error_fr(r, "parse key"); goto out; } /* * Better check that this is actually one of our hostkeys * before attempting to sign anything with it. */ if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) { error_f("unknown host %s key", sshkey_type(key)); goto out; } /* * XXX refactor: make kex->sign just use an index rather * than passing in public and private keys */ if ((key_prv = get_hostkey_by_index(ndx)) == NULL && (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) { error_f("can't retrieve hostkey %d", ndx); goto out; } sshbuf_reset(sigbuf); free(sig); sig = NULL; /* * For RSA keys, prefer to use the signature type negotiated * during KEX to the default (SHA1). */ sigalg = sshkey_ssh_name(key); if (sshkey_type_plain(key->type) == KEY_RSA) { if (kex_rsa_sigalg != NULL) sigalg = kex_rsa_sigalg; else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) sigalg = "rsa-sha2-512"; else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) sigalg = "rsa-sha2-256"; } debug3_f("sign %s key (index %d) using sigalg %s", sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, "hostkeys-prove-00@openssh.com")) != 0 || (r = sshbuf_put_stringb(sigbuf, ssh->kex->session_id)) != 0 || (r = sshkey_puts(key, sigbuf)) != 0 || (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error_fr(r, "assemble signature"); goto out; } } /* Success */ *respp = resp; resp = NULL; /* don't free it */ success = 1; out: free(sig); sshbuf_free(resp); sshbuf_free(sigbuf); sshkey_free(key); return success; } static int server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { 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_f("no/invalid user"); if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); debug_f("rtype %s want_reply %d", rtype, want_reply); /* -R style forwarding */ if (strcmp(rtype, "tcpip-forward") == 0) { if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &port)) != 0) sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__); debug_f("tcpip-forward listen %s port %u", fwd.listen_host, port); if (port <= INT_MAX) fwd.listen_port = (int)port; /* check permissions */ 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)) { success = 0; ssh_packet_send_debug(ssh, "Server has disabled port forwarding."); } else { /* Start listening on the port */ success = channel_setup_remote_fwd_listener(ssh, &fwd, &allocated_listen_port, &options.fwd_opts); } if ((resp = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (allocated_listen_port != 0 && (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0) fatal_fr(r, "sshbuf_put_u32"); } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &port)) != 0) sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__); debug_f("cancel-tcpip-forward addr %s port %d", 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) { if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) sshpkt_fatal(ssh, r, "%s: parse streamlocal-forward@openssh.com", __func__); debug_f("streamlocal-forward listen path %s", fwd.listen_path); /* check permissions */ if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0 || !auth_opts->permit_port_forwarding_flag || options.disable_forwarding) { success = 0; ssh_packet_send_debug(ssh, "Server has disabled " "streamlocal forwarding."); } else { /* Start listening on the socket */ success = channel_setup_remote_fwd_listener(ssh, &fwd, NULL, &options.fwd_opts); } } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) { if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) sshpkt_fatal(ssh, r, "%s: parse cancel-streamlocal-forward@openssh.com", __func__); debug_f("cancel-streamlocal-forward path %s", 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(ssh, &resp); } /* XXX sshpkt_get_end() */ if (want_reply) { 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, struct ssh *ssh) { Channel *c; int r, success = 0; char *rtype = NULL; u_char want_reply = 0; u_int id = 0; 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 %u request %s reply %d", id, rtype, want_reply); 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")) { 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(ssh, c, rtype); if (want_reply && !(c->flags & CHAN_CLOSE_SENT)) { if (!c->have_remote_id) fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send reply", __func__); } free(rtype); return 0; } static void 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 */ 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 */ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); } openssh-10.0p1/PaxHeaders.10889/serverloop.h100644 001750 001750 0000000003614775415623 0015525xustar0030 atime=1744182234.752757504 openssh-10.0p1/serverloop.h010064400017500001750000000017501477541562300141130ustar00djmdjm/* $OpenBSD: serverloop.h,v 1.8 2017/09/12 06:32:07 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * 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). */ #ifndef SERVERLOOP_H #define SERVERLOOP_H struct ssh; void server_loop2(struct ssh *, Authctxt *); #endif openssh-10.0p1/PaxHeaders.10889/session.c100644 001750 001750 0000000003614775415623 0015003xustar0030 atime=1744182234.760570483 openssh-10.0p1/session.c010064400017500001750000002057101477541562300133730ustar00djmdjm/* $OpenBSD: session.c,v 1.341 2025/04/09 07:00:03 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 support by Markus Friedl. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #ifdef HAVE_SYS_STAT_H # include #endif #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #include #include #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshpty.h" #include "packet.h" #include "sshbuf.h" #include "ssherr.h" #include "match.h" #include "uidswap.h" #include "channels.h" #include "sshkey.h" #include "cipher.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "hostfile.h" #include "auth.h" #include "auth-options.h" #include "authfd.h" #include "pathnames.h" #include "log.h" #include "misc.h" #include "servconf.h" #include "sshlogin.h" #include "serverloop.h" #include "canohost.h" #include "session.h" #include "kex.h" #include "monitor_wrap.h" #include "sftp.h" #include "atomicio.h" #if defined(KRB5) && defined(USE_AFS) #include #endif #ifdef WITH_SELINUX #include #endif /* * Hack for systems that do not support FD passing: allocate PTYs directly * without calling into the monitor. This requires either the post-auth * privsep process retain root privileges (see the comment in * sshd-session.c:privsep_postauth) or that PTY allocation doesn't require * privileges to begin with (e.g. Cygwin). */ #ifdef DISABLE_FD_PASSING #define mm_pty_allocate pty_allocate #endif #define IS_INTERNAL_SFTP(c) \ (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \ (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \ c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \ c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t')) /* func */ Session *session_new(void); 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(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_authenticated2(struct ssh *, Authctxt *); static int session_pty_req(struct ssh *, Session *); /* import */ extern ServerOptions options; extern char *__progname; extern int debug_flag; extern u_int utmp_len; extern int startup_pipe; extern void destroy_sensitive_data(void); extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; extern char *tun_fwd_ifnames; /* serverloop.c */ /* original command from peer. */ const char *original_command = NULL; /* data */ static int sessions_first_unused = -1; static int sessions_nalloc = 0; static Session *sessions = NULL; #define SUBSYSTEM_NONE 0 #define SUBSYSTEM_EXT 1 #define SUBSYSTEM_INT_SFTP 2 #define SUBSYSTEM_INT_SFTP_ERROR 3 #ifdef HAVE_LOGIN_CAP 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; static char *auth_sock_dir = NULL; /* removes the agent forwarding socket */ static void auth_sock_cleanup_proc(struct passwd *pw) { if (auth_sock_name != NULL) { temporarily_use_uid(pw); unlink(auth_sock_name); rmdir(auth_sock_dir); auth_sock_name = NULL; restore_uid(); } } static int auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw) { Channel *nc; int sock = -1; if (auth_sock_name != NULL) { error("authentication forwarding requested twice."); return 0; } /* Temporarily drop privileged uid for mkdir/bind. */ temporarily_use_uid(pw); /* Allocate a buffer for the socket name, and format the name. */ auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX"); /* Create private directory for socket */ if (mkdtemp(auth_sock_dir) == NULL) { ssh_packet_send_debug(ssh, "Agent forwarding disabled: " "mkdtemp() failed: %.100s", strerror(errno)); restore_uid(); free(auth_sock_dir); auth_sock_dir = NULL; goto authsock_err; } xasprintf(&auth_sock_name, "%s/agent.%ld", auth_sock_dir, (long) getpid()); /* Start a Unix listener on auth_sock_name. */ sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0); /* Restore the privileged uid. */ restore_uid(); /* Check for socket/bind/listen failure. */ if (sock < 0) goto authsock_err; /* Allocate a channel for the authentication agent socket. */ nc = channel_new(ssh, "auth-listener", SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "auth socket", 1); nc->path = xstrdup(auth_sock_name); return 1; authsock_err: free(auth_sock_name); if (auth_sock_dir != NULL) { temporarily_use_uid(pw); rmdir(auth_sock_dir); restore_uid(); free(auth_sock_dir); } if (sock != -1) close(sock); auth_sock_name = NULL; auth_sock_dir = NULL; return 0; } static void display_loginmsg(void) { int r; if (sshbuf_len(loginmsg) == 0) return; if ((r = sshbuf_put_u8(loginmsg, 0)) != 0) fatal_fr(r, "sshbuf_put_u8"); printf("%s", (char *)sshbuf_ptr(loginmsg)); sshbuf_reset(loginmsg); } static void prepare_auth_info_file(struct passwd *pw, struct sshbuf *info) { int fd = -1, success = 0; if (!options.expose_userauth_info || info == NULL) return; temporarily_use_uid(pw); auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX"); if ((fd = mkstemp(auth_info_file)) == -1) { error_f("mkstemp: %s", strerror(errno)); goto out; } if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info), sshbuf_len(info)) != sshbuf_len(info)) { error_f("write: %s", strerror(errno)); goto out; } if (close(fd) != 0) { error_f("close: %s", strerror(errno)); goto out; } success = 1; out: if (!success) { if (fd != -1) close(fd); free(auth_info_file); auth_info_file = NULL; } restore_uid(); } static void set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts) { 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 = hpdelim2(&cp, NULL)) == NULL) fatal_f("internal error: hpdelim"); host = cleanhostname(host); if (cp == NULL || (port = permitopen_port(cp)) < 0) fatal_f("internal error: permitopen port"); channel_add_permission(ssh, FORWARD_USER, FORWARD_LOCAL, host, port); free(tmp); } } 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_f("internal error: hpdelim"); host = cleanhostname(host); if (cp == NULL || (port = permitopen_port(cp)) < 0) fatal_f("internal error: permitlisten port"); channel_add_permission(ssh, FORWARD_USER, FORWARD_REMOTE, host, port); free(tmp); } } } void do_authenticated(struct ssh *ssh, Authctxt *authctxt) { setproctitle("%s", authctxt->pw->pw_name); auth_log_authopts("active", auth_opts, 0); /* setup the channel layer */ /* XXX - streamlocal? */ set_fwdpermit_from_authopts(ssh, auth_opts); 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); prepare_auth_info_file(authctxt->pw, authctxt->session_info); do_authenticated2(ssh, authctxt); do_cleanup(ssh, authctxt); } /* Check untrusted xauth strings for metacharacters */ static int xauth_valid_string(const char *s) { size_t i; 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 /* * This is called to fork and execute a command when we have no tty. This * will call do_child from the child, and server_loop from the parent after * setting up file descriptors and such. */ int 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]; if (s == NULL) fatal("do_exec_no_pty: no session"); /* Allocate pipes for communicating with the program. */ if (pipe(pin) == -1) { error_f("pipe in: %.100s", strerror(errno)); return -1; } if (pipe(pout) == -1) { error_f("pipe out: %.100s", strerror(errno)); close(pin[0]); close(pin[1]); return -1; } if (pipe(perr) == -1) { error_f("pipe err: %.100s", strerror(errno)); close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); return -1; } #else int inout[2], err[2]; if (s == NULL) fatal("do_exec_no_pty: no session"); /* Uses socket pairs to communicate with the program. */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) { error_f("socketpair #1: %.100s", strerror(errno)); return -1; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) == -1) { error_f("socketpair #2: %.100s", strerror(errno)); close(inout[0]); close(inout[1]); return -1; } #endif session_proctitle(s); /* Fork the child. */ switch ((pid = fork())) { case -1: error_f("fork: %.100s", strerror(errno)); #ifdef USE_PIPES close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); close(perr[0]); close(perr[1]); #else close(inout[0]); close(inout[1]); close(err[0]); close(err[1]); #endif return -1; case 0: is_child = 1; /* * Create a new session and process group since the 4.4BSD * setlogin() affects the entire process group. */ if (setsid() == -1) error("setsid failed: %.100s", strerror(errno)); #ifdef USE_PIPES /* * Redirect stdin. We close the parent side of the socket * pair, and make the child side the standard input. */ close(pin[1]); if (dup2(pin[0], 0) == -1) perror("dup2 stdin"); close(pin[0]); /* Redirect stdout. */ close(pout[0]); if (dup2(pout[1], 1) == -1) perror("dup2 stdout"); close(pout[1]); /* Redirect stderr. */ close(perr[0]); if (dup2(perr[1], 2) == -1) perror("dup2 stderr"); close(perr[1]); #else /* * Redirect stdin, stdout, and stderr. Stdin and stdout will * use the same socket, as some programs (particularly rdist) * seem to depend on it. */ close(inout[1]); close(err[1]); if (dup2(inout[0], 0) == -1) /* stdin */ perror("dup2 stdin"); if (dup2(inout[0], 1) == -1) /* stdout (same as stdin) */ perror("dup2 stdout"); close(inout[0]); if (dup2(err[0], 2) == -1) /* stderr */ perror("dup2 stderr"); close(err[0]); #endif /* Do processing for the child (exec command etc). */ do_child(ssh, s, command); /* NOTREACHED */ default: break; } #ifdef HAVE_CYGWIN cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); #endif s->pid = pid; /* Set interactive/non-interactive mode. */ ssh_packet_set_interactive(ssh, s->display != NULL, options.ip_qos_interactive, options.ip_qos_bulk); /* * Clear loginmsg, since it's the child's responsibility to display * it to the user, otherwise multiple sessions may accumulate * multiple copies of the login messages. */ sshbuf_reset(loginmsg); #ifdef USE_PIPES /* We are the parent. Close the child sides of the pipes. */ close(pin[0]); close(pout[1]); close(perr[1]); 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]); close(err[0]); /* * Enter the interactive session. Note: server_loop must be able to * handle the case that fdin and fdout are the same. */ session_set_fds(ssh, s, inout[1], inout[1], err[1], s->is_subsystem, 0); #endif return 0; } /* * This is called to fork and execute a command when we have a tty. This * will call do_child from the child, and server_loop from the parent after * setting up file descriptors, controlling tty, updating wtmp, utmp, * lastlog, and other such operations. */ int do_exec_pty(struct ssh *ssh, Session *s, const char *command) { int fdout, ptyfd, ttyfd, ptymaster; pid_t pid; if (s == NULL) fatal("do_exec_pty: no session"); ptyfd = s->ptyfd; ttyfd = s->ttyfd; /* * Create another descriptor of the pty master side for use as the * standard input. We could use the original descriptor, but this * simplifies code in server_loop. The descriptor is bidirectional. * Do this before forking (and cleanup in the child) so as to * detect and gracefully fail out-of-fd conditions. */ if ((fdout = dup(ptyfd)) == -1) { error_f("dup #1: %s", strerror(errno)); close(ttyfd); close(ptyfd); return -1; } /* we keep a reference to the pty master */ if ((ptymaster = dup(ptyfd)) == -1) { error_f("dup #2: %s", strerror(errno)); close(ttyfd); close(ptyfd); close(fdout); return -1; } /* Fork the child. */ switch ((pid = fork())) { case -1: error_f("fork: %.100s", strerror(errno)); close(fdout); close(ptymaster); close(ttyfd); close(ptyfd); return -1; case 0: is_child = 1; close(fdout); close(ptymaster); /* Close the master side of the pseudo tty. */ close(ptyfd); /* Make the pseudo tty our controlling tty. */ pty_make_controlling_tty(&ttyfd, s->tty); /* Redirect stdin/stdout/stderr from the pseudo tty. */ if (dup2(ttyfd, 0) == -1) error("dup2 stdin: %s", strerror(errno)); if (dup2(ttyfd, 1) == -1) error("dup2 stdout: %s", strerror(errno)); if (dup2(ttyfd, 2) == -1) error("dup2 stderr: %s", strerror(errno)); /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); /* record login, etc. similar to login(1) */ #ifndef HAVE_OSF_SIA do_login(ssh, s, command); #endif /* * Do common processing for the child, such as execing * the command. */ do_child(ssh, s, command); /* NOTREACHED */ default: break; } #ifdef HAVE_CYGWIN cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); #endif s->pid = pid; /* Parent. Close the slave side of the pseudo tty. */ close(ttyfd); /* Enter interactive session. */ s->ptymaster = ptymaster; ssh_packet_set_interactive(ssh, 1, options.ip_qos_interactive, options.ip_qos_bulk); session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1); return 0; } /* * This is called to fork and execute a command. If another command is * to be forced, execute that instead. */ int do_exec(struct ssh *ssh, Session *s, const char *command) { int ret; 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 (auth_opts->force_command != NULL) { original_command = 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; } else if (s->is_subsystem) s->is_subsystem = SUBSYSTEM_EXT; snprintf(session_type, sizeof(session_type), "forced-command %s '%.900s'", forced, command); } else if (s->is_subsystem) { snprintf(session_type, sizeof(session_type), "subsystem '%.900s'", s->subsys); } else if (command == NULL) { snprintf(session_type, sizeof(session_type), "shell"); } else { /* NB. we don't log unforced commands to preserve privacy */ snprintf(session_type, sizeof(session_type), "command"); } if (s->ttyfd != -1) { tty = s->tty; if (strncmp(tty, "/dev/", 5) == 0) tty += 5; } 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, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), s->self); #ifdef SSH_AUDIT_EVENTS if (command != NULL) mm_audit_run_command(command); else if (s->ttyfd == -1) { char *shell = s->pw->pw_shell; if (shell[0] == '\0') /* empty shell means /bin/sh */ shell =_PATH_BSHELL; mm_audit_run_command(shell); } #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); else ret = do_exec_no_pty(ssh, s, command); original_command = NULL; /* * Clear loginmsg: it's the child's responsibility to display * it to the user, otherwise multiple sessions may accumulate * multiple copies of the login messages. */ sshbuf_reset(loginmsg); return ret; } /* administrative, login(1)-like work */ void do_login(struct ssh *ssh, Session *s, const char *command) { socklen_t fromlen; struct sockaddr_storage from; /* * 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 (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); } } if (check_quietlogin(s, command)) return; display_loginmsg(); do_motd(); } /* * Display the message of the day. */ void do_motd(void) { FILE *f; char buf[256]; if (options.print_motd) { #ifdef HAVE_LOGIN_CAP f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", "/etc/motd"), "r"); #else f = fopen("/etc/motd", "r"); #endif if (f) { while (fgets(buf, sizeof(buf), f)) fputs(buf, stdout); fclose(f); } } } /* * Check for quiet login, either .hushlogin or command given. */ int check_quietlogin(Session *s, const char *command) { char buf[256]; struct passwd *pw = s->pw; struct stat st; /* Return 1 if .hushlogin exists or a command given. */ if (command != NULL) return 1; snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); #ifdef HAVE_LOGIN_CAP if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0) return 1; #else if (stat(buf, &st) >= 0) return 1; #endif return 0; } /* * 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 allowlist is not NULL, then it is interpreted as a pattern list and * only variable names that match it will be accepted. */ static void read_environment_file(char ***env, u_int *envsize, const char *filename, const char *allowlist) { FILE *f; char *line = NULL, *cp, *value; size_t linesize = 0; u_int lineno = 0; f = fopen(filename, "r"); if (!f) return; while (getline(&line, &linesize, f) != -1) { if (++lineno > 1000) fatal("Too many lines in environment file %s", filename); for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') continue; cp[strcspn(cp, "\n")] = '\0'; value = strchr(cp, '='); if (value == NULL) { fprintf(stderr, "Bad line %u in %.100s\n", lineno, filename); continue; } /* * Replace the equals sign by nul, and advance value to * the value string. */ *value = '\0'; value++; if (allowlist != NULL && match_pattern_list(cp, allowlist, 0) != 1) continue; child_set_env(env, envsize, cp, value); } free(line); fclose(f); } #ifdef HAVE_ETC_DEFAULT_LOGIN /* * Return named variable from specified environment, or NULL if not present. */ static char * child_get_env(char **env, const char *name) { int i; size_t len; len = strlen(name); for (i=0; env[i] != NULL; i++) if (strncmp(name, env[i], len) == 0 && env[i][len] == '=') return(env[i] + len + 1); return NULL; } /* * Read /etc/default/login. * We pick up the PATH (or SUPATH for root) and UMASK. */ static void read_etc_default_login(char ***env, u_int *envsize, uid_t uid) { char **tmpenv = NULL, *var; u_int i, tmpenvsize = 0; u_long mask; /* * We don't want to copy the whole file to the child's environment, * so we use a temporary environment and copy the variables we're * interested in. */ read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login", options.permit_user_env_allowlist); if (tmpenv == NULL) return; if (uid == 0) var = child_get_env(tmpenv, "SUPATH"); else var = child_get_env(tmpenv, "PATH"); if (var != NULL) child_set_env(env, envsize, "PATH", var); if ((var = child_get_env(tmpenv, "UMASK")) != NULL) if (sscanf(var, "%5lo", &mask) == 1) umask((mode_t)mask); for (i = 0; tmpenv[i] != NULL; i++) free(tmpenv[i]); free(tmpenv); } #endif /* HAVE_ETC_DEFAULT_LOGIN */ #if defined(USE_PAM) || defined(HAVE_CYGWIN) static void copy_environment_denylist(char **source, char ***env, u_int *envsize, const char *denylist) { char *var_name, *var_val; int i; if (source == NULL) return; for(i = 0; source[i] != NULL; i++) { var_name = xstrdup(source[i]); if ((var_val = strstr(var_name, "=")) == NULL) { free(var_name); continue; } *var_val++ = '\0'; if (denylist == NULL || match_pattern_list(var_name, denylist, 0) != 1) { debug3("Copy environment: %s=%s", var_name, var_val); child_set_env(env, envsize, var_name, var_val); } 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_denylist(source, env, envsize, NULL); } #endif static char ** do_setup_env(struct ssh *ssh, Session *s, const char *shell) { char buf[256]; size_t n; u_int i, envsize; char *ocp, *cp, *value, **env, *laddr; struct passwd *pw = s->pw; #if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN) char *path = NULL; #endif /* Initialize the environment. */ envsize = 100; env = xcalloc(envsize, sizeof(char *)); env[0] = NULL; #ifdef HAVE_CYGWIN /* * The Windows environment contains some setting which are * important for a running system. They must not be dropped. */ { char **p; p = fetch_windows_environment(); copy_environment(p, &env, &envsize); free_windows_environment(p); } #endif #ifdef GSSAPI /* Allow any GSSAPI methods that we've used to alter * the child's environment as they see fit */ ssh_gssapi_do_child(&env, &envsize); #endif /* 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); #ifdef _AIX child_set_env(&env, &envsize, "LOGIN", pw->pw_name); #endif 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")); #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. */ # ifdef HAVE_ETC_DEFAULT_LOGIN 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); } # endif /* HAVE_CYGWIN */ #endif /* HAVE_LOGIN_CAP */ if (!options.use_pam) { snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name); child_set_env(&env, &envsize, "MAIL", buf); } /* Normal systems set SHELL by default. */ child_set_env(&env, &envsize, "SHELL", shell); if (getenv("TZ")) child_set_env(&env, &envsize, "TZ", getenv("TZ")); if (s->term) child_set_env(&env, &envsize, "TERM", s->term); if (s->display) child_set_env(&env, &envsize, "DISPLAY", s->display); /* * Since we clear KRB5CCNAME at startup, if it's set now then it * must have been set by a native authentication method (eg AIX or * SIA), so copy it to the child. */ { char *cp; if ((cp = getenv("KRB5CCNAME")) != NULL) child_set_env(&env, &envsize, "KRB5CCNAME", cp); } #ifdef _AIX { char *cp; if ((cp = getenv("AUTHSTATE")) != NULL) child_set_env(&env, &envsize, "AUTHSTATE", cp); read_environment_file(&env, &envsize, "/etc/environment", options.permit_user_env_allowlist); } #endif #ifdef KRB5 if (s->authctxt->krb5_ccname) 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 != NULL) { *cp = '\0'; /* Apply PermitUserEnvironment allowlist */ if (options.permit_user_env_allowlist == NULL || match_pattern_list(ocp, options.permit_user_env_allowlist, 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/%s/environment", pw->pw_dir, _PATH_SSH_USER_DIR); read_environment_file(&env, &envsize, buf, options.permit_user_env_allowlist); } #ifdef USE_PAM /* * Pull in any environment variables that may have * been set by PAM. */ if (options.use_pam) { char **p; /* * Don't allow PAM-internal env vars to leak * back into the session environment. */ #define PAM_ENV_DENYLIST "SSH_AUTH_INFO*,SSH_CONNECTION*" p = fetch_pam_child_environment(); copy_environment_denylist(p, &env, &envsize, PAM_ENV_DENYLIST); free_pam_environment(p); p = fetch_pam_environment(); copy_environment_denylist(p, &env, &envsize, PAM_ENV_DENYLIST); free_pam_environment(p); } #endif /* USE_PAM */ /* 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); free(cp); } /* 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"); for (i = 0; env[i]; i++) fprintf(stderr, " %.200s\n", env[i]); } return env; } /* * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found * first in this order). */ static void do_rc_files(struct ssh *ssh, Session *s, const char *shell) { FILE *f = NULL; char *cmd = NULL, *user_rc = NULL; int do_xauth; struct stat st; do_xauth = s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; xasprintf(&user_rc, "%s/%s", s->pw->pw_dir, _PATH_SSH_USER_RC); /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ if (!s->is_subsystem && options.adm_forced_command == NULL && auth_opts->permit_user_rc && options.permit_user_rc && stat(user_rc, &st) >= 0) { if (xasprintf(&cmd, "%s -c '%s %s'", shell, _PATH_BSHELL, user_rc) == -1) fatal_f("xasprintf: %s", strerror(errno)); if (debug_flag) fprintf(stderr, "Running %s\n", cmd); f = popen(cmd, "w"); if (f) { if (do_xauth) fprintf(f, "%s %s\n", s->auth_proto, s->auth_data); pclose(f); } else fprintf(stderr, "Could not run %s\n", user_rc); } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { if (debug_flag) fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, _PATH_SSH_SYSTEM_RC); f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); if (f) { if (do_xauth) fprintf(f, "%s %s\n", s->auth_proto, s->auth_data); pclose(f); } else fprintf(stderr, "Could not run %s\n", _PATH_SSH_SYSTEM_RC); } else if (do_xauth && options.xauth_location != NULL) { /* Add authority data to .Xauthority if appropriate. */ if (debug_flag) { fprintf(stderr, "Running %.500s remove %.100s\n", options.xauth_location, s->auth_display); fprintf(stderr, "%.500s add %.100s %.100s %.100s\n", options.xauth_location, s->auth_display, s->auth_proto, s->auth_data); } if (xasprintf(&cmd, "%s -q -", options.xauth_location) == -1) fatal_f("xasprintf: %s", strerror(errno)); f = popen(cmd, "w"); if (f) { fprintf(f, "remove %s\n", s->auth_display); fprintf(f, "add %s %s %s\n", s->auth_display, s->auth_proto, s->auth_data); pclose(f); } else { fprintf(stderr, "Could not run %s\n", cmd); } } free(cmd); free(user_rc); } static void do_nologin(struct passwd *pw) { FILE *f = NULL; char buf[1024], *nl, *def_nl = _PATH_NOLOGIN; struct stat sb; #ifdef HAVE_LOGIN_CAP if (login_getcapbool(lc, "ignorenologin", 0) || pw->pw_uid == 0) return; nl = login_getcapstr(lc, "nologin", def_nl, def_nl); #else if (pw->pw_uid == 0) return; nl = def_nl; #endif if (stat(nl, &sb) == -1) return; /* /etc/nologin exists. Print its contents if we can and exit. */ logit("User %.100s not allowed because %s exists", pw->pw_name, nl); if ((f = fopen(nl, "r")) != NULL) { while (fgets(buf, sizeof(buf), f)) fputs(buf, stderr); fclose(f); } exit(254); } /* * Chroot into a directory after checking it for safety: all path components * must be root-owned directories with strict permissions. */ static void safely_chroot(const char *path, uid_t uid) { const char *cp; char component[PATH_MAX]; struct stat st; if (!path_absolute(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_f("checking '%s'", component); if (stat(component, &st) != 0) fatal_f("stat(\"%s\"): %s", component, strerror(errno)); if (st.st_uid != 0 || (st.st_mode & 022) != 0) fatal("bad ownership or modes for chroot " "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)); if (chroot(path) == -1) fatal("chroot(\"%s\"): %s", path, strerror(errno)); if (chdir("/") == -1) fatal_f("chdir(/) after chroot: %s", strerror(errno)); verbose("Changed root directory to \"%s\"", path); } /* Set login name, uid, gid, and groups. */ void do_setusercontext(struct passwd *pw) { char uidstr[32], *chroot_path, *tmp; platform_setusercontext(pw); if (platform_privileged_uidswap()) { #ifdef HAVE_LOGIN_CAP if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { perror("unable to set user context"); exit(1); } #else if (setlogin(pw->pw_name) < 0) error("setlogin failed: %s", strerror(errno)); if (setgid(pw->pw_gid) < 0) { perror("setgid"); exit(1); } /* Initialize the group list. */ if (initgroups(pw->pw_name, pw->pw_gid) < 0) { perror("initgroups"); exit(1); } endgrent(); #endif platform_setusercontext_post_groups(pw); 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, "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; in_chroot = 1; } #ifdef HAVE_LOGIN_CAP if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) { perror("unable to set user context (setuser)"); exit(1); } /* * FreeBSD's setusercontext() will not apply the user's * own umask setting unless running with the user's UID. */ (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 (!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); #endif } else if (options.chroot_directory != NULL && strcasecmp(options.chroot_directory, "none") != 0) { fatal("server lacks privileges to chroot to ChrootDirectory"); } if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); } static void do_pwchange(Session *s) { fflush(NULL); fprintf(stderr, "WARNING: Your password has expired.\n"); if (s->ttyfd != -1) { fprintf(stderr, "You must change your password now and log in again!\n"); #ifdef WITH_SELINUX setexeccon(NULL); #endif #ifdef PASSWD_NEEDS_USERNAME execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name, (char *)NULL); #else execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL); #endif perror("passwd"); } else { fprintf(stderr, "Password change required but no TTY available.\n"); } exit(1); } static void child_close_fds(struct ssh *ssh) { extern int auth_sock; if (auth_sock != -1) { close(auth_sock); auth_sock = -1; } if (ssh_packet_get_connection_in(ssh) == ssh_packet_get_connection_out(ssh)) close(ssh_packet_get_connection_in(ssh)); else { 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(ssh); /* * Close any extra file descriptors. Note that there may still be * descriptors left by system functions. They will be closed later. */ endpwent(); /* Stop directing logs to a high-numbered fd before we close it */ log_redirect_stderr_to(NULL); /* * Close any extra open file descriptors so that we don't have them * hanging around in clients. Note that we want to do this after * initgroups, because at least on Solaris 2.3 it leaves file * descriptors open. */ closefrom(STDERR_FILENO + 1); } /* * Performs common processing for the child, such as setting up the * environment, closing extra file descriptors, setting the user and group * ids, and executing the command or shell. */ #define ARGV_MAX 10 void do_child(struct ssh *ssh, Session *s, const char *command) { extern char **environ; 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 keys from memory */ ssh_packet_clear_keys(ssh); /* Force a password change */ if (s->authctxt->force_pwchange) { do_setusercontext(pw); child_close_fds(ssh); do_pwchange(s); exit(1); } /* * Login(1) does this as well, and it needs uid 0 for the "-h" * switch, so we let login(1) to this for us. */ #ifdef HAVE_OSF_SIA 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(); #endif /* HAVE_OSF_SIA */ #ifdef USE_PAM if (options.use_pam && !is_pam_session_open()) { debug3("PAM session not opened, exiting"); display_loginmsg(); exit(254); } #endif /* * Get the shell from the password data. An empty shell field is * legal, and means /bin/sh. */ shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; /* * Make sure $SHELL points to the shell from the password file, * even if shell is overridden from login.conf */ env = do_setup_env(ssh, s, shell); #ifdef HAVE_LOGIN_CAP shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); #endif /* * 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 * ssh_remote_ipaddr there. */ child_close_fds(ssh); /* * Must take new environment into use so that .ssh/rc, * /etc/ssh/sshrc and xauth are run in the proper environment. */ environ = env; #if defined(KRB5) && defined(USE_AFS) /* * At this point, we check to see if AFS is active and if we have * a valid Kerberos 5 TGT. If so, it seems like a good idea to see * if we can (and need to) extend the ticket into an AFS token. If * we don't do this, we run into potential problems if the user's * home directory is in AFS and it's not world-readable. */ if (options.kerberos_get_afs_token && k_hasafs() && (s->authctxt->krb5_ctx != NULL)) { char cell[64]; debug("Getting AFS token"); k_setpag(); if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0) krb5_afslog(s->authctxt->krb5_ctx, s->authctxt->krb5_fwd_ccache, cell, NULL); krb5_afslog_home(s->authctxt->krb5_ctx, s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir); } #endif /* Change current directory to the user's home directory. */ 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 || !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); do_rc_files(ssh, s, shell); /* restore SIGPIPE for child */ 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); } else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) { extern int optind, optreset; int i; char *p, *args; setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME); args = xstrdup(command ? command : "sftp-server"); for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " "))) if (i < ARGV_MAX - 1) argv[i++] = p; argv[i] = NULL; optind = optreset = 1; __progname = argv[0]; #ifdef WITH_SELINUX ssh_selinux_change_context("sftpd_t"); #endif exit(sftp_server_main(i, argv, s->pw)); } fflush(NULL); /* Get the last component of the shell name. */ if ((shell0 = strrchr(shell, '/')) != NULL) shell0++; else shell0 = shell; /* * If we have no command, execute the shell. In this case, the shell * name to be passed in argv[0] is preceded by '-' to indicate that * this is a login shell. */ if (!command) { char argv0[256]; /* Start the shell. Set initial character to '-'. */ argv0[0] = '-'; if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1) >= sizeof(argv0) - 1) { errno = EINVAL; perror(shell); exit(1); } /* Execute the shell. */ argv[0] = argv0; argv[1] = NULL; execve(shell, argv, env); /* Executing the shell failed. */ perror(shell); exit(1); } /* * Execute the command using the user's shell. This uses the -c * option to execute the command. */ argv[0] = (char *) shell0; argv[1] = "-c"; argv[2] = (char *) command; argv[3] = NULL; execve(shell, argv, env); perror(shell); exit(1); } void session_unused(int id) { debug3_f("session id %d unused", id); if (id >= options.max_sessions || id >= sessions_nalloc) { fatal_f("insane session id %d (max %d nalloc %d)", id, options.max_sessions, sessions_nalloc); } memset(&sessions[id], 0, sizeof(*sessions)); sessions[id].self = id; sessions[id].used = 0; sessions[id].chanid = -1; sessions[id].ptyfd = -1; sessions[id].ttyfd = -1; sessions[id].ptymaster = -1; sessions[id].x11_chanids = NULL; sessions[id].next_unused = sessions_first_unused; sessions_first_unused = id; } Session * session_new(void) { Session *s, *tmp; if (sessions_first_unused == -1) { if (sessions_nalloc >= options.max_sessions) return NULL; debug2_f("allocate (allocated %d max %d)", sessions_nalloc, options.max_sessions); tmp = xrecallocarray(sessions, sessions_nalloc, sessions_nalloc + 1, sizeof(*sessions)); if (tmp == NULL) { error_f("cannot allocate %d sessions", sessions_nalloc + 1); return NULL; } sessions = tmp; session_unused(sessions_nalloc++); } if (sessions_first_unused >= sessions_nalloc || sessions_first_unused < 0) { fatal_f("insane first_unused %d max %d nalloc %d", sessions_first_unused, options.max_sessions, sessions_nalloc); } s = &sessions[sessions_first_unused]; if (s->used) fatal_f("session %d already used", sessions_first_unused); sessions_first_unused = s->next_unused; s->used = 1; s->next_unused = -1; debug("session_new: session %d", s->self); return s; } static void session_dump(void) { int i; for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; debug("dump: used %d next_unused %d session %d " "channel %d pid %ld", s->used, s->next_unused, s->self, s->chanid, (long)s->pid); } } int session_open(Authctxt *authctxt, int chanid) { Session *s = session_new(); debug("session_open: channel %d", chanid); if (s == NULL) { error("no more sessions"); return 0; } s->authctxt = authctxt; s->pw = authctxt->pw; if (s->pw == NULL || !authctxt->valid) fatal("no user for session %d", s->self); debug("session_open: session %d: link with channel %d", s->self, chanid); s->chanid = chanid; return 1; } Session * session_by_tty(char *tty) { int i; for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { debug("session_by_tty: session %d tty %s", i, tty); return s; } } debug("session_by_tty: unknown tty %.100s", tty); session_dump(); return NULL; } static Session * session_by_channel(int id) { int i; for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->chanid == id) { debug("session_by_channel: session %d channel %d", i, id); return s; } } debug("session_by_channel: unknown channel %d", id); session_dump(); return NULL; } static Session * session_by_x11_channel(int id) { int i, j; for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->x11_chanids == NULL || !s->used) continue; for (j = 0; s->x11_chanids[j] != -1; j++) { if (s->x11_chanids[j] == id) { debug("session_by_x11_channel: session %d " "channel %d", s->self, id); return s; } } } debug("session_by_x11_channel: unknown channel %d", id); session_dump(); return NULL; } static Session * session_by_pid(pid_t pid) { int i; debug("session_by_pid: pid %ld", (long)pid); for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->pid == pid) return s; } error("session_by_pid: unknown pid %ld", (long)pid); session_dump(); return NULL; } static int session_window_change_req(struct ssh *ssh, Session *s) { 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(struct ssh *ssh, Session *s) { int r; if (!auth_opts->permit_pty_flag || !options.permit_tty) { debug("Allocating a pty not permitted for this connection."); return 0; } if (s->ttyfd != -1) { ssh_packet_disconnect(ssh, "Protocol error: you already have a pty."); return 0; } 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); s->term = NULL; } /* Allocate a pty and open it. */ debug("Allocating pty."); if (!mm_pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) { free(s->term); s->term = NULL; s->ptyfd = -1; s->ttyfd = -1; error("session_pty_req: session %d alloc failed", s->self); return 0; } debug("session_pty_req: session %d alloc %s", s->self, s->tty); ssh_tty_parse_modes(ssh, s->ttyfd); if ((r = sshpkt_get_end(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); /* Set window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); session_proctitle(s); return 1; } static int session_subsystem_req(struct ssh *ssh, Session *s) { struct stat st; int r, success = 0; char *prog, *cmd, *type; u_int i; 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); for (i = 0; i < options.num_subsystems; i++) { if (strcmp(s->subsys, options.subsystem_name[i]) == 0) { prog = options.subsystem_command[i]; cmd = options.subsystem_args[i]; if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) { s->is_subsystem = SUBSYSTEM_INT_SFTP; debug("subsystem: %s", prog); } else { if (stat(prog, &st) == -1) debug("subsystem: cannot stat %s: %s", prog, strerror(errno)); s->is_subsystem = SUBSYSTEM_EXT; debug("subsystem: exec() %s", cmd); } xasprintf(&type, "session:subsystem:%s", options.subsystem_name[i]); channel_set_xtype(ssh, s->chanid, type); free(type); success = do_exec(ssh, s, cmd) == 0; break; } } if (!success) logit("subsystem request for %.100s by user %s failed, " "subsystem not found", s->subsys, s->pw->pw_name); return success; } static int session_x11_req(struct ssh *ssh, Session *s) { 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; } 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; 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); s->auth_proto = NULL; s->auth_data = NULL; } return success; } static int session_shell_req(struct ssh *ssh, Session *s) { int r; if ((r = sshpkt_get_end(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); channel_set_xtype(ssh, s->chanid, "session:shell"); return do_exec(ssh, s, NULL) == 0; } static int session_exec_req(struct ssh *ssh, Session *s) { 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__); channel_set_xtype(ssh, s->chanid, "session:command"); success = do_exec(ssh, s, command) == 0; free(command); return success; } static int session_break_req(struct ssh *ssh, Session *s) { int r; 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) == -1) return 0; return 1; } static int session_env_req(struct ssh *ssh, Session *s) { char *name, *val; u_int i; int r; 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) { debug2("Ignoring env request %s: too many env vars", name); goto fail; } 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 = 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++; return (1); } } debug2("Ignoring env request %s: disallowed name", name); fail: free(name); free(val); 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 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_fr(r, "parse"); goto out; } if ((sig = name2sig(signame)) == -1) { error_f("unsupported signal \"%s\"", signame); goto out; } if (s->pid <= 0) { error_f("no pid for session %d", s->self); goto out; } if (s->forced || s->is_subsystem) { error_f("refusing to send signal %s to %s session", signame, s->forced ? "forced-command" : "subsystem"); goto out; } debug_f("signal %s, killpg(%ld, %d)", signame, (long)s->pid, sig); temporarily_use_uid(s->pw); r = killpg(s->pid, sig); restore_uid(); if (r != 0) { error_f("killpg(%ld, %d): %s", (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; 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 || options.disable_forwarding) { debug_f("agent forwarding disabled"); return 0; } if (called) { return 0; } else { called = 1; return auth_input_request_forwarding(ssh, s->pw); } } int 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_f("no session %d req %.100s", c->self, rtype); return 0; } debug_f("session %d req %s", s->self, rtype); /* * a session is in LARVAL state until a shell, a command * or a subsystem is executed */ if (c->type == SSH_CHANNEL_LARVAL) { if (strcmp(rtype, "shell") == 0) { success = session_shell_req(ssh, s); } else if (strcmp(rtype, "exec") == 0) { success = session_exec_req(ssh, s); } else if (strcmp(rtype, "pty-req") == 0) { success = session_pty_req(ssh, s); } else if (strcmp(rtype, "x11-req") == 0) { success = session_x11_req(ssh, s); } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { success = session_auth_agent_req(ssh, s); } else if (strcmp(rtype, "subsystem") == 0) { success = session_subsystem_req(ssh, s); } else if (strcmp(rtype, "env") == 0) { success = session_env_req(ssh, s); } } if (strcmp(rtype, "window-change") == 0) { success = session_window_change_req(ssh, s); } else if (strcmp(rtype, "break") == 0) { success = session_break_req(ssh, s); } else if (strcmp(rtype, "signal") == 0) { success = session_signal_req(ssh, s); } return success; } void session_set_fds(struct ssh *ssh, Session *s, int fdin, int fdout, int fderr, int ignore_fderr, int is_tty) { /* * 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(ssh, s->chanid, fdout, fdin, fderr, ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, 1, is_tty, CHAN_SES_WINDOW_DEFAULT); } /* * Function to perform pty cleanup. Also called if we get aborted abnormally * (e.g., due to a dropped connection). */ void session_pty_cleanup2(Session *s) { if (s == NULL) { error_f("no session"); return; } if (s->ttyfd == -1) return; debug_f("session %d release %s", s->self, s->tty); /* Record that the user has logged out. */ if (s->pid != 0) record_logout(s->pid, s->tty, s->pw->pw_name); /* Release the pseudo-tty. */ if (getuid() == 0) pty_release(s->tty); /* * Close the server side of the socket pairs. We must do this after * 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) == -1) error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; } void session_pty_cleanup(Session *s) { mm_session_pty_cleanup2(s); } static char * sig2name(int sig) { #define SSH_SIG(x) if (sig == SIG ## x) return #x SSH_SIG(ABRT); SSH_SIG(ALRM); SSH_SIG(FPE); SSH_SIG(HUP); SSH_SIG(ILL); SSH_SIG(INT); SSH_SIG(KILL); SSH_SIG(PIPE); SSH_SIG(QUIT); SSH_SIG(SEGV); SSH_SIG(TERM); SSH_SIG(USR1); SSH_SIG(USR2); #undef SSH_SIG return "SIG@openssh.com"; } static void session_close_x11(struct ssh *ssh, int id) { Channel *c; if ((c = channel_by_id(ssh, id)) == NULL) { debug_f("x11 channel %d missing", id); } else { /* Detach X11 listener */ debug_f("detach x11 channel %d", id); channel_cancel_cleanup(ssh, id); if (c->ostate != CHAN_OUTPUT_CLOSED) chan_mark_dead(ssh, c); } } static void session_close_single_x11(struct ssh *ssh, int id, int force, void *arg) { Session *s; u_int i; debug3_f("channel %d", id); channel_cancel_cleanup(ssh, id); if ((s = session_by_x11_channel(id)) == NULL) fatal_f("no x11 channel %d", id); for (i = 0; s->x11_chanids[i] != -1; i++) { debug_f("session %d: closing channel %d", s->self, s->x11_chanids[i]); /* * The channel "id" is already closing, but make sure we * close all of its siblings. */ if (s->x11_chanids[i] != id) session_close_x11(ssh, s->x11_chanids[i]); } free(s->x11_chanids); s->x11_chanids = NULL; free(s->display); s->display = NULL; free(s->auth_proto); s->auth_proto = NULL; free(s->auth_data); s->auth_data = NULL; free(s->auth_display); s->auth_display = NULL; } static void session_exit_message(struct ssh *ssh, Session *s, int status) { Channel *c; int r; char *note = NULL; if ((c = channel_lookup(ssh, s->chanid)) == NULL) fatal_f("session %d: no channel %d", s->self, s->chanid); if (WIFEXITED(status)) { 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__); xasprintf(¬e, "exit %d", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { 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__); xasprintf(¬e, "signal %d%s", WTERMSIG(status), WCOREDUMP(status) ? " core dumped" : ""); } else { /* Some weird exit cause. Just exit. */ ssh_packet_disconnect(ssh, "wait returned status %04x.", status); } debug_f("session %d channel %d pid %ld %s", s->self, s->chanid, (long)s->pid, note == NULL ? "UNKNOWN" : note); free(note); /* disconnect channel */ debug_f("release channel %d", s->chanid); /* * Adjust cleanup callback attachment to send close messages when * the channel gets EOF. The session will be then be closed * by session_close_by_channel when the child sessions close their fds. */ channel_register_cleanup(ssh, c->self, session_close_by_channel, 1); /* * emulate a write failure with 'chan_write_failed', nobody will be * interested in data we write. * Note that we must not call 'chan_read_failed', since there could * be some more data waiting in the pipe. */ if (c->ostate != CHAN_OUTPUT_CLOSED) chan_write_failed(ssh, c); } void session_close(struct ssh *ssh, Session *s) { u_int i; 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); free(s->display); free(s->x11_chanids); free(s->auth_display); free(s->auth_data); free(s->auth_proto); free(s->subsys); if (s->env != NULL) { for (i = 0; i < s->num_env; i++) { free(s->env[i].name); free(s->env[i].val); } free(s->env); } session_proctitle(s); session_unused(s->self); } void session_close_by_pid(struct ssh *ssh, pid_t pid, int status) { Session *s = session_by_pid(pid); if (s == NULL) { debug_f("no session for pid %ld", (long)pid); return; } if (s->chanid != -1) session_exit_message(ssh, s, status); if (s->ttyfd != -1) session_pty_cleanup(s); s->pid = 0; } /* * this is called when a channel dies before * the session 'child' itself dies */ void session_close_by_channel(struct ssh *ssh, int id, int force, void *arg) { Session *s = session_by_channel(id); u_int i; if (s == NULL) { debug_f("no session for id %d", id); return; } debug_f("channel %d child %ld", id, (long)s->pid); if (s->pid != 0) { debug_f("channel %d: has child, ttyfd %d", id, s->ttyfd); /* * delay detach of session (unless this is a forced close), * but release pty, since the fd's to the child are already * closed */ if (s->ttyfd != -1) session_pty_cleanup(s); if (!force) return; } /* detach by removing callback */ 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(ssh, s->x11_chanids[i]); s->x11_chanids[i] = -1; } } s->chanid = -1; session_close(ssh, s); } void session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *)) { int i; for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used) { if (closefunc != NULL) closefunc(s); else session_close(ssh, s); } } } static char * session_tty_list(void) { static char buf[1024]; int i; char *cp; buf[0] = '\0'; for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1) { if (strncmp(s->tty, "/dev/", 5) != 0) { cp = strrchr(s->tty, '/'); cp = (cp == NULL) ? s->tty : cp + 1; } else cp = s->tty + 5; if (buf[0] != '\0') strlcat(buf, ",", sizeof buf); strlcat(buf, cp, sizeof buf); } } if (buf[0] == '\0') strlcpy(buf, "notty", sizeof buf); return buf; } void session_proctitle(Session *s) { if (s->pw == NULL) error("no user for session %d", s->self); else setproctitle("%s@%s", s->pw->pw_name, session_tty_list()); } int 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 (!auth_opts->permit_x11_forwarding_flag) { ssh_packet_send_debug(ssh, "X11 forwarding disabled by key options."); return 0; } if (!options.x11_forwarding || options.disable_forwarding) { debug("X11 forwarding disabled in server configuration file."); return 0; } if (options.xauth_location == NULL || (stat(options.xauth_location, &st) == -1)) { 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(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(ssh, s->x11_chanids[i], session_close_single_x11, 0); } /* Set up a suitable value for the DISPLAY variable. */ if (gethostname(hostname, sizeof(hostname)) == -1) fatal("gethostname: %.100s", strerror(errno)); /* * auth_display must be used as the displayname when the * authorization entry is added with xauth(1). This will be * different than the DISPLAY string for localhost displays. */ if (options.x11_use_localhost) { snprintf(display, sizeof display, "localhost:%u.%u", s->display_number, s->screen); snprintf(auth_display, sizeof auth_display, "unix:%u.%u", s->display_number, s->screen); s->display = xstrdup(display); s->auth_display = xstrdup(auth_display); } else { #ifdef IPADDR_IN_DISPLAY struct hostent *he; struct in_addr my_addr; he = gethostbyname(hostname); if (he == NULL) { error("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)); snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr), s->display_number, s->screen); #else snprintf(display, sizeof display, "%.400s:%u.%u", hostname, s->display_number, s->screen); #endif s->display = xstrdup(display); s->auth_display = xstrdup(display); } return 1; } static void do_authenticated2(struct ssh *ssh, Authctxt *authctxt) { server_loop2(ssh, authctxt); } void do_cleanup(struct ssh *ssh, Authctxt *authctxt) { static int called = 0; debug("do_cleanup"); /* no cleanup if we're in the child for login shell */ if (is_child) return; /* avoid double cleanup */ if (called) return; called = 1; if (authctxt == NULL) return; #ifdef USE_PAM if (options.use_pam) { sshpam_cleanup(); sshpam_thread_cleanup(); } #endif if (!authctxt->authenticated) return; #ifdef KRB5 if (options.kerberos_ticket_cleanup && authctxt->krb5_ctx) krb5_cleanup_proc(authctxt); #endif #ifdef GSSAPI 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 (mm_is_monitor()) 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; } openssh-10.0p1/PaxHeaders.10889/session.h100644 001750 001750 0000000003614775415623 0015010xustar0030 atime=1744182234.760570483 openssh-10.0p1/session.h010064400017500001750000000051451477541562300134000ustar00djmdjm/* $OpenBSD: session.h,v 1.37 2023/01/06 02:39:59 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 SESSION_H #define SESSION_H #define TTYSZ 64 typedef struct Session Session; struct Session { int used; int self; int next_unused; struct passwd *pw; Authctxt *authctxt; pid_t pid; int forced; /* tty */ char *term; int ptyfd, ttyfd, ptymaster; u_int row, col, xpixel, ypixel; char tty[TTYSZ]; /* X11 */ u_int display_number; char *display; u_int screen; char *auth_display; char *auth_proto; char *auth_data; int single_connection; int chanid; int *x11_chanids; int is_subsystem; char *subsys; u_int num_env; struct { char *name; char *val; } *env; }; 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(struct ssh *, Channel *, const char *); void session_close_by_pid(struct ssh *ssh, pid_t, int); void session_close_by_channel(struct ssh *, int, 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(struct ssh *, Session *); void do_setusercontext(struct passwd *); const char *session_get_remote_name_or_ip(struct ssh *, u_int, int); #endif openssh-10.0p1/PaxHeaders.10889/sftp-client.c100644 001750 001750 0000000003514775415623 0015547xustar0029 atime=1744182234.76838302 openssh-10.0p1/sftp-client.c010064400017500001750000002360571477541562300141500ustar00djmdjm/* $OpenBSD: sftp-client.c,v 1.177 2025/03/11 07:48:51 dtucker Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* XXX: memleaks */ /* XXX: signed vs unsigned */ /* XXX: remove all logging, only return status codes */ /* XXX: copy between two remote sites */ #include "includes.h" #include #ifdef HAVE_SYS_STATVFS_H #include #endif #include "openbsd-compat/sys-queue.h" #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #include #include #include #include #include #include #include #include "xmalloc.h" #include "ssherr.h" #include "sshbuf.h" #include "log.h" #include "atomicio.h" #include "progressmeter.h" #include "misc.h" #include "utf8.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" extern volatile sig_atomic_t interrupted; extern int showprogress; /* Default size of buffer for up/download (fix sftp.1 scp.1 if changed) */ #define DEFAULT_COPY_BUFLEN 32768 /* Default number of concurrent xfer requests (fix sftp.1 scp.1 if changed) */ #define DEFAULT_NUM_REQUESTS 64 /* Minimum amount of data to read at a time */ #define MIN_READ_SIZE 512 /* Maximum depth to descend in directory trees */ #define MAX_DIR_DEPTH 64 /* Directory separator characters */ #ifdef HAVE_CYGWIN # define SFTP_DIRECTORY_CHARS "/\\" #else /* HAVE_CYGWIN */ # define SFTP_DIRECTORY_CHARS "/" #endif /* HAVE_CYGWIN */ struct sftp_conn { int fd_in; int fd_out; u_int download_buflen; u_int upload_buflen; u_int num_requests; u_int version; u_int msg_id; #define SFTP_EXT_POSIX_RENAME 0x00000001 #define SFTP_EXT_STATVFS 0x00000002 #define SFTP_EXT_FSTATVFS 0x00000004 #define SFTP_EXT_HARDLINK 0x00000008 #define SFTP_EXT_FSYNC 0x00000010 #define SFTP_EXT_LSETSTAT 0x00000020 #define SFTP_EXT_LIMITS 0x00000040 #define SFTP_EXT_PATH_EXPAND 0x00000080 #define SFTP_EXT_COPY_DATA 0x00000100 #define SFTP_EXT_GETUSERSGROUPS_BY_ID 0x00000200 u_int exts; u_int64_t limit_kbps; struct bwlimit bwlimit_in, bwlimit_out; }; /* Tracks in-progress requests during file transfers */ struct request { u_int id; size_t len; u_int64_t offset; TAILQ_ENTRY(request) tq; }; TAILQ_HEAD(requests, request); static u_char * get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, const char *errfmt, ...) __attribute__((format(printf, 4, 5))); static struct request * request_enqueue(struct requests *requests, u_int id, size_t len, uint64_t offset) { struct request *req; req = xcalloc(1, sizeof(*req)); req->id = id; req->len = len; req->offset = offset; TAILQ_INSERT_TAIL(requests, req, tq); return req; } static struct request * request_find(struct requests *requests, u_int id) { struct request *req; for (req = TAILQ_FIRST(requests); req != NULL && req->id != id; req = TAILQ_NEXT(req, tq)) ; return req; } static int sftpio(void *_bwlimit, size_t amount) { struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; refresh_progress_meter(0); if (bwlimit != NULL) bandwidth_limit(bwlimit, amount); return 0; } static void send_msg(struct sftp_conn *conn, struct sshbuf *m) { u_char mlen[4]; struct iovec iov[2]; if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) fatal("Outbound message too long %zu", sshbuf_len(m)); /* Send length first */ put_u32(mlen, sshbuf_len(m)); iov[0].iov_base = mlen; iov[0].iov_len = sizeof(mlen); iov[1].iov_base = (u_char *)sshbuf_ptr(m); iov[1].iov_len = sshbuf_len(m); if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) != sshbuf_len(m) + sizeof(mlen)) fatal("Couldn't send packet: %s", strerror(errno)); sshbuf_reset(m); } static void get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) { u_int msg_len; u_char *p; int r; sshbuf_reset(m); if ((r = sshbuf_reserve(m, 4, &p)) != 0) fatal_fr(r, "reserve"); if (atomicio6(read, conn->fd_in, p, 4, sftpio, conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) { if (errno == EPIPE || errno == ECONNRESET) fatal("Connection closed"); else fatal("Couldn't read packet: %s", strerror(errno)); } if ((r = sshbuf_get_u32(m, &msg_len)) != 0) fatal_fr(r, "sshbuf_get_u32"); if (msg_len > SFTP_MAX_MSG_LENGTH) { do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL, "Received message too long %u", msg_len); fatal("Ensure the remote shell produces no output " "for non-interactive sessions."); } if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) fatal_fr(r, "reserve"); if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != msg_len) { if (errno == EPIPE) fatal("Connection closed"); else fatal("Read packet: %s", strerror(errno)); } } static void get_msg(struct sftp_conn *conn, struct sshbuf *m) { get_msg_extended(conn, m, 0); } static void send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, u_int len) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, code)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, s, len)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); sshbuf_free(msg); } static void send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, const void *s, u_int len, Attrib *a) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, code)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, s, len)) != 0 || (r = encode_attrib(msg, a)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o", conn->fd_out, code, id, a->flags, a->perm); sshbuf_free(msg); } static u_int get_status(struct sftp_conn *conn, u_int expected_id) { struct sshbuf *msg; u_char type; u_int id, status; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "compose"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type != SSH2_FXP_STATUS) fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", SSH2_FXP_STATUS, type); if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse"); sshbuf_free(msg); debug3("SSH2_FXP_STATUS %u", status); return status; } static u_char * get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, const char *errfmt, ...) { struct sshbuf *msg; u_int id, status; u_char type; u_char *handle; char errmsg[256]; va_list args; int r; va_start(args, errfmt); if (errfmt != NULL) vsnprintf(errmsg, sizeof(errmsg), errfmt, args); va_end(args); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); if (id != expected_id) fatal("%s: ID mismatch (%u != %u)", errfmt == NULL ? __func__ : errmsg, id, expected_id); if (type == SSH2_FXP_STATUS) { if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (errfmt != NULL) error("%s: %s", errmsg, fx2txt(status)); sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_HANDLE) fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); if ((r = sshbuf_get_string(msg, &handle, len)) != 0) fatal_fr(r, "parse handle"); sshbuf_free(msg); return handle; } static int get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, Attrib *a) { struct sshbuf *msg; u_int id; u_char type; int r; Attrib attr; if (a != NULL) memset(a, '\0', sizeof(*a)); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (quiet) debug("stat remote: %s", fx2txt(status)); else error("stat remote: %s", fx2txt(status)); sshbuf_free(msg); return -1; } else if (type != SSH2_FXP_ATTRS) { fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", SSH2_FXP_ATTRS, type); } if ((r = decode_attrib(msg, &attr)) != 0) { error_fr(r, "decode_attrib"); sshbuf_free(msg); return -1; } /* success */ if (a != NULL) *a = attr; debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o", type, id, attr.flags, attr.perm); sshbuf_free(msg); return 0; } static int get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, u_int expected_id, int quiet) { struct sshbuf *msg; u_char type; u_int id; u_int64_t flag; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received statvfs reply T:%u I:%u", type, id); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (quiet) debug("remote statvfs: %s", fx2txt(status)); else error("remote statvfs: %s", fx2txt(status)); sshbuf_free(msg); return -1; } else if (type != SSH2_FXP_EXTENDED_REPLY) { fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", SSH2_FXP_EXTENDED_REPLY, type); } memset(st, 0, sizeof(*st)); if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || (r = sshbuf_get_u64(msg, &flag)) != 0 || (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) fatal_fr(r, "parse statvfs"); st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; sshbuf_free(msg); return 0; } struct sftp_conn * sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, u_int64_t limit_kbps) { u_char type; struct sshbuf *msg; struct sftp_conn *ret; int r; ret = xcalloc(1, sizeof(*ret)); ret->msg_id = 1; ret->fd_in = fd_in; ret->fd_out = fd_out; ret->download_buflen = ret->upload_buflen = transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN; ret->num_requests = num_requests ? num_requests : DEFAULT_NUM_REQUESTS; ret->exts = 0; ret->limit_kbps = 0; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) fatal_fr(r, "parse"); send_msg(ret, msg); get_msg_extended(ret, msg, 1); /* Expecting a VERSION reply */ if ((r = sshbuf_get_u8(msg, &type)) != 0) fatal_fr(r, "parse type"); if (type != SSH2_FXP_VERSION) { error("Invalid packet back from SSH2_FXP_INIT (type %u)", type); sshbuf_free(msg); free(ret); return(NULL); } if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) fatal_fr(r, "parse version"); debug2("Remote version: %u", ret->version); /* Check for extensions */ while (sshbuf_len(msg) > 0) { char *name; u_char *value; size_t vlen; int known = 0; if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || (r = sshbuf_get_string(msg, &value, &vlen)) != 0) fatal_fr(r, "parse extension"); if (strcmp(name, "posix-rename@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_POSIX_RENAME; known = 1; } else if (strcmp(name, "statvfs@openssh.com") == 0 && strcmp((char *)value, "2") == 0) { ret->exts |= SFTP_EXT_STATVFS; known = 1; } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && strcmp((char *)value, "2") == 0) { ret->exts |= SFTP_EXT_FSTATVFS; known = 1; } else if (strcmp(name, "hardlink@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_HARDLINK; known = 1; } else if (strcmp(name, "fsync@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_FSYNC; known = 1; } else if (strcmp(name, "lsetstat@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_LSETSTAT; known = 1; } else if (strcmp(name, "limits@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_LIMITS; known = 1; } else if (strcmp(name, "expand-path@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_PATH_EXPAND; known = 1; } else if (strcmp(name, "copy-data") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_COPY_DATA; known = 1; } else if (strcmp(name, "users-groups-by-id@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_GETUSERSGROUPS_BY_ID; known = 1; } if (known) { debug2("Server supports extension \"%s\" revision %s", name, value); } else { debug2("Unrecognised server extension \"%s\"", name); } free(name); free(value); } sshbuf_free(msg); /* Query the server for its limits */ if (ret->exts & SFTP_EXT_LIMITS) { struct sftp_limits limits; if (sftp_get_limits(ret, &limits) != 0) fatal_f("limits failed"); /* If the caller did not specify, find a good value */ if (transfer_buflen == 0) { ret->download_buflen = MINIMUM(limits.read_length, SFTP_MAX_MSG_LENGTH - 1024); ret->upload_buflen = MINIMUM(limits.write_length, SFTP_MAX_MSG_LENGTH - 1024); ret->download_buflen = MAXIMUM(ret->download_buflen, 64); ret->upload_buflen = MAXIMUM(ret->upload_buflen, 64); debug3("server upload/download buffer sizes " "%llu / %llu; using %u / %u", (unsigned long long)limits.write_length, (unsigned long long)limits.read_length, ret->upload_buflen, ret->download_buflen); } /* Use the server limit to scale down our value only */ if (num_requests == 0 && limits.open_handles) { ret->num_requests = MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles); if (ret->num_requests == 0) ret->num_requests = 1; debug3("server handle limit %llu; using %u", (unsigned long long)limits.open_handles, ret->num_requests); } } /* Some filexfer v.0 servers don't support large packets */ if (ret->version == 0) { ret->download_buflen = MINIMUM(ret->download_buflen, 20480); ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480); } ret->limit_kbps = limit_kbps; if (ret->limit_kbps > 0) { bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps, ret->download_buflen); bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps, ret->upload_buflen); } return ret; } u_int sftp_proto_version(struct sftp_conn *conn) { return conn->version; } int sftp_get_limits(struct sftp_conn *conn, struct sftp_limits *limits) { u_int id, msg_id; u_char type; struct sshbuf *msg; int r; if ((conn->exts & SFTP_EXT_LIMITS) == 0) { error("Server does not support limits@openssh.com extension"); return -1; } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message limits@openssh.com I:%u", id); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &msg_id)) != 0) fatal_fr(r, "parse"); debug3("Received limits reply T:%u I:%u", type, msg_id); if (id != msg_id) fatal("ID mismatch (%u != %u)", msg_id, id); if (type != SSH2_FXP_EXTENDED_REPLY) { debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", SSH2_FXP_EXTENDED_REPLY, type); /* Disable the limits extension */ conn->exts &= ~SFTP_EXT_LIMITS; sshbuf_free(msg); return -1; } memset(limits, 0, sizeof(*limits)); if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 || (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 || (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 || (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0) fatal_fr(r, "parse limits"); sshbuf_free(msg); return 0; } int sftp_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) { u_int id, status; struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0) fatal_fr(r, "parse"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_CLOSE I:%u", id); status = get_status(conn, id); if (status != SSH2_FX_OK) error("close remote: %s", fx2txt(status)); sshbuf_free(msg); return status == SSH2_FX_OK ? 0 : -1; } static int sftp_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, SFTP_DIRENT ***dir) { struct sshbuf *msg; u_int count, id, i, expected_id, ents = 0; size_t handle_len; u_char type, *handle; int status = SSH2_FX_FAILURE; int r; if (dir) *dir = NULL; id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0) fatal_fr(r, "compose OPENDIR"); send_msg(conn, msg); handle = get_handle(conn, id, &handle_len, "remote readdir(\"%s\")", path); if (handle == NULL) { sshbuf_free(msg); return -1; } if (dir) { ents = 0; *dir = xcalloc(1, sizeof(**dir)); (*dir)[0] = NULL; } for (; !interrupted;) { id = expected_id = conn->msg_id++; debug3("Sending SSH2_FXP_READDIR I:%u", id); sshbuf_reset(msg); if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0) fatal_fr(r, "compose READDIR"); send_msg(conn, msg); sshbuf_reset(msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received reply T:%u I:%u", type, id); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int rstatus; if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) fatal_fr(r, "parse status"); debug3("Received SSH2_FXP_STATUS %d", rstatus); if (rstatus == SSH2_FX_EOF) break; error("Couldn't read directory: %s", fx2txt(rstatus)); goto out; } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) fatal_fr(r, "parse count"); if (count > SSHBUF_SIZE_MAX) fatal_f("nonsensical number of entries"); if (count == 0) break; debug3("Received %d SSH2_FXP_NAME responses", count); for (i = 0; i < count; i++) { char *filename, *longname; Attrib a; if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0) fatal_fr(r, "parse filenames"); if ((r = decode_attrib(msg, &a)) != 0) { error_fr(r, "couldn't decode attrib"); free(filename); free(longname); goto out; } if (print_flag) mprintf("%s\n", longname); /* * Directory entries should never contain '/' * These can be used to attack recursive ops * (e.g. send '../../../../etc/passwd') */ if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) { error("Server sent suspect path \"%s\" " "during readdir of \"%s\"", filename, path); } else if (dir) { *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); (*dir)[ents] = xcalloc(1, sizeof(***dir)); (*dir)[ents]->filename = xstrdup(filename); (*dir)[ents]->longname = xstrdup(longname); memcpy(&(*dir)[ents]->a, &a, sizeof(a)); (*dir)[++ents] = NULL; } free(filename); free(longname); } } status = 0; out: sshbuf_free(msg); sftp_close(conn, handle, handle_len); free(handle); if (status != 0 && dir != NULL) { /* Don't return results on error */ sftp_free_dirents(*dir); *dir = NULL; } else if (interrupted && dir != NULL && *dir != NULL) { /* Don't return partial matches on interrupt */ sftp_free_dirents(*dir); *dir = xcalloc(1, sizeof(**dir)); **dir = NULL; } return status == SSH2_FX_OK ? 0 : -1; } int sftp_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) { return sftp_lsreaddir(conn, path, 0, dir); } void sftp_free_dirents(SFTP_DIRENT **s) { int i; if (s == NULL) return; for (i = 0; s[i]; i++) { free(s[i]->filename); free(s[i]->longname); free(s[i]); } free(s); } int sftp_rm(struct sftp_conn *conn, const char *path) { u_int status, id; debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote delete %s: %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) { u_int status, id; debug2("Sending SSH2_FXP_MKDIR \"%s\"", path); id = conn->msg_id++; send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, strlen(path), a); status = get_status(conn, id); if (status != SSH2_FX_OK && print_flag) error("remote mkdir \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_rmdir(struct sftp_conn *conn, const char *path) { u_int status, id; debug2("Sending SSH2_FXP_RMDIR \"%s\"", path); id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_RMDIR, path, strlen(path)); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote rmdir \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_stat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a) { u_int id; debug2("Sending SSH2_FXP_STAT \"%s\"", path); id = conn->msg_id++; send_string_request(conn, id, conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, path, strlen(path)); return get_decode_stat(conn, id, quiet, a); } int sftp_lstat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a) { u_int id; if (conn->version == 0) { do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, "Server version does not support lstat operation"); return sftp_stat(conn, path, quiet, a); } id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_LSTAT, path, strlen(path)); return get_decode_stat(conn, id, quiet, a); } #ifdef notyet int sftp_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, int quiet, Attrib *a) { u_int id; debug2("Sending SSH2_FXP_FSTAT \"%s\""); id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_FSTAT, handle, handle_len); return get_decode_stat(conn, id, quiet, a); } #endif int sftp_setstat(struct sftp_conn *conn, const char *path, Attrib *a) { u_int status, id; debug2("Sending SSH2_FXP_SETSTAT \"%s\"", path); id = conn->msg_id++; send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, strlen(path), a); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote setstat \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a) { u_int status, id; debug2("Sending SSH2_FXP_FSETSTAT"); id = conn->msg_id++; send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, handle_len, a); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote fsetstat: %s", fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } /* Implements both the realpath and expand-path operations */ static char * sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) { struct sshbuf *msg; u_int expected_id, count, id; char *filename, *longname; Attrib a; u_char type; int r; const char *what = "SSH2_FXP_REALPATH"; if (expand) what = "expand-path@openssh.com"; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); expected_id = id = conn->msg_id++; if (expand) { debug2("Sending SSH2_FXP_EXTENDED(expand-path@openssh.com) " "\"%s\"", path); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "expand-path@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0) fatal_fr(r, "compose %s", what); send_msg(conn, msg); } else { debug2("Sending SSH2_FXP_REALPATH \"%s\"", path); send_string_request(conn, id, SSH2_FXP_REALPATH, path, strlen(path)); } get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; char *errmsg; if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); error("%s %s: %s", expand ? "expand" : "realpath", path, *errmsg == '\0' ? fx2txt(status) : errmsg); free(errmsg); sshbuf_free(msg); return NULL; } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) fatal_fr(r, "parse count"); if (count != 1) fatal("Got multiple names (%d) from %s", count, what); if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || (r = decode_attrib(msg, &a)) != 0) fatal_fr(r, "parse filename/attrib"); debug3("%s %s -> %s", what, path, filename); free(longname); sshbuf_free(msg); return(filename); } char * sftp_realpath(struct sftp_conn *conn, const char *path) { return sftp_realpath_expand(conn, path, 0); } int sftp_can_expand_path(struct sftp_conn *conn) { return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0; } char * sftp_expand_path(struct sftp_conn *conn, const char *path) { if (!sftp_can_expand_path(conn)) { debug3_f("no server support, fallback to realpath"); return sftp_realpath_expand(conn, path, 0); } return sftp_realpath_expand(conn, path, 1); } int sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) { Attrib junk, attr; struct sshbuf *msg; u_char *old_handle, *new_handle; u_int mode, status, id; size_t old_handle_len, new_handle_len; int r; /* Return if the extension is not supported */ if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) { error("Server does not support copy-data extension"); return -1; } /* Make sure the file exists, and we can copy its perms */ if (sftp_stat(conn, oldpath, 0, &attr) != 0) return -1; /* Do not preserve set[ug]id here, as we do not preserve ownership */ if (attr.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { mode = attr.perm & 0777; if (!S_ISREG(attr.perm)) { error("Cannot copy non-regular file: %s", oldpath); return -1; } } else { /* NB: The user's umask will apply to this */ mode = 0666; } /* Set up the new perms for the new file */ attrib_clear(&attr); attr.perm = mode; attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); attrib_clear(&junk); /* Send empty attributes */ /* Open the old file for reading */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || (r = encode_attrib(msg, &junk)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath); sshbuf_reset(msg); old_handle = get_handle(conn, id, &old_handle_len, "remote open(\"%s\")", oldpath); if (old_handle == NULL) { sshbuf_free(msg); return -1; } /* Open the new file for writing */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| SSH2_FXF_TRUNC)) != 0 || (r = encode_attrib(msg, &attr)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath); sshbuf_reset(msg); new_handle = get_handle(conn, id, &new_handle_len, "remote open(\"%s\")", newpath); if (new_handle == NULL) { sshbuf_free(msg); free(old_handle); return -1; } /* Copy the file data */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "copy-data")) != 0 || (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 || (r = sshbuf_put_u64(msg, 0)) != 0 || (r = sshbuf_put_u64(msg, 0)) != 0 || (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 || (r = sshbuf_put_u64(msg, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(conn, msg); debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0", oldpath, newpath); status = get_status(conn, id); if (status != SSH2_FX_OK) error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); /* Clean up everything */ sshbuf_free(msg); sftp_close(conn, old_handle, old_handle_len); sftp_close(conn, new_handle, new_handle_len); free(old_handle); free(new_handle); return status == SSH2_FX_OK ? 0 : -1; } int sftp_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy) { struct sshbuf *msg; u_int status, id; int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Send rename request */ id = conn->msg_id++; if (use_ext) { debug2("Sending SSH2_FXP_EXTENDED(posix-rename@openssh.com) " "\"%s\" to \"%s\"", oldpath, newpath); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0) fatal_fr(r, "compose posix-rename"); } else { debug2("Sending SSH2_FXP_RENAME \"%s\" to \"%s\"", oldpath, newpath); if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0) fatal_fr(r, "compose rename"); } if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0) fatal_fr(r, "compose paths"); send_msg(conn, msg); debug3("Sent message %s \"%s\" -> \"%s\"", use_ext ? "posix-rename@openssh.com" : "SSH2_FXP_RENAME", oldpath, newpath); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote rename \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { struct sshbuf *msg; u_int status, id; int r; if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { error("Server does not support hardlink@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(hardlink@openssh.com) " "\"%s\" to \"%s\"", oldpath, newpath); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Send link request */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", oldpath, newpath); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote link \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { struct sshbuf *msg; u_int status, id; int r; if (conn->version < 3) { error("This server does not support the symlink operation"); return(SSH2_FX_OP_UNSUPPORTED); } debug2("Sending SSH2_FXP_SYMLINK \"%s\" to \"%s\"", oldpath, newpath); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Send symlink request */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, newpath); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote symlink file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) { struct sshbuf *msg; u_int status, id; int r; /* Silently return if the extension is not supported */ if ((conn->exts & SFTP_EXT_FSYNC) == 0) return -1; debug2("Sending SSH2_FXP_EXTENDED(fsync@openssh.com)"); /* Send fsync request */ if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fsync@openssh.com I:%u", id); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote fsync: %s", fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } #ifdef notyet char * sftp_readlink(struct sftp_conn *conn, const char *path) { struct sshbuf *msg; u_int expected_id, count, id; char *filename, *longname; Attrib a; u_char type; int r; debug2("Sending SSH2_FXP_READLINK \"%s\"", path); expected_id = id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); error("Couldn't readlink: %s", fx2txt(status)); sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) fatal_fr(r, "parse count"); if (count != 1) fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || (r = decode_attrib(msg, &a)) != 0) fatal_fr(r, "parse filenames/attrib"); debug3("SSH_FXP_READLINK %s -> %s", path, filename); free(longname); sshbuf_free(msg); return filename; } #endif int sftp_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, int quiet) { struct sshbuf *msg; u_int id; int r; if ((conn->exts & SFTP_EXT_STATVFS) == 0) { error("Server does not support statvfs@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(statvfs@openssh.com) \"%s\"", path); id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); return get_decode_statvfs(conn, st, id, quiet); } #ifdef notyet int sftp_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, struct sftp_statvfs *st, int quiet) { struct sshbuf *msg; u_int id; if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { error("Server does not support fstatvfs@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(fstatvfs@openssh.com)"); id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); return get_decode_statvfs(conn, st, id, quiet); } #endif int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) { struct sshbuf *msg; u_int status, id; int r; if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) { error("Server does not support lsetstat@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(lsetstat@openssh.com) \"%s\"", path); id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0 || (r = encode_attrib(msg, a)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote lsetstat \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } static void send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, u_int len, const u_char *handle, u_int handle_len) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || (r = sshbuf_put_u64(msg, offset)) != 0 || (r = sshbuf_put_u32(msg, len)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); } static int send_open(struct sftp_conn *conn, const char *path, const char *tag, u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp) { Attrib junk; u_char *handle; size_t handle_len; struct sshbuf *msg; int r; u_int id; debug2("Sending SSH2_FXP_OPEN \"%s\"", path); *handlep = NULL; *handle_lenp = 0; if (a == NULL) { attrib_clear(&junk); /* Send empty attributes */ a = &junk; } /* Send open request */ if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0 || (r = sshbuf_put_u32(msg, openmode)) != 0 || (r = encode_attrib(msg, a)) != 0) fatal_fr(r, "compose %s open", tag); send_msg(conn, msg); sshbuf_free(msg); debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x", tag, id, path, openmode); if ((handle = get_handle(conn, id, &handle_len, "%s open \"%s\"", tag, path)) == NULL) return -1; /* success */ *handlep = handle; *handle_lenp = handle_len; return 0; } static const char * progress_meter_path(const char *path) { const char *progresspath; if ((progresspath = strrchr(path, '/')) == NULL) return path; progresspath++; if (*progresspath == '\0') return path; return progresspath; } int sftp_download(struct sftp_conn *conn, const char *remote_path, const char *local_path, Attrib *a, int preserve_flag, int resume_flag, int fsync_flag, int inplace_flag) { struct sshbuf *msg; u_char *handle; int local_fd = -1, write_error; int read_error, write_errno, lmodified = 0, reordered = 0, r; u_int64_t offset = 0, size, highwater = 0, maxack = 0; u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; off_t progress_counter; size_t handle_len; struct stat st; struct requests requests; struct request *req; u_char type; Attrib attr; debug2_f("download remote \"%s\" to local \"%s\"", remote_path, local_path); TAILQ_INIT(&requests); if (a == NULL) { if (sftp_stat(conn, remote_path, 0, &attr) != 0) return -1; a = &attr; } /* Do not preserve set[ug]id here, as we do not preserve ownership */ if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) mode = a->perm & 0777; else mode = 0666; if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && (!S_ISREG(a->perm))) { error("download %s: not a regular file", remote_path); return(-1); } if (a->flags & SSH2_FILEXFER_ATTR_SIZE) size = a->size; else size = 0; buflen = conn->download_buflen; /* Send open request */ if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL, &handle, &handle_len) != 0) return -1; local_fd = open(local_path, O_WRONLY | O_CREAT | ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR); if (local_fd == -1) { error("open local \"%s\": %s", local_path, strerror(errno)); goto fail; } if (resume_flag) { if (fstat(local_fd, &st) == -1) { error("stat local \"%s\": %s", local_path, strerror(errno)); goto fail; } if (st.st_size < 0) { error("\"%s\" has negative size", local_path); goto fail; } if ((u_int64_t)st.st_size > size) { error("Unable to resume download of \"%s\": " "local file is larger than remote", local_path); fail: sftp_close(conn, handle, handle_len); free(handle); if (local_fd != -1) close(local_fd); return -1; } offset = highwater = maxack = st.st_size; } /* Read from remote and write to local */ write_error = read_error = write_errno = num_req = 0; max_req = 1; progress_counter = offset; if (showprogress && size != 0) { start_progress_meter(progress_meter_path(remote_path), size, &progress_counter); } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); while (num_req > 0 || max_req > 0) { u_char *data; size_t len; /* * Simulate EOF on interrupt: stop sending new requests and * allow outstanding requests to drain gracefully */ if (interrupted) { if (num_req == 0) /* If we haven't started yet... */ break; max_req = 0; } /* Send some more requests */ while (num_req < max_req) { debug3("Request range %llu -> %llu (%d/%d)", (unsigned long long)offset, (unsigned long long)offset + buflen - 1, num_req, max_req); req = request_enqueue(&requests, conn->msg_id++, buflen, offset); offset += buflen; num_req++; send_read_request(conn, req->id, req->offset, req->len, handle, handle_len); } sshbuf_reset(msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received reply T:%u I:%u R:%d", type, id, max_req); /* Find the request in our queue */ if ((req = request_find(&requests, id)) == NULL) fatal("Unexpected reply %u", id); switch (type) { case SSH2_FXP_STATUS: if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (status != SSH2_FX_EOF) read_error = 1; max_req = 0; TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; break; case SSH2_FXP_DATA: if ((r = sshbuf_get_string(msg, &data, &len)) != 0) fatal_fr(r, "parse data"); debug3("Received data %llu -> %llu", (unsigned long long)req->offset, (unsigned long long)req->offset + len - 1); if (len > req->len) fatal("Received more data than asked for " "%zu > %zu", len, req->len); lmodified = 1; if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || atomicio(vwrite, local_fd, data, len) != len) && !write_error) { write_errno = errno; write_error = 1; max_req = 0; } else { /* * Track both the highest offset acknowledged * and the highest *contiguous* offset * acknowledged. * We'll need the latter for ftruncate()ing * interrupted transfers. */ if (maxack < req->offset + len) maxack = req->offset + len; if (!reordered && req->offset <= highwater) highwater = maxack; else if (!reordered && req->offset > highwater) reordered = 1; } progress_counter += len; free(data); if (len == req->len) { TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; } else { /* Resend the request for the missing data */ debug3("Short data block, re-requesting " "%llu -> %llu (%2d)", (unsigned long long)req->offset + len, (unsigned long long)req->offset + req->len - 1, num_req); req->id = conn->msg_id++; req->len -= len; req->offset += len; send_read_request(conn, req->id, req->offset, req->len, handle, handle_len); /* Reduce the request size */ if (len < buflen) buflen = MAXIMUM(MIN_READ_SIZE, len); } if (max_req > 0) { /* max_req = 0 iff EOF received */ if (size > 0 && offset > size) { /* Only one request at a time * after the expected EOF */ debug3("Finish at %llu (%2d)", (unsigned long long)offset, num_req); max_req = 1; } else if (max_req < conn->num_requests) { ++max_req; } } break; default: fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", SSH2_FXP_DATA, type); } } if (showprogress && size) stop_progress_meter(); /* Sanity check */ if (TAILQ_FIRST(&requests) != NULL) fatal("Transfer complete, but requests still in queue"); if (!read_error && !write_error && !interrupted) { /* we got everything */ highwater = maxack; } /* * Truncate at highest contiguous point to avoid holes on interrupt, * or unconditionally if writing in place. */ if (inplace_flag || read_error || write_error || interrupted) { if (reordered && resume_flag && (read_error || write_error || interrupted)) { error("Unable to resume download of \"%s\": " "server reordered requests", local_path); } debug("truncating at %llu", (unsigned long long)highwater); if (ftruncate(local_fd, highwater) == -1) error("local ftruncate \"%s\": %s", local_path, strerror(errno)); } if (read_error) { error("read remote \"%s\" : %s", remote_path, fx2txt(status)); status = -1; sftp_close(conn, handle, handle_len); } else if (write_error) { error("write local \"%s\": %s", local_path, strerror(write_errno)); status = SSH2_FX_FAILURE; sftp_close(conn, handle, handle_len); } else { if (sftp_close(conn, handle, handle_len) != 0 || interrupted) status = SSH2_FX_FAILURE; else status = SSH2_FX_OK; /* Override umask and utimes if asked */ #ifdef HAVE_FCHMOD if (preserve_flag && fchmod(local_fd, mode) == -1) #else if (preserve_flag && chmod(local_path, mode) == -1) #endif /* HAVE_FCHMOD */ error("local chmod \"%s\": %s", local_path, strerror(errno)); if (preserve_flag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { struct timeval tv[2]; tv[0].tv_sec = a->atime; tv[1].tv_sec = a->mtime; tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(local_path, tv) == -1) error("local set times \"%s\": %s", local_path, strerror(errno)); } if (resume_flag && !lmodified) logit("File \"%s\" was not modified", local_path); else if (fsync_flag) { debug("syncing \"%s\"", local_path); if (fsync(local_fd) == -1) error("local sync \"%s\": %s", local_path, strerror(errno)); } } close(local_fd); sshbuf_free(msg); free(handle); return status == SSH2_FX_OK ? 0 : -1; } static int download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, int depth, Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) { int i, ret = 0; SFTP_DIRENT **dir_entries; char *filename, *new_src = NULL, *new_dst = NULL; mode_t mode = 0777, tmpmode = mode; Attrib *a, ldirattrib, lsym; if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); return -1; } debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst); if (dirattrib == NULL) { if (sftp_stat(conn, src, 1, &ldirattrib) != 0) { error("stat remote \"%s\" directory failed", src); return -1; } dirattrib = &ldirattrib; } if (!S_ISDIR(dirattrib->perm)) { error("\"%s\" is not a directory", src); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) mprintf("Retrieving %s\n", src); if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { mode = dirattrib->perm & 01777; tmpmode = mode | (S_IWUSR|S_IXUSR); } else { debug("download remote \"%s\": server " "did not send permissions", dst); } if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { error("mkdir %s: %s", dst, strerror(errno)); return -1; } if (sftp_readdir(conn, src, &dir_entries) == -1) { error("remote readdir \"%s\" failed", src); return -1; } for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { free(new_dst); free(new_src); filename = dir_entries[i]->filename; new_dst = sftp_path_append(dst, filename); new_src = sftp_path_append(src, filename); a = &dir_entries[i]->a; if (S_ISLNK(a->perm)) { if (!follow_link_flag) { logit("download \"%s\": not a regular file", new_src); continue; } /* Replace the stat contents with the symlink target */ if (sftp_stat(conn, new_src, 1, &lsym) != 0) { logit("remote stat \"%s\" failed", new_src); ret = -1; continue; } a = &lsym; } if (S_ISDIR(a->perm)) { if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (download_dir_internal(conn, new_src, new_dst, depth + 1, a, preserve_flag, print_flag, resume_flag, fsync_flag, follow_link_flag, inplace_flag) == -1) ret = -1; } else if (S_ISREG(a->perm)) { if (sftp_download(conn, new_src, new_dst, a, preserve_flag, resume_flag, fsync_flag, inplace_flag) == -1) { error("Download of file %s to %s failed", new_src, new_dst); ret = -1; } } else logit("download \"%s\": not a regular file", new_src); } free(new_dst); free(new_src); if (preserve_flag) { if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { struct timeval tv[2]; tv[0].tv_sec = dirattrib->atime; tv[1].tv_sec = dirattrib->mtime; tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(dst, tv) == -1) error("local set times on \"%s\": %s", dst, strerror(errno)); } else debug("Server did not send times for directory " "\"%s\"", dst); } if (mode != tmpmode && chmod(dst, mode) == -1) error("local chmod directory \"%s\": %s", dst, strerror(errno)); sftp_free_dirents(dir_entries); return ret; } int sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst, Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) { char *src_canon; int ret; if ((src_canon = sftp_realpath(conn, src)) == NULL) { error("download \"%s\": path canonicalization failed", src); return -1; } ret = download_dir_internal(conn, src_canon, dst, 0, dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, follow_link_flag, inplace_flag); free(src_canon); return ret; } int sftp_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path, int preserve_flag, int resume, int fsync_flag, int inplace_flag) { int r, local_fd; u_int openmode, id, status = SSH2_FX_OK, reordered = 0; off_t offset, progress_counter; u_char type, *handle, *data; struct sshbuf *msg; struct stat sb; Attrib a, t, c; u_int32_t startid, ackid; u_int64_t highwater = 0, maxack = 0; struct request *ack = NULL; struct requests acks; size_t handle_len; debug2_f("upload local \"%s\" to remote \"%s\"", local_path, remote_path); TAILQ_INIT(&acks); if ((local_fd = open(local_path, O_RDONLY)) == -1) { error("open local \"%s\": %s", local_path, strerror(errno)); return(-1); } if (fstat(local_fd, &sb) == -1) { error("fstat local \"%s\": %s", local_path, strerror(errno)); close(local_fd); return(-1); } if (!S_ISREG(sb.st_mode)) { error("local \"%s\" is not a regular file", local_path); close(local_fd); return(-1); } stat_to_attrib(&sb, &a); a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; a.perm &= 0777; if (!preserve_flag) a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; if (resume) { /* Get remote file size if it exists */ if (sftp_stat(conn, remote_path, 0, &c) != 0) { close(local_fd); return -1; } if ((off_t)c.size >= sb.st_size) { error("resume \"%s\": destination file " "same size or larger", local_path); close(local_fd); return -1; } if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) { close(local_fd); return -1; } highwater = c.size; } openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT; if (resume) openmode |= SSH2_FXF_APPEND; else if (!inplace_flag) openmode |= SSH2_FXF_TRUNC; /* Send open request */ if (send_open(conn, remote_path, "dest", openmode, &a, &handle, &handle_len) != 0) { close(local_fd); return -1; } id = conn->msg_id; startid = ackid = id + 1; data = xmalloc(conn->upload_buflen); /* Read from local and write to remote */ offset = progress_counter = (resume ? c.size : 0); if (showprogress) { start_progress_meter(progress_meter_path(local_path), sb.st_size, &progress_counter); } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (;;) { int len; /* * Can't use atomicio here because it returns 0 on EOF, * thus losing the last block of the file. * Simulate an EOF on interrupt, allowing ACKs from the * server to drain. */ if (interrupted || status != SSH2_FX_OK) len = 0; else do len = read(local_fd, data, conn->upload_buflen); while ((len == -1) && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); if (len == -1) { fatal("read local \"%s\": %s", local_path, strerror(errno)); } else if (len != 0) { ack = request_enqueue(&acks, ++id, len, offset); sshbuf_reset(msg); if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || (r = sshbuf_put_u32(msg, ack->id)) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || (r = sshbuf_put_u64(msg, offset)) != 0 || (r = sshbuf_put_string(msg, data, len)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", id, (unsigned long long)offset, len); } else if (TAILQ_FIRST(&acks) == NULL) break; if (ack == NULL) fatal("Unexpected ACK %u", id); if (id == startid || len == 0 || id - ackid >= conn->num_requests) { u_int rid; sshbuf_reset(msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &rid)) != 0) fatal_fr(r, "parse"); if (type != SSH2_FXP_STATUS) fatal("Expected SSH2_FXP_STATUS(%d) packet, " "got %d", SSH2_FXP_STATUS, type); if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); debug3("SSH2_FXP_STATUS %u", status); /* Find the request in our queue */ if ((ack = request_find(&acks, rid)) == NULL) fatal("Can't find request for ID %u", rid); TAILQ_REMOVE(&acks, ack, tq); debug3("In write loop, ack for %u %zu bytes at %lld", ack->id, ack->len, (unsigned long long)ack->offset); ++ackid; progress_counter += ack->len; /* * Track both the highest offset acknowledged and the * highest *contiguous* offset acknowledged. * We'll need the latter for ftruncate()ing * interrupted transfers. */ if (maxack < ack->offset + ack->len) maxack = ack->offset + ack->len; if (!reordered && ack->offset <= highwater) highwater = maxack; else if (!reordered && ack->offset > highwater) { debug3_f("server reordered ACKs"); reordered = 1; } free(ack); } offset += len; if (offset < 0) fatal_f("offset < 0"); } sshbuf_free(msg); if (showprogress) stop_progress_meter(); free(data); if (status == SSH2_FX_OK && !interrupted) { /* we got everything */ highwater = maxack; } if (status != SSH2_FX_OK) { error("write remote \"%s\": %s", remote_path, fx2txt(status)); status = SSH2_FX_FAILURE; } if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { debug("truncating at %llu", (unsigned long long)highwater); attrib_clear(&t); t.flags = SSH2_FILEXFER_ATTR_SIZE; t.size = highwater; sftp_fsetstat(conn, handle, handle_len, &t); } if (close(local_fd) == -1) { error("close local \"%s\": %s", local_path, strerror(errno)); status = SSH2_FX_FAILURE; } /* Override umask and utimes if asked */ if (preserve_flag) sftp_fsetstat(conn, handle, handle_len, &a); if (fsync_flag) (void)sftp_fsync(conn, handle, handle_len); if (sftp_close(conn, handle, handle_len) != 0) status = SSH2_FX_FAILURE; free(handle); return status == SSH2_FX_OK ? 0 : -1; } static int upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, int follow_link_flag, int inplace_flag) { int ret = 0; DIR *dirp; struct dirent *dp; char *filename, *new_src = NULL, *new_dst = NULL; struct stat sb; Attrib a, dirattrib; u_int32_t saved_perm; debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst); if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); return -1; } if (stat(src, &sb) == -1) { error("stat local \"%s\": %s", src, strerror(errno)); return -1; } if (!S_ISDIR(sb.st_mode)) { error("\"%s\" is not a directory", src); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) mprintf("Entering %s\n", src); stat_to_attrib(&sb, &a); a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; a.perm &= 01777; if (!preserve_flag) a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; /* * sftp lacks a portable status value to match errno EEXIST, * so if we get a failure back then we must check whether * the path already existed and is a directory. Ensure we can * write to the directory we create for the duration of the transfer. */ saved_perm = a.perm; a.perm |= (S_IWUSR|S_IXUSR); if (sftp_mkdir(conn, dst, &a, 0) != 0) { if (sftp_stat(conn, dst, 0, &dirattrib) != 0) return -1; if (!S_ISDIR(dirattrib.perm)) { error("\"%s\" exists but is not a directory", dst); return -1; } } a.perm = saved_perm; if ((dirp = opendir(src)) == NULL) { error("local opendir \"%s\": %s", src, strerror(errno)); return -1; } while (((dp = readdir(dirp)) != NULL) && !interrupted) { if (dp->d_ino == 0) continue; free(new_dst); free(new_src); filename = dp->d_name; new_dst = sftp_path_append(dst, filename); new_src = sftp_path_append(src, filename); if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (lstat(new_src, &sb) == -1) { logit("local lstat \"%s\": %s", filename, strerror(errno)); ret = -1; continue; } if (S_ISLNK(sb.st_mode)) { if (!follow_link_flag) { logit("%s: not a regular file", filename); continue; } /* Replace the stat contents with the symlink target */ if (stat(new_src, &sb) == -1) { logit("local stat \"%s\": %s", filename, strerror(errno)); ret = -1; continue; } } if (S_ISDIR(sb.st_mode)) { if (upload_dir_internal(conn, new_src, new_dst, depth + 1, preserve_flag, print_flag, resume, fsync_flag, follow_link_flag, inplace_flag) == -1) ret = -1; } else if (S_ISREG(sb.st_mode)) { if (sftp_upload(conn, new_src, new_dst, preserve_flag, resume, fsync_flag, inplace_flag) == -1) { error("upload \"%s\" to \"%s\" failed", new_src, new_dst); ret = -1; } } else logit("%s: not a regular file", filename); } free(new_dst); free(new_src); sftp_setstat(conn, dst, &a); (void) closedir(dirp); return ret; } int sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int preserve_flag, int print_flag, int resume, int fsync_flag, int follow_link_flag, int inplace_flag) { char *dst_canon; int ret; if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { error("upload \"%s\": path canonicalization failed", dst); return -1; } ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, print_flag, resume, fsync_flag, follow_link_flag, inplace_flag); free(dst_canon); return ret; } static void handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, u_int *nreqsp, u_int *write_errorp) { struct sshbuf *msg; u_char type; u_int id, status; int r; struct pollfd pfd; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Try to eat replies from the upload side */ while (*nreqsp > 0) { debug3_f("%u outstanding replies", *nreqsp); if (!synchronous) { /* Bail out if no data is ready to be read */ pfd.fd = to->fd_in; pfd.events = POLLIN; if ((r = poll(&pfd, 1, 0)) == -1) { if (errno == EINTR) break; fatal_f("poll: %s", strerror(errno)); } else if (r == 0) break; /* fd not ready */ } sshbuf_reset(msg); get_msg(to, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "dest parse"); debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp); if (type != SSH2_FXP_STATUS) { fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d", SSH2_FXP_STATUS, type); } if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse dest status"); debug3("dest SSH2_FXP_STATUS %u", status); if (status != SSH2_FX_OK) { /* record first error */ if (*write_errorp == 0) *write_errorp = status; } /* * XXX this doesn't do full reply matching like sftp_upload and * so cannot gracefully truncate terminated uploads at a * high-water mark. ATM the only caller of this function (scp) * doesn't support transfer resumption, so this doesn't matter * a whole lot. * * To be safe, sftp_crossload truncates the destination file to * zero length on upload failure, since we can't trust the * server not to have reordered replies that could have * inserted holes where none existed in the source file. * * XXX we could get a more accurate progress bar if we updated * the counter based on the reply from the destination... */ (*nreqsp)--; } debug3_f("done: %u outstanding replies", *nreqsp); sshbuf_free(msg); } int sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *a, int preserve_flag) { struct sshbuf *msg; int write_error, read_error, r; u_int64_t offset = 0, size; u_int id, buflen, num_req, max_req, status = SSH2_FX_OK; u_int num_upload_req; off_t progress_counter; u_char *from_handle, *to_handle; size_t from_handle_len, to_handle_len; struct requests requests; struct request *req; u_char type; Attrib attr; debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path); TAILQ_INIT(&requests); if (a == NULL) { if (sftp_stat(from, from_path, 0, &attr) != 0) return -1; a = &attr; } if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && (!S_ISREG(a->perm))) { error("download \"%s\": not a regular file", from_path); return(-1); } if (a->flags & SSH2_FILEXFER_ATTR_SIZE) size = a->size; else size = 0; buflen = from->download_buflen; if (buflen > to->upload_buflen) buflen = to->upload_buflen; /* Send open request to read side */ if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL, &from_handle, &from_handle_len) != 0) return -1; /* Send open request to write side */ a->flags &= ~SSH2_FILEXFER_ATTR_SIZE; a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID; a->perm &= 0777; if (!preserve_flag) a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; if (send_open(to, to_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, &to_handle, &to_handle_len) != 0) { sftp_close(from, from_handle, from_handle_len); return -1; } /* Read from remote "from" and write to remote "to" */ offset = 0; write_error = read_error = num_req = num_upload_req = 0; max_req = 1; progress_counter = 0; if (showprogress && size != 0) { start_progress_meter(progress_meter_path(from_path), size, &progress_counter); } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); while (num_req > 0 || max_req > 0) { u_char *data; size_t len; /* * Simulate EOF on interrupt: stop sending new requests and * allow outstanding requests to drain gracefully */ if (interrupted) { if (num_req == 0) /* If we haven't started yet... */ break; max_req = 0; } /* Send some more requests */ while (num_req < max_req) { debug3("Request range %llu -> %llu (%d/%d)", (unsigned long long)offset, (unsigned long long)offset + buflen - 1, num_req, max_req); req = request_enqueue(&requests, from->msg_id++, buflen, offset); offset += buflen; num_req++; send_read_request(from, req->id, req->offset, req->len, from_handle, from_handle_len); } /* Try to eat replies from the upload side (nonblocking) */ handle_dest_replies(to, to_path, 0, &num_upload_req, &write_error); sshbuf_reset(msg); get_msg(from, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received origin reply T:%u I:%u R:%d", type, id, max_req); /* Find the request in our queue */ if ((req = request_find(&requests, id)) == NULL) fatal("Unexpected reply %u", id); switch (type) { case SSH2_FXP_STATUS: if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (status != SSH2_FX_EOF) read_error = 1; max_req = 0; TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; break; case SSH2_FXP_DATA: if ((r = sshbuf_get_string(msg, &data, &len)) != 0) fatal_fr(r, "parse data"); debug3("Received data %llu -> %llu", (unsigned long long)req->offset, (unsigned long long)req->offset + len - 1); if (len > req->len) fatal("Received more data than asked for " "%zu > %zu", len, req->len); /* Write this chunk out to the destination */ sshbuf_reset(msg); if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 || (r = sshbuf_put_string(msg, to_handle, to_handle_len)) != 0 || (r = sshbuf_put_u64(msg, req->offset)) != 0 || (r = sshbuf_put_string(msg, data, len)) != 0) fatal_fr(r, "compose write"); send_msg(to, msg); debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu", id, (unsigned long long)offset, len); num_upload_req++; progress_counter += len; free(data); if (len == req->len) { TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; } else { /* Resend the request for the missing data */ debug3("Short data block, re-requesting " "%llu -> %llu (%2d)", (unsigned long long)req->offset + len, (unsigned long long)req->offset + req->len - 1, num_req); req->id = from->msg_id++; req->len -= len; req->offset += len; send_read_request(from, req->id, req->offset, req->len, from_handle, from_handle_len); /* Reduce the request size */ if (len < buflen) buflen = MAXIMUM(MIN_READ_SIZE, len); } if (max_req > 0) { /* max_req = 0 iff EOF received */ if (size > 0 && offset > size) { /* Only one request at a time * after the expected EOF */ debug3("Finish at %llu (%2d)", (unsigned long long)offset, num_req); max_req = 1; } else if (max_req < from->num_requests) { ++max_req; } } break; default: fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", SSH2_FXP_DATA, type); } } if (showprogress && size) stop_progress_meter(); /* Drain replies from the server (blocking) */ debug3_f("waiting for %u replies from destination", num_upload_req); handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error); /* Sanity check */ if (TAILQ_FIRST(&requests) != NULL) fatal("Transfer complete, but requests still in queue"); /* Truncate at 0 length on interrupt or error to avoid holes at dest */ if (read_error || write_error || interrupted) { debug("truncating \"%s\" at 0", to_path); sftp_close(to, to_handle, to_handle_len); free(to_handle); if (send_open(to, to_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, &to_handle, &to_handle_len) != 0) { error("dest truncate \"%s\" failed", to_path); to_handle = NULL; } } if (read_error) { error("read origin \"%s\": %s", from_path, fx2txt(status)); status = -1; sftp_close(from, from_handle, from_handle_len); if (to_handle != NULL) sftp_close(to, to_handle, to_handle_len); } else if (write_error) { error("write dest \"%s\": %s", to_path, fx2txt(write_error)); status = SSH2_FX_FAILURE; sftp_close(from, from_handle, from_handle_len); if (to_handle != NULL) sftp_close(to, to_handle, to_handle_len); } else { if (sftp_close(from, from_handle, from_handle_len) != 0 || interrupted) status = -1; else status = SSH2_FX_OK; if (to_handle != NULL) { /* Need to resend utimes after write */ if (preserve_flag) sftp_fsetstat(to, to_handle, to_handle_len, a); sftp_close(to, to_handle, to_handle_len); } } sshbuf_free(msg); free(from_handle); free(to_handle); return status == SSH2_FX_OK ? 0 : -1; } static int crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, int depth, Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) { int i, ret = 0; SFTP_DIRENT **dir_entries; char *filename, *new_from_path = NULL, *new_to_path = NULL; mode_t mode = 0777; Attrib *a, curdir, ldirattrib, newdir, lsym; debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path); if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); return -1; } if (dirattrib == NULL) { if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) { error("stat remote \"%s\" failed", from_path); return -1; } dirattrib = &ldirattrib; } if (!S_ISDIR(dirattrib->perm)) { error("\"%s\" is not a directory", from_path); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) mprintf("Retrieving %s\n", from_path); curdir = *dirattrib; /* dirattrib will be clobbered */ curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE; curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) { debug("Origin did not send permissions for " "directory \"%s\"", to_path); curdir.perm = S_IWUSR|S_IXUSR; curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; } /* We need to be able to write to the directory while we transfer it */ mode = curdir.perm & 01777; curdir.perm = mode | (S_IWUSR|S_IXUSR); /* * sftp lacks a portable status value to match errno EEXIST, * so if we get a failure back then we must check whether * the path already existed and is a directory. Ensure we can * write to the directory we create for the duration of the transfer. */ if (sftp_mkdir(to, to_path, &curdir, 0) != 0) { if (sftp_stat(to, to_path, 0, &newdir) != 0) return -1; if (!S_ISDIR(newdir.perm)) { error("\"%s\" exists but is not a directory", to_path); return -1; } } curdir.perm = mode; if (sftp_readdir(from, from_path, &dir_entries) == -1) { error("origin readdir \"%s\" failed", from_path); return -1; } for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { free(new_from_path); free(new_to_path); filename = dir_entries[i]->filename; new_from_path = sftp_path_append(from_path, filename); new_to_path = sftp_path_append(to_path, filename); a = &dir_entries[i]->a; if (S_ISLNK(a->perm)) { if (!follow_link_flag) { logit("%s: not a regular file", filename); continue; } /* Replace the stat contents with the symlink target */ if (sftp_stat(from, new_from_path, 1, &lsym) != 0) { logit("remote stat \"%s\" failed", new_from_path); ret = -1; continue; } a = &lsym; } if (S_ISDIR(a->perm)) { if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (crossload_dir_internal(from, to, new_from_path, new_to_path, depth + 1, a, preserve_flag, print_flag, follow_link_flag) == -1) ret = -1; } else if (S_ISREG(a->perm)) { if (sftp_crossload(from, to, new_from_path, new_to_path, a, preserve_flag) == -1) { error("crossload \"%s\" to \"%s\" failed", new_from_path, new_to_path); ret = -1; } } else { logit("origin \"%s\": not a regular file", new_from_path); } } free(new_to_path); free(new_from_path); sftp_setstat(to, to_path, &curdir); sftp_free_dirents(dir_entries); return ret; } int sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) { char *from_path_canon; int ret; if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { error("crossload \"%s\": path canonicalization failed", from_path); return -1; } ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0, dirattrib, preserve_flag, print_flag, follow_link_flag); free(from_path_canon); return ret; } int sftp_can_get_users_groups_by_id(struct sftp_conn *conn) { return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0; } int sftp_get_users_groups_by_id(struct sftp_conn *conn, const u_int *uids, u_int nuids, const u_int *gids, u_int ngids, char ***usernamesp, char ***groupnamesp) { struct sshbuf *msg, *uidbuf, *gidbuf; u_int i, expected_id, id; char *name, **usernames = NULL, **groupnames = NULL; u_char type; int r; *usernamesp = *groupnamesp = NULL; if (!sftp_can_get_users_groups_by_id(conn)) return SSH_ERR_FEATURE_UNSUPPORTED; if ((msg = sshbuf_new()) == NULL || (uidbuf = sshbuf_new()) == NULL || (gidbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); expected_id = id = conn->msg_id++; debug2("Sending SSH2_FXP_EXTENDED(users-groups-by-id@openssh.com)"); for (i = 0; i < nuids; i++) { if ((r = sshbuf_put_u32(uidbuf, uids[i])) != 0) fatal_fr(r, "compose uids"); } for (i = 0; i < ngids; i++) { if ((r = sshbuf_put_u32(gidbuf, gids[i])) != 0) fatal_fr(r, "compose gids"); } if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "users-groups-by-id@openssh.com")) != 0 || (r = sshbuf_put_stringb(msg, uidbuf)) != 0 || (r = sshbuf_put_stringb(msg, gidbuf)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; char *errmsg; if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); error("users-groups-by-id %s", *errmsg == '\0' ? fx2txt(status) : errmsg); free(errmsg); sshbuf_free(msg); sshbuf_free(uidbuf); sshbuf_free(gidbuf); return -1; } else if (type != SSH2_FXP_EXTENDED_REPLY) fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", SSH2_FXP_EXTENDED_REPLY, type); /* reuse */ sshbuf_free(uidbuf); sshbuf_free(gidbuf); uidbuf = gidbuf = NULL; if ((r = sshbuf_froms(msg, &uidbuf)) != 0 || (r = sshbuf_froms(msg, &gidbuf)) != 0) fatal_fr(r, "parse response"); if (nuids > 0) { usernames = xcalloc(nuids, sizeof(*usernames)); for (i = 0; i < nuids; i++) { if ((r = sshbuf_get_cstring(uidbuf, &name, NULL)) != 0) fatal_fr(r, "parse user name"); /* Handle unresolved names */ if (*name == '\0') { free(name); name = NULL; } usernames[i] = name; } } if (ngids > 0) { groupnames = xcalloc(ngids, sizeof(*groupnames)); for (i = 0; i < ngids; i++) { if ((r = sshbuf_get_cstring(gidbuf, &name, NULL)) != 0) fatal_fr(r, "parse user name"); /* Handle unresolved names */ if (*name == '\0') { free(name); name = NULL; } groupnames[i] = name; } } if (sshbuf_len(uidbuf) != 0) fatal_f("unexpected extra username data"); if (sshbuf_len(gidbuf) != 0) fatal_f("unexpected extra groupname data"); sshbuf_free(uidbuf); sshbuf_free(gidbuf); sshbuf_free(msg); /* success */ *usernamesp = usernames; *groupnamesp = groupnames; return 0; } char * sftp_path_append(const char *p1, const char *p2) { char *ret; size_t len = strlen(p1) + strlen(p2) + 2; ret = xmalloc(len); strlcpy(ret, p1, len); if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') strlcat(ret, "/", len); strlcat(ret, p2, len); return(ret); } /* * Arg p must be dynamically allocated. It will either be returned or * freed and a replacement allocated. Caller must free returned string. */ char * sftp_make_absolute(char *p, const char *pwd) { char *abs_str; /* Derelativise */ if (p && !path_absolute(p)) { abs_str = sftp_path_append(pwd, p); free(p); return(abs_str); } else return(p); } int sftp_remote_is_dir(struct sftp_conn *conn, const char *path) { Attrib a; /* XXX: report errors? */ if (sftp_stat(conn, path, 1, &a) != 0) return(0); if (!(a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) return(0); return S_ISDIR(a.perm); } /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ int sftp_globpath_is_dir(const char *pathname) { size_t l = strlen(pathname); return l > 0 && pathname[l - 1] == '/'; } openssh-10.0p1/PaxHeaders.10889/sftp-client.h100644 001750 001750 0000000003514775415623 0015554xustar0029 atime=1744182234.76838302 openssh-10.0p1/sftp-client.h010064400017500001750000000150521477541562300141430ustar00djmdjm/* $OpenBSD: sftp-client.h,v 1.39 2023/09/08 05:56:13 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Client side of SSH2 filexfer protocol */ #ifndef _SFTP_CLIENT_H #define _SFTP_CLIENT_H #ifdef USE_SYSTEM_GLOB # include #else # include "openbsd-compat/glob.h" #endif typedef struct SFTP_DIRENT SFTP_DIRENT; struct SFTP_DIRENT { char *filename; char *longname; Attrib a; }; /* * Used for statvfs responses on the wire from the server, because the * server's native format may be larger than the client's. */ struct sftp_statvfs { u_int64_t f_bsize; u_int64_t f_frsize; u_int64_t f_blocks; u_int64_t f_bfree; u_int64_t f_bavail; u_int64_t f_files; u_int64_t f_ffree; u_int64_t f_favail; u_int64_t f_fsid; u_int64_t f_flag; u_int64_t f_namemax; }; /* Used for limits response on the wire from the server */ struct sftp_limits { u_int64_t packet_length; u_int64_t read_length; u_int64_t write_length; u_int64_t open_handles; }; /* print flag values */ #define SFTP_QUIET 0 /* be quiet during transfers */ #define SFTP_PRINT 1 /* list files and show progress bar */ #define SFTP_PROGRESS_ONLY 2 /* progress bar only */ /* * Initialise a SSH filexfer connection. Returns NULL on error or * a pointer to a initialized sftp_conn struct on success. */ struct sftp_conn *sftp_init(int, int, u_int, u_int, u_int64_t); u_int sftp_proto_version(struct sftp_conn *); /* Query server limits */ int sftp_get_limits(struct sftp_conn *, struct sftp_limits *); /* Close file referred to by 'handle' */ int sftp_close(struct sftp_conn *, const u_char *, u_int); /* Read contents of 'path' to NULL-terminated array 'dir' */ int sftp_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from sftp_readdir) */ void sftp_free_dirents(SFTP_DIRENT **); /* Delete file 'path' */ int sftp_rm(struct sftp_conn *, const char *); /* Create directory 'path' */ int sftp_mkdir(struct sftp_conn *, const char *, Attrib *, int); /* Remove directory 'path' */ int sftp_rmdir(struct sftp_conn *, const char *); /* Get file attributes of 'path' (follows symlinks) */ int sftp_stat(struct sftp_conn *, const char *, int, Attrib *); /* Get file attributes of 'path' (does not follow symlinks) */ int sftp_lstat(struct sftp_conn *, const char *, int, Attrib *); /* Set file attributes of 'path' */ int sftp_setstat(struct sftp_conn *, const char *, Attrib *); /* Set file attributes of open file 'handle' */ int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); /* Set file attributes of 'path', not following symlinks */ int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); /* Canonicalise 'path' - caller must free result */ char *sftp_realpath(struct sftp_conn *, const char *); /* Canonicalisation with tilde expansion (requires server extension) */ char *sftp_expand_path(struct sftp_conn *, const char *); /* Returns non-zero if server can tilde-expand paths */ int sftp_can_expand_path(struct sftp_conn *); /* Get statistics for filesystem hosting file at "path" */ int sftp_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); /* Rename 'oldpath' to 'newpath' */ int sftp_rename(struct sftp_conn *, const char *, const char *, int); /* Copy 'oldpath' to 'newpath' */ int sftp_copy(struct sftp_conn *, const char *, const char *); /* Link 'oldpath' to 'newpath' */ int sftp_hardlink(struct sftp_conn *, const char *, const char *); /* Rename 'oldpath' to 'newpath' */ int sftp_symlink(struct sftp_conn *, const char *, const char *); /* Call fsync() on open file 'handle' */ int sftp_fsync(struct sftp_conn *conn, u_char *, u_int); /* * Download 'remote_path' to 'local_path'. Preserve permissions and times * if 'pflag' is set */ int sftp_download(struct sftp_conn *, const char *, const char *, Attrib *, int, int, int, int); /* * Recursively download 'remote_directory' to 'local_directory'. Preserve * times if 'pflag' is set */ int sftp_download_dir(struct sftp_conn *, const char *, const char *, Attrib *, int, int, int, int, int, int); /* * Upload 'local_path' to 'remote_path'. Preserve permissions and times * if 'pflag' is set */ int sftp_upload(struct sftp_conn *, const char *, const char *, int, int, int, int); /* * Recursively upload 'local_directory' to 'remote_directory'. Preserve * times if 'pflag' is set */ int sftp_upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, int, int, int); /* * Download a 'from_path' from the 'from' connection and upload it to * to 'to' connection at 'to_path'. */ int sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *a, int preserve_flag); /* * Recursively download a directory from 'from_path' from the 'from' * connection and upload it to 'to' connection at 'to_path'. */ int sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag); /* * User/group ID to name translation. */ int sftp_can_get_users_groups_by_id(struct sftp_conn *conn); int sftp_get_users_groups_by_id(struct sftp_conn *conn, const u_int *uids, u_int nuids, const u_int *gids, u_int ngids, char ***usernamesp, char ***groupnamesp); /* Concatenate paths, taking care of slashes. Caller must free result. */ char *sftp_path_append(const char *, const char *); /* Make absolute path if relative path and CWD is given. Does not modify * original if the path is already absolute. */ char *sftp_make_absolute(char *, const char *); /* Check if remote path is directory */ int sftp_remote_is_dir(struct sftp_conn *conn, const char *path); /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ int sftp_globpath_is_dir(const char *pathname); #endif openssh-10.0p1/PaxHeaders.10889/sftp-common.c100644 001750 001750 0000000003514775415623 0015561xustar0029 atime=1744182234.76838302 openssh-10.0p1/sftp-common.c010064400017500001750000000156461477541562300141610ustar00djmdjm/* $OpenBSD: sftp-common.c,v 1.34 2023/03/31 04:00:37 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_UTIL_H #include #endif #include "xmalloc.h" #include "ssherr.h" #include "sshbuf.h" #include "log.h" #include "misc.h" #include "sftp.h" #include "sftp-common.h" /* Clear contents of attributes structure */ void attrib_clear(Attrib *a) { a->flags = 0; a->size = 0; a->uid = 0; a->gid = 0; a->perm = 0; a->atime = 0; a->mtime = 0; } /* Convert from struct stat to filexfer attribs */ void stat_to_attrib(const struct stat *st, Attrib *a) { attrib_clear(a); a->flags = 0; a->flags |= SSH2_FILEXFER_ATTR_SIZE; a->size = st->st_size; a->flags |= SSH2_FILEXFER_ATTR_UIDGID; a->uid = st->st_uid; a->gid = st->st_gid; a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a->perm = st->st_mode; a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME; a->atime = st->st_atime; a->mtime = st->st_mtime; } /* Convert from filexfer attribs to struct stat */ void attrib_to_stat(const Attrib *a, struct stat *st) { memset(st, 0, sizeof(*st)); if (a->flags & SSH2_FILEXFER_ATTR_SIZE) st->st_size = a->size; if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { st->st_uid = a->uid; st->st_gid = a->gid; } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) st->st_mode = a->perm; if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { st->st_atime = a->atime; st->st_mtime = a->mtime; } } /* Decode attributes in buffer */ int decode_attrib(struct sshbuf *b, Attrib *a) { int r; attrib_clear(a); if ((r = sshbuf_get_u32(b, &a->flags)) != 0) return r; if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { if ((r = sshbuf_get_u64(b, &a->size)) != 0) return r; } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { if ((r = sshbuf_get_u32(b, &a->uid)) != 0 || (r = sshbuf_get_u32(b, &a->gid)) != 0) return r; } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { if ((r = sshbuf_get_u32(b, &a->perm)) != 0) return r; } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { if ((r = sshbuf_get_u32(b, &a->atime)) != 0 || (r = sshbuf_get_u32(b, &a->mtime)) != 0) return r; } /* vendor-specific extensions */ if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) { char *type; u_char *data; size_t dlen; u_int i, count; if ((r = sshbuf_get_u32(b, &count)) != 0) return r; if (count > 0x100000) return SSH_ERR_INVALID_FORMAT; for (i = 0; i < count; i++) { if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 || (r = sshbuf_get_string(b, &data, &dlen)) != 0) return r; debug3("Got file attribute \"%.100s\" len %zu", type, dlen); free(type); free(data); } } return 0; } /* Encode attributes to buffer */ int encode_attrib(struct sshbuf *b, const Attrib *a) { int r; if ((r = sshbuf_put_u32(b, a->flags)) != 0) return r; if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { if ((r = sshbuf_put_u64(b, a->size)) != 0) return r; } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { if ((r = sshbuf_put_u32(b, a->uid)) != 0 || (r = sshbuf_put_u32(b, a->gid)) != 0) return r; } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { if ((r = sshbuf_put_u32(b, a->perm)) != 0) return r; } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { if ((r = sshbuf_put_u32(b, a->atime)) != 0 || (r = sshbuf_put_u32(b, a->mtime)) != 0) return r; } return 0; } /* Convert from SSH2_FX_ status to text error message */ const char * fx2txt(int status) { switch (status) { case SSH2_FX_OK: return("No error"); case SSH2_FX_EOF: return("End of file"); case SSH2_FX_NO_SUCH_FILE: return("No such file or directory"); case SSH2_FX_PERMISSION_DENIED: return("Permission denied"); case SSH2_FX_FAILURE: return("Failure"); case SSH2_FX_BAD_MESSAGE: return("Bad message"); case SSH2_FX_NO_CONNECTION: return("No connection"); case SSH2_FX_CONNECTION_LOST: return("Connection lost"); case SSH2_FX_OP_UNSUPPORTED: return("Operation unsupported"); default: return("Unknown status"); } /* NOTREACHED */ } /* * drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh */ char * ls_file(const char *name, const struct stat *st, int remote, int si_units, const char *user, const char *group) { int ulen, glen, sz = 0; struct tm *ltime = localtime(&st->st_mtime); 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) { if (user == NULL) { snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); user = ubuf; } if (group == NULL) { 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); if (now - (365*24*60*60)/2 < st->st_mtime && now >= st->st_mtime) sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime); else sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime); } if (sz == 0) tbuf[0] = '\0'; 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 %3s %-*s %-*s %8s %s %s", mode, lc, ulen, user, glen, group, sbuf, tbuf, name); } else { 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); } openssh-10.0p1/PaxHeaders.10889/sftp-common.h100644 001750 001750 0000000003514775415623 0015566xustar0029 atime=1744182234.76838302 openssh-10.0p1/sftp-common.h010064400017500001750000000040701477541562300141530ustar00djmdjm/* $OpenBSD: sftp-common.h,v 1.13 2022/09/19 10:41:58 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Maximum packet that we are willing to send/accept */ #define SFTP_MAX_MSG_LENGTH (256 * 1024) struct sshbuf; typedef struct Attrib Attrib; /* File attributes */ struct Attrib { u_int32_t flags; u_int64_t size; u_int32_t uid; u_int32_t gid; u_int32_t perm; u_int32_t atime; u_int32_t mtime; }; void attrib_clear(Attrib *); void stat_to_attrib(const struct stat *, Attrib *); void attrib_to_stat(const Attrib *, struct stat *); int decode_attrib(struct sshbuf *, Attrib *); int encode_attrib(struct sshbuf *, const Attrib *); char *ls_file(const char *, const struct stat *, int, int, const char *, const char *); const char *fx2txt(int); openssh-10.0p1/PaxHeaders.10889/sftp-glob.c100644 001750 001750 0000000003514775415623 0015214xustar0029 atime=1744182234.76838302 openssh-10.0p1/sftp-glob.c010064400017500001750000000105111477541562300135760ustar00djmdjm/* $OpenBSD: sftp-glob.c,v 1.33 2023/09/10 23:12:32 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #ifdef HAVE_SYS_STAT_H # include #endif #include #include #include #include #include "xmalloc.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" int sftp_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); struct SFTP_OPENDIR { SFTP_DIRENT **dir; int offset; }; static struct { struct sftp_conn *conn; } cur; static void * fudge_opendir(const char *path) { struct SFTP_OPENDIR *r; r = xcalloc(1, sizeof(*r)); if (sftp_readdir(cur.conn, path, &r->dir)) { free(r); return(NULL); } r->offset = 0; return((void *)r); } static struct dirent * fudge_readdir(struct SFTP_OPENDIR *od) { /* Solaris needs sizeof(dirent) + path length (see below) */ static char buf[sizeof(struct dirent) + MAXPATHLEN]; struct dirent *ret = (struct dirent *)buf; #ifdef __GNU_LIBRARY__ static int inum = 1; #endif /* __GNU_LIBRARY__ */ if (od->dir[od->offset] == NULL) return(NULL); memset(buf, 0, sizeof(buf)); /* * Solaris defines dirent->d_name as a one byte array and expects * you to hack around it. */ #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN); #else strlcpy(ret->d_name, od->dir[od->offset++]->filename, sizeof(ret->d_name)); #endif #ifdef __GNU_LIBRARY__ /* * Idiot glibc uses extensions to struct dirent for readdir with * ALTDIRFUNCs. Not that this is documented anywhere but the * source... Fake an inode number to appease it. */ ret->d_ino = inum++; if (!inum) inum = 1; #endif /* __GNU_LIBRARY__ */ return(ret); } static void fudge_closedir(struct SFTP_OPENDIR *od) { sftp_free_dirents(od->dir); free(od); } static int fudge_lstat(const char *path, struct stat *st) { Attrib a; if (sftp_lstat(cur.conn, path, 1, &a) != 0) return -1; attrib_to_stat(&a, st); return 0; } static int fudge_stat(const char *path, struct stat *st) { Attrib a; if (sftp_stat(cur.conn, path, 1, &a) != 0) return -1; attrib_to_stat(&a, st); return(0); } int sftp_glob(struct sftp_conn *conn, const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { int r; size_t l; char *s; struct stat sb; pglob->gl_opendir = fudge_opendir; pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir; pglob->gl_closedir = (void (*)(void *))fudge_closedir; pglob->gl_lstat = fudge_lstat; pglob->gl_stat = fudge_stat; memset(&cur, 0, sizeof(cur)); cur.conn = conn; if ((r = glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)) != 0) return r; /* * When both GLOB_NOCHECK and GLOB_MARK are active, a single gl_pathv * entry has been returned and that entry has not already been marked, * then check whether it needs a '/' appended as a directory mark. * * This ensures that a NOCHECK result is annotated as a directory. * The glob(3) spec doesn't promise to mark NOCHECK entries, but doing * it simplifies our callers (sftp/scp) considerably. * * XXX doesn't try to handle gl_offs. */ if ((flags & (GLOB_NOCHECK|GLOB_MARK)) == (GLOB_NOCHECK|GLOB_MARK) && pglob->gl_matchc == 0 && pglob->gl_offs == 0 && pglob->gl_pathc == 1 && (s = pglob->gl_pathv[0]) != NULL && (l = strlen(s)) > 0 && s[l-1] != '/') { if (fudge_stat(s, &sb) == 0 && S_ISDIR(sb.st_mode)) { /* NOCHECK on a directory; annotate */ if ((s = realloc(s, l + 2)) != NULL) { memcpy(s + l, "/", 2); pglob->gl_pathv[0] = s; } } } return 0; } openssh-10.0p1/PaxHeaders.10889/sftp-realpath.c100644 001750 001750 0000000003514775415623 0016071xustar0029 atime=1744182234.76838302 openssh-10.0p1/sftp-realpath.c010064400017500001750000000137201477541562300144600ustar00djmdjm/* $OpenBSD: sftp-realpath.c,v 1.2 2021/09/02 21:03:54 deraadt Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * * 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 names of the authors 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" #include #include #include #include #include #include #include #include #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]); * * Find the real name of path, by removing all ".", ".." and symlink * components. Returns (resolved) on success, or (NULL) on failure, * in which case the path which caused trouble is left in (resolved). */ char * 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, 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] = '/'; resolved[1] = '\0'; if (path[1] == '\0') return (resolved); resolved_len = 1; left_len = strlcpy(left, path + 1, sizeof(left)); } else { if (getcwd(resolved, PATH_MAX) == NULL) { if (mem_allocated) free(resolved); else strlcpy(resolved, ".", PATH_MAX); return (NULL); } resolved_len = strlen(resolved); left_len = strlcpy(left, path, sizeof(left)); } if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; goto err; } /* * Iterate over path components in `left'. */ while (left_len != 0) { /* * Extract the next path component and adjust `left' * and its length. */ p = strchr(left, '/'); s = p ? p : left + left_len; if (s - left >= (ptrdiff_t)sizeof(next_token)) { errno = ENAMETOOLONG; goto err; } memcpy(next_token, left, s - left); next_token[s - left] = '\0'; left_len -= s - left; if (p != NULL) memmove(left, s + 1, left_len + 1); if (resolved[resolved_len - 1] != '/') { if (resolved_len + 1 >= PATH_MAX) { errno = ENAMETOOLONG; goto err; } resolved[resolved_len++] = '/'; resolved[resolved_len] = '\0'; } if (next_token[0] == '\0') continue; else if (strcmp(next_token, ".") == 0) continue; else if (strcmp(next_token, "..") == 0) { /* * Strip the last path component except when we have * single "/" */ if (resolved_len > 1) { resolved[resolved_len - 1] = '\0'; q = strrchr(resolved, '/') + 1; *q = '\0'; resolved_len = q - resolved; } continue; } /* * Append the next path component and lstat() it. If * lstat() fails we still can return successfully if * there are no more path components left. */ resolved_len = strlcat(resolved, next_token, PATH_MAX); if (resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; goto err; } if (lstat(resolved, &sb) != 0) { if (errno == ENOENT && p == NULL) { errno = serrno; return (resolved); } goto err; } if (S_ISLNK(sb.st_mode)) { if (symlinks++ > SYMLOOP_MAX) { errno = ELOOP; goto err; } slen = readlink(resolved, symlink, sizeof(symlink) - 1); if (slen < 0) goto err; symlink[slen] = '\0'; if (symlink[0] == '/') { resolved[1] = 0; resolved_len = 1; } else if (resolved_len > 1) { /* Strip the last path component. */ resolved[resolved_len - 1] = '\0'; q = strrchr(resolved, '/') + 1; *q = '\0'; resolved_len = q - resolved; } /* * If there are any path components left, then * append them to symlink. The result is placed * in `left'. */ if (p != NULL) { if (symlink[slen - 1] != '/') { if (slen + 1 >= (ptrdiff_t)sizeof(symlink)) { errno = ENAMETOOLONG; goto err; } symlink[slen] = '/'; symlink[slen + 1] = 0; } left_len = strlcat(symlink, left, sizeof(symlink)); if (left_len >= sizeof(symlink)) { errno = ENAMETOOLONG; goto err; } } left_len = strlcpy(left, symlink, sizeof(left)); } } /* * Remove trailing slash except when the resolved pathname * is a single "/". */ if (resolved_len > 1 && resolved[resolved_len - 1] == '/') resolved[resolved_len - 1] = '\0'; return (resolved); err: if (mem_allocated) free(resolved); return (NULL); } openssh-10.0p1/PaxHeaders.10889/sftp-server-main.c100644 001750 001750 0000000003614775415623 0016522xustar0030 atime=1744182234.769359838 openssh-10.0p1/sftp-server-main.c010064400017500001750000000026661477541562300151170ustar00djmdjm/* $OpenBSD: sftp-server-main.c,v 1.6 2019/06/06 05:13:13 otto Exp $ */ /* * Copyright (c) 2008 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. */ #include "includes.h" #include #include #include #include #include #include "log.h" #include "sftp.h" #include "misc.h" #include "xmalloc.h" void cleanup_exit(int i) { sftp_server_cleanup_exit(i); } int main(int argc, char **argv) { struct passwd *user_pw; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); if ((user_pw = getpwuid(getuid())) == NULL) { fprintf(stderr, "No user found for uid %lu\n", (u_long)getuid()); return 1; } return (sftp_server_main(argc, argv, user_pw)); } openssh-10.0p1/PaxHeaders.10889/sftp-server.0100644 001750 001750 0000000003614775415623 0015515xustar0030 atime=1744182234.769359838 openssh-10.0p1/sftp-server.0010064400017500001750000000104011477541562300140740ustar00djmdjmSFTP-SERVER(8) System Manager's Manual SFTP-SERVER(8) NAME sftp-server M-bM-^@M-^S OpenSSH SFTP server subsystem SYNOPSIS sftp-server [-ehR] [-d start_directory] [-f log_facility] [-l log_level] [-P denied_requests] [-p allowed_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 denied_requests Specifies a comma-separated list of SFTP protocol requests that are banned by the server. sftp-server will reply to any denied request with a failure. The -Q flag can be used to determine the supported request types. If both denied and allowed lists are specified, then the denied list is applied before the allowed list. -p allowed_requests Specifies a comma-separated list of SFTP protocol requests that are permitted by the server. All request types that are not on the allowed list 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 Queries 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 to deny or allow specific requests (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 OpenBSD 7.6 July 27, 2021 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/sftp-server.8100644 001750 001750 0000000003614775415623 0015525xustar0030 atime=1744182234.769359838 openssh-10.0p1/sftp-server.8010064400017500001750000000117561477541562300141220ustar00djmdjm.\" $OpenBSD: sftp-server.8,v 1.31 2021/07/27 14:14:25 jmc 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. .\" .Dd $Mdocdate: July 27 2021 $ .Dt SFTP-SERVER 8 .Os .Sh NAME .Nm sftp-server .Nd OpenSSH SFTP server subsystem .Sh SYNOPSIS .Nm sftp-server .Bk -words .Op Fl ehR .Op Fl d Ar start_directory .Op Fl f Ar log_facility .Op Fl l Ar log_level .Op Fl P Ar denied_requests .Op Fl p Ar allowed_requests .Op Fl u Ar umask .Ek .Nm .Fl Q Ar protocol_feature .Sh DESCRIPTION .Nm is a program that speaks the server side of SFTP protocol to stdout and expects client requests from stdin. .Nm is not intended to be called directly, but from .Xr sshd 8 using the .Cm Subsystem option. .Pp Command-line flags to .Nm should be specified in the .Cm Subsystem declaration. See .Xr sshd_config 5 for more information. .Pp Valid options are: .Bl -tag -width Ds .It Fl d Ar 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 .Xr sshd_config 5 .Cm ChrootDirectory option. .It Fl e Causes .Nm to print logging information to stderr instead of syslog for debugging. .It Fl f Ar log_facility Specifies the facility code that is used when logging messages from .Nm . The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is AUTH. .It Fl h Displays .Nm usage information. .It Fl l Ar log_level Specifies which messages will be logged by .Nm . The possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. INFO and VERBOSE log transactions that .Nm performs on behalf of the client. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of debugging output. The default is ERROR. .It Fl P Ar denied_requests Specifies a comma-separated list of SFTP protocol requests that are banned by the server. .Nm will reply to any denied request with a failure. The .Fl Q flag can be used to determine the supported request types. If both denied and allowed lists are specified, then the denied list is applied before the allowed list. .It Fl p Ar allowed_requests Specifies a comma-separated list of SFTP protocol requests that are permitted by the server. All request types that are not on the allowed list will be logged and replied to with a failure message. .Pp Care must be taken when using this feature to ensure that requests made implicitly by SFTP clients are permitted. .It Fl Q Ar protocol_feature Queries protocol features supported by .Nm . At present the only feature that may be queried is .Dq requests , which may be used to deny or allow specific requests (flags .Fl P and .Fl p respectively). .It Fl R Places this instance of .Nm 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. .It Fl u Ar umask Sets an explicit .Xr umask 2 to be applied to newly-created files and directories, instead of the user's default mask. .El .Pp On some systems, .Nm must be able to access .Pa /dev/log for logging to work, and use of .Nm in a chroot configuration therefore requires that .Xr syslogd 8 establish a logging socket inside the chroot directory. .Sh SEE ALSO .Xr sftp 1 , .Xr ssh 1 , .Xr sshd_config 5 , .Xr sshd 8 .Rs .%A T. Ylonen .%A S. Lehtinen .%T "SSH File Transfer Protocol" .%N draft-ietf-secsh-filexfer-02.txt .%D October 2001 .%O work in progress material .Re .Sh HISTORY .Nm first appeared in .Ox 2.8 . .Sh AUTHORS .An Markus Friedl Aq Mt markus@openbsd.org openssh-10.0p1/PaxHeaders.10889/sftp-server.c100644 001750 001750 0000000003614775415623 0015600xustar0030 atime=1744182234.773265365 openssh-10.0p1/sftp-server.c010064400017500001750000001477511477541562300142020ustar00djmdjm/* $OpenBSD: sftp-server.c,v 1.148 2024/04/30 06:23:51 djm Exp $ */ /* * Copyright (c) 2000-2004 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. */ #include "includes.h" #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #include #include #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #include #include #include "atomicio.h" #include "xmalloc.h" #include "sshbuf.h" #include "ssherr.h" #include "log.h" #include "misc.h" #include "match.h" #include "uidswap.h" #include "sftp.h" #include "sftp-common.h" char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ /* Maximum data read that we are willing to accept */ #define SFTP_MAX_READ_LENGTH (SFTP_MAX_MSG_LENGTH - 1024) /* Our verbosity */ static LogLevel log_level = SYSLOG_LEVEL_ERROR; /* Our client */ static struct passwd *pw = NULL; static char *client_addr = NULL; /* input and output queue */ struct sshbuf *iqueue; struct sshbuf *oqueue; /* Version of client */ static u_int version; /* SSH2_FXP_INIT received */ static int init_done; /* Disable writes */ static int readonly; /* Requests that are allowed/denied */ static char *request_allowlist, *request_denylist; /* portable attributes, etc. */ typedef struct Stat Stat; struct Stat { char *name; char *long_name; Attrib attrib; }; /* Packet handlers */ static void process_open(u_int32_t id); static void process_close(u_int32_t id); static void process_read(u_int32_t id); static void process_write(u_int32_t id); static void process_stat(u_int32_t id); static void process_lstat(u_int32_t id); static void process_fstat(u_int32_t id); static void process_setstat(u_int32_t id); static void process_fsetstat(u_int32_t id); static void process_opendir(u_int32_t id); static void process_readdir(u_int32_t id); static void process_remove(u_int32_t id); static void process_mkdir(u_int32_t id); static void process_rmdir(u_int32_t id); static void process_realpath(u_int32_t id); static void process_rename(u_int32_t id); static void process_readlink(u_int32_t id); static void process_symlink(u_int32_t id); static void process_extended_posix_rename(u_int32_t id); 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_limits(u_int32_t id); static void process_extended_expand(u_int32_t id); static void process_extended_copy_data(u_int32_t id); static void process_extended_home_directory(u_int32_t id); static void process_extended_get_users_groups_by_id(u_int32_t id); static void process_extended(u_int32_t id); struct sftp_handler { const char *name; /* user-visible name for fine-grained perms */ const char *ext_name; /* extended request name */ u_int type; /* packet type, for non extended packets */ void (*handler)(u_int32_t); int does_write; /* if nonzero, banned for readonly mode */ }; 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 }, { "read", NULL, SSH2_FXP_READ, process_read, 0 }, { "write", NULL, SSH2_FXP_WRITE, process_write, 1 }, { "lstat", NULL, SSH2_FXP_LSTAT, process_lstat, 0 }, { "fstat", NULL, SSH2_FXP_FSTAT, process_fstat, 0 }, { "setstat", NULL, SSH2_FXP_SETSTAT, process_setstat, 1 }, { "fsetstat", NULL, SSH2_FXP_FSETSTAT, process_fsetstat, 1 }, { "opendir", NULL, SSH2_FXP_OPENDIR, process_opendir, 0 }, { "readdir", NULL, SSH2_FXP_READDIR, process_readdir, 0 }, { "remove", NULL, SSH2_FXP_REMOVE, process_remove, 1 }, { "mkdir", NULL, SSH2_FXP_MKDIR, process_mkdir, 1 }, { "rmdir", NULL, SSH2_FXP_RMDIR, process_rmdir, 1 }, { "realpath", NULL, SSH2_FXP_REALPATH, process_realpath, 0 }, { "stat", NULL, SSH2_FXP_STAT, process_stat, 0 }, { "rename", NULL, SSH2_FXP_RENAME, process_rename, 1 }, { "readlink", NULL, SSH2_FXP_READLINK, process_readlink, 0 }, { "symlink", NULL, SSH2_FXP_SYMLINK, process_symlink, 1 }, { NULL, NULL, 0, NULL, 0 } }; /* SSH2_FXP_EXTENDED submessages */ 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 }, { "limits", "limits@openssh.com", 0, process_extended_limits, 0 }, { "expand-path", "expand-path@openssh.com", 0, process_extended_expand, 0 }, { "copy-data", "copy-data", 0, process_extended_copy_data, 1 }, { "home-directory", "home-directory", 0, process_extended_home_directory, 0 }, { "users-groups-by-id", "users-groups-by-id@openssh.com", 0, process_extended_get_users_groups_by_id, 0 }, { NULL, NULL, 0, NULL, 0 } }; static const struct sftp_handler * extended_handler_byname(const char *name) { int i; for (i = 0; extended_handlers[i].handler != NULL; i++) { if (strcmp(name, extended_handlers[i].ext_name) == 0) return &extended_handlers[i]; } return NULL; } static int request_permitted(const struct sftp_handler *h) { char *result; if (readonly && h->does_write) { verbose("Refusing %s request in read-only mode", h->name); return 0; } if (request_denylist != NULL && ((result = match_list(h->name, request_denylist, NULL))) != NULL) { free(result); verbose("Refusing denylisted %s request", h->name); return 0; } if (request_allowlist != NULL && ((result = match_list(h->name, request_allowlist, NULL))) != NULL) { free(result); debug2("Permitting allowlisted %s request", h->name); return 1; } if (request_allowlist != NULL) { verbose("Refusing non-allowlisted %s request", h->name); return 0; } return 1; } static int errno_to_portable(int unixerrno) { int ret = 0; switch (unixerrno) { case 0: ret = SSH2_FX_OK; break; case ENOENT: case ENOTDIR: case EBADF: case ELOOP: ret = SSH2_FX_NO_SUCH_FILE; break; case EPERM: case EACCES: case EFAULT: ret = SSH2_FX_PERMISSION_DENIED; break; case ENAMETOOLONG: case EINVAL: ret = SSH2_FX_BAD_MESSAGE; break; case ENOSYS: ret = SSH2_FX_OP_UNSUPPORTED; break; default: ret = SSH2_FX_FAILURE; break; } return ret; } static int flags_from_portable(int pflags) { int flags = 0; if ((pflags & SSH2_FXF_READ) && (pflags & SSH2_FXF_WRITE)) { flags = O_RDWR; } else if (pflags & SSH2_FXF_READ) { flags = O_RDONLY; } else if (pflags & SSH2_FXF_WRITE) { flags = O_WRONLY; } if (pflags & SSH2_FXF_APPEND) flags |= O_APPEND; if (pflags & SSH2_FXF_CREAT) flags |= O_CREAT; if (pflags & SSH2_FXF_TRUNC) flags |= O_TRUNC; if (pflags & SSH2_FXF_EXCL) flags |= O_EXCL; return flags; } static const char * string_from_portable(int pflags) { static char ret[128]; *ret = '\0'; #define PAPPEND(str) { \ if (*ret != '\0') \ strlcat(ret, ",", sizeof(ret)); \ strlcat(ret, str, sizeof(ret)); \ } if (pflags & SSH2_FXF_READ) PAPPEND("READ") if (pflags & SSH2_FXF_WRITE) PAPPEND("WRITE") if (pflags & SSH2_FXF_APPEND) PAPPEND("APPEND") if (pflags & SSH2_FXF_CREAT) PAPPEND("CREATE") if (pflags & SSH2_FXF_TRUNC) PAPPEND("TRUNCATE") if (pflags & SSH2_FXF_EXCL) PAPPEND("EXCL") return ret; } /* handle handles */ typedef struct Handle Handle; struct Handle { int use; DIR *dirp; int fd; int flags; char *name; u_int64_t bytes_read, bytes_write; int next_unused; }; enum { HANDLE_UNUSED, HANDLE_DIR, HANDLE_FILE }; static Handle *handles = NULL; static u_int num_handles = 0; static int first_unused_handle = -1; static void handle_unused(int i) { handles[i].use = HANDLE_UNUSED; handles[i].next_unused = first_unused_handle; first_unused_handle = i; } static int handle_new(int use, const char *name, int fd, int flags, DIR *dirp) { int i; if (first_unused_handle == -1) { if (num_handles + 1 <= num_handles) return -1; num_handles++; handles = xreallocarray(handles, num_handles, sizeof(Handle)); handle_unused(num_handles - 1); } i = first_unused_handle; first_unused_handle = handles[i].next_unused; handles[i].use = use; handles[i].dirp = dirp; handles[i].fd = fd; handles[i].flags = flags; handles[i].name = xstrdup(name); handles[i].bytes_read = handles[i].bytes_write = 0; return i; } static int handle_is_ok(int i, int type) { return i >= 0 && (u_int)i < num_handles && handles[i].use == type; } static int handle_to_string(int handle, u_char **stringp, int *hlenp) { if (stringp == NULL || hlenp == NULL) return -1; *stringp = xmalloc(sizeof(int32_t)); put_u32(*stringp, handle); *hlenp = sizeof(int32_t); return 0; } static int handle_from_string(const u_char *handle, u_int hlen) { int val; if (hlen != sizeof(int32_t)) return -1; val = get_u32(handle); if (handle_is_ok(val, HANDLE_FILE) || handle_is_ok(val, HANDLE_DIR)) return val; return -1; } static char * handle_to_name(int handle) { if (handle_is_ok(handle, HANDLE_DIR)|| handle_is_ok(handle, HANDLE_FILE)) return handles[handle].name; return NULL; } static DIR * handle_to_dir(int handle) { if (handle_is_ok(handle, HANDLE_DIR)) return handles[handle].dirp; return NULL; } static int handle_to_fd(int handle) { if (handle_is_ok(handle, HANDLE_FILE)) return handles[handle].fd; return -1; } static int handle_to_flags(int handle) { if (handle_is_ok(handle, HANDLE_FILE)) return handles[handle].flags; return 0; } static void handle_update_read(int handle, ssize_t bytes) { if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) handles[handle].bytes_read += bytes; } static void handle_update_write(int handle, ssize_t bytes) { if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) handles[handle].bytes_write += bytes; } static u_int64_t handle_bytes_read(int handle) { if (handle_is_ok(handle, HANDLE_FILE)) return (handles[handle].bytes_read); return 0; } static u_int64_t handle_bytes_write(int handle) { if (handle_is_ok(handle, HANDLE_FILE)) return (handles[handle].bytes_write); return 0; } static int handle_close(int handle) { int ret = -1; if (handle_is_ok(handle, HANDLE_FILE)) { ret = close(handles[handle].fd); free(handles[handle].name); handle_unused(handle); } else if (handle_is_ok(handle, HANDLE_DIR)) { ret = closedir(handles[handle].dirp); free(handles[handle].name); handle_unused(handle); } else { errno = ENOENT; } return ret; } static void handle_log_close(int handle, char *emsg) { if (handle_is_ok(handle, HANDLE_FILE)) { logit("%s%sclose \"%s\" bytes read %llu written %llu", emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", handle_to_name(handle), (unsigned long long)handle_bytes_read(handle), (unsigned long long)handle_bytes_write(handle)); } else { logit("%s%sclosedir \"%s\"", emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", handle_to_name(handle)); } } static void handle_log_exit(void) { u_int i; for (i = 0; i < num_handles; i++) if (handles[i].use != HANDLE_UNUSED) handle_log_close(i, "forced"); } static int get_handle(struct sshbuf *queue, int *hp) { u_char *handle; int r; size_t hlen; *hp = -1; if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0) return r; if (hlen < 256) *hp = handle_from_string(handle, hlen); free(handle); return 0; } /* send replies */ static void send_msg(struct sshbuf *m) { int r; if ((r = sshbuf_put_stringb(oqueue, m)) != 0) fatal_fr(r, "enqueue"); sshbuf_reset(m); } static const char * status_to_message(u_int32_t status) { static const char * const status_messages[] = { "Success", /* SSH_FX_OK */ "End of file", /* SSH_FX_EOF */ "No such file", /* SSH_FX_NO_SUCH_FILE */ "Permission denied", /* SSH_FX_PERMISSION_DENIED */ "Failure", /* SSH_FX_FAILURE */ "Bad message", /* SSH_FX_BAD_MESSAGE */ "No connection", /* SSH_FX_NO_CONNECTION */ "Connection lost", /* SSH_FX_CONNECTION_LOST */ "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ "Unknown error" /* Others */ }; return (status_messages[MINIMUM(status,SSH2_FX_MAX)]); } static void send_status_errmsg(u_int32_t id, u_int32_t status, const char *errmsg) { struct sshbuf *msg; int r; debug3("request %u: sent status %u", id, status); if (log_level > SYSLOG_LEVEL_VERBOSE || (status != SSH2_FX_OK && status != SSH2_FX_EOF)) logit("sent status %s", status_to_message(status)); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_u32(msg, status)) != 0) fatal_fr(r, "compose"); if (version >= 3) { if ((r = sshbuf_put_cstring(msg, errmsg == NULL ? status_to_message(status) : errmsg)) != 0 || (r = sshbuf_put_cstring(msg, "")) != 0) fatal_fr(r, "compose message"); } send_msg(msg); sshbuf_free(msg); } static void send_status(u_int32_t id, u_int32_t status) { send_status_errmsg(id, status, NULL); } static void send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, data, dlen)) != 0) fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } static void send_data(u_int32_t id, const u_char *data, int dlen) { debug("request %u: sent data len %d", id, dlen); send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); } static void send_handle(u_int32_t id, int handle) { u_char *string; int hlen; handle_to_string(handle, &string, &hlen); debug("request %u: sent handle %d", id, handle); send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); free(string); } static void send_names(u_int32_t id, int count, const Stat *stats) { struct sshbuf *msg; int i, r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_u32(msg, count)) != 0) fatal_fr(r, "compose"); debug("request %u: sent names count %d", id, count); for (i = 0; i < count; i++) { if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 || (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 || (r = encode_attrib(msg, &stats[i].attrib)) != 0) fatal_fr(r, "compose filenames/attrib"); } send_msg(msg); sshbuf_free(msg); } static void send_attrib(u_int32_t id, const Attrib *a) { struct sshbuf *msg; int r; debug("request %u: sent attrib have 0x%x", id, a->flags); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = encode_attrib(msg, a)) != 0) fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } static void send_statvfs(u_int32_t id, struct statvfs *st) { struct sshbuf *msg; u_int64_t flag; int r; flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 || (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 || (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 || (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 || (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 || (r = sshbuf_put_u64(msg, st->f_files)) != 0 || (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 || (r = sshbuf_put_u64(msg, st->f_favail)) != 0 || (r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 || (r = sshbuf_put_u64(msg, flag)) != 0 || (r = sshbuf_put_u64(msg, st->f_namemax)) != 0) fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } /* * Prepare SSH2_FXP_VERSION extension advertisement for a single extension. * The extension is checked for permission prior to advertisement. */ static int compose_extension(struct sshbuf *msg, const char *name, const char *ver) { int r; const struct sftp_handler *exthnd; if ((exthnd = extended_handler_byname(name)) == NULL) fatal_f("internal error: no handler for %s", name); if (!request_permitted(exthnd)) { debug2_f("refusing to advertise disallowed extension %s", name); return 0; } if ((r = sshbuf_put_cstring(msg, name)) != 0 || (r = sshbuf_put_cstring(msg, ver)) != 0) fatal_fr(r, "compose %s", name); return 0; } /* parse incoming */ static void process_init(void) { struct sshbuf *msg; int r; if ((r = sshbuf_get_u32(iqueue, &version)) != 0) fatal_fr(r, "parse"); verbose("received client version %u", version); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) fatal_fr(r, "compose"); /* extension advertisements */ compose_extension(msg, "posix-rename@openssh.com", "1"); compose_extension(msg, "statvfs@openssh.com", "2"); compose_extension(msg, "fstatvfs@openssh.com", "2"); compose_extension(msg, "hardlink@openssh.com", "1"); compose_extension(msg, "fsync@openssh.com", "1"); compose_extension(msg, "lsetstat@openssh.com", "1"); compose_extension(msg, "limits@openssh.com", "1"); compose_extension(msg, "expand-path@openssh.com", "1"); compose_extension(msg, "copy-data", "1"); compose_extension(msg, "home-directory", "1"); compose_extension(msg, "users-groups-by-id@openssh.com", "1"); send_msg(msg); sshbuf_free(msg); } static void process_open(u_int32_t id) { u_int32_t pflags; Attrib a; char *name; int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ (r = decode_attrib(iqueue, &a)) != 0) fatal_fr(r, "parse"); debug3("request %u: open flags %d", id, pflags); flags = flags_from_portable(pflags); mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && ((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 == -1) { status = errno_to_portable(errno); } else { handle = handle_new(HANDLE_FILE, name, fd, flags, NULL); if (handle < 0) { close(fd); } else { send_handle(id, handle); status = SSH2_FX_OK; } } } if (status != SSH2_FX_OK) send_status(id, status); free(name); } static void process_close(u_int32_t id) { int r, handle, ret, status = SSH2_FX_FAILURE; if ((r = get_handle(iqueue, &handle)) != 0) fatal_fr(r, "parse"); debug3("request %u: close handle %u", id, handle); handle_log_close(handle, NULL); ret = handle_close(handle); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); } static void process_read(u_int32_t id) { static u_char *buf; static size_t buflen; u_int32_t len; int r, handle, fd, ret, status = SSH2_FX_FAILURE; u_int64_t off; if ((r = get_handle(iqueue, &handle)) != 0 || (r = sshbuf_get_u64(iqueue, &off)) != 0 || (r = sshbuf_get_u32(iqueue, &len)) != 0) fatal_fr(r, "parse"); debug("request %u: read \"%s\" (handle %d) off %llu len %u", id, handle_to_name(handle), handle, (unsigned long long)off, len); if ((fd = handle_to_fd(handle)) == -1) goto out; if (len > SFTP_MAX_READ_LENGTH) { debug2("read change len %u to %u", len, SFTP_MAX_READ_LENGTH); len = SFTP_MAX_READ_LENGTH; } if (len > buflen) { debug3_f("allocate %zu => %u", buflen, len); if ((buf = realloc(buf, len)) == NULL) fatal_f("realloc failed"); buflen = len; } if (lseek(fd, off, SEEK_SET) == -1) { status = errno_to_portable(errno); error_f("seek \"%.100s\": %s", handle_to_name(handle), strerror(errno)); goto out; } if (len == 0) { /* weird, but not strictly disallowed */ ret = 0; } else if ((ret = read(fd, buf, len)) == -1) { status = errno_to_portable(errno); error_f("read \"%.100s\": %s", handle_to_name(handle), strerror(errno)); goto out; } else if (ret == 0) { status = SSH2_FX_EOF; goto out; } send_data(id, buf, ret); handle_update_read(handle, ret); /* success */ status = SSH2_FX_OK; out: if (status != SSH2_FX_OK) send_status(id, status); } static void process_write(u_int32_t id) { u_int64_t off; size_t len; int r, handle, fd, ret, status; u_char *data; if ((r = get_handle(iqueue, &handle)) != 0 || (r = sshbuf_get_u64(iqueue, &off)) != 0 || (r = sshbuf_get_string(iqueue, &data, &len)) != 0) fatal_fr(r, "parse"); debug("request %u: write \"%s\" (handle %d) off %llu len %zu", id, handle_to_name(handle), handle, (unsigned long long)off, len); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else { if (!(handle_to_flags(handle) & O_APPEND) && lseek(fd, off, SEEK_SET) == -1) { status = errno_to_portable(errno); error_f("seek \"%.100s\": %s", handle_to_name(handle), strerror(errno)); } else { /* XXX ATOMICIO ? */ ret = write(fd, data, len); if (ret == -1) { status = errno_to_portable(errno); error_f("write \"%.100s\": %s", handle_to_name(handle), strerror(errno)); } else if ((size_t)ret == len) { status = SSH2_FX_OK; handle_update_write(handle, ret); } else { debug2_f("nothing at all written"); status = SSH2_FX_FAILURE; } } } send_status(id, status); free(data); } static void process_do_stat(u_int32_t id, int do_lstat) { Attrib a; struct stat st; char *name; int r, status = SSH2_FX_FAILURE; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) fatal_fr(r, "parse"); 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 == -1) { status = errno_to_portable(errno); } else { stat_to_attrib(&st, &a); send_attrib(id, &a); status = SSH2_FX_OK; } if (status != SSH2_FX_OK) send_status(id, status); free(name); } static void process_stat(u_int32_t id) { process_do_stat(id, 0); } static void process_lstat(u_int32_t id) { process_do_stat(id, 1); } static void process_fstat(u_int32_t id) { Attrib a; struct stat st; int fd, r, handle, status = SSH2_FX_FAILURE; if ((r = get_handle(iqueue, &handle)) != 0) fatal_fr(r, "parse"); debug("request %u: fstat \"%s\" (handle %u)", id, handle_to_name(handle), handle); fd = handle_to_fd(handle); if (fd >= 0) { r = fstat(fd, &st); if (r == -1) { status = errno_to_portable(errno); } else { stat_to_attrib(&st, &a); send_attrib(id, &a); status = SSH2_FX_OK; } } if (status != SSH2_FX_OK) send_status(id, status); } static struct timeval * attrib_to_tv(const Attrib *a) { static struct timeval tv[2]; tv[0].tv_sec = a->atime; tv[0].tv_usec = 0; tv[1].tv_sec = a->mtime; tv[1].tv_usec = 0; 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) { 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_fr(r, "parse"); debug("request %u: setstat name \"%s\"", id, name); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a.size); r = truncate(name, a.size); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", name, a.perm); r = chmod(name, a.perm & 07777); 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 = utimes(name, attrib_to_tv(&a)); 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 = chown(name, a.uid, a.gid); if (r == -1) status = errno_to_portable(errno); } send_status(id, status); free(name); } static void process_fsetstat(u_int32_t id) { Attrib a; int handle, fd, r; int status = SSH2_FX_OK; if ((r = get_handle(iqueue, &handle)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) fatal_fr(r, "parse"); debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else { char *name = handle_to_name(handle); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a.size); r = ftruncate(fd, a.size); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", name, a.perm); #ifdef HAVE_FCHMOD r = fchmod(fd, a.perm & 07777); #else r = chmod(name, a.perm & 07777); #endif 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); #ifdef HAVE_FUTIMES r = futimes(fd, attrib_to_tv(&a)); #else r = utimes(name, attrib_to_tv(&a)); #endif 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); #ifdef HAVE_FCHOWN r = fchown(fd, a.uid, a.gid); #else r = chown(name, a.uid, a.gid); #endif if (r == -1) status = errno_to_portable(errno); } } send_status(id, status); } static void process_opendir(u_int32_t id) { DIR *dirp = NULL; char *path; int r, handle, status = SSH2_FX_FAILURE; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: opendir", id); logit("opendir \"%s\"", path); dirp = opendir(path); if (dirp == NULL) { status = errno_to_portable(errno); } else { handle = handle_new(HANDLE_DIR, path, 0, 0, dirp); if (handle < 0) { closedir(dirp); } else { send_handle(id, handle); status = SSH2_FX_OK; } } if (status != SSH2_FX_OK) send_status(id, status); free(path); } static void process_readdir(u_int32_t id) { DIR *dirp; struct dirent *dp; char *path; int r, handle; if ((r = get_handle(iqueue, &handle)) != 0) fatal_fr(r, "parse"); debug("request %u: readdir \"%s\" (handle %d)", id, handle_to_name(handle), handle); dirp = handle_to_dir(handle); path = handle_to_name(handle); if (dirp == NULL || path == NULL) { send_status(id, SSH2_FX_FAILURE); } else { struct stat st; char pathname[PATH_MAX]; Stat *stats; int nstats = 10, count = 0, i; stats = xcalloc(nstats, sizeof(Stat)); while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { nstats *= 2; 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) == -1) continue; stat_to_attrib(&st, &(stats[count].attrib)); stats[count].name = xstrdup(dp->d_name); stats[count].long_name = ls_file(dp->d_name, &st, 0, 0, NULL, NULL); count++; /* send up to 100 entries in one message */ /* XXX check packet size instead */ if (count == 100) break; } if (count > 0) { send_names(id, count, stats); for (i = 0; i < count; i++) { free(stats[i].name); free(stats[i].long_name); } } else { send_status(id, SSH2_FX_EOF); } free(stats); } } static void process_remove(u_int32_t id) { char *name; int r, status = SSH2_FX_FAILURE; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: remove", id); logit("remove name \"%s\"", name); r = unlink(name); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(name); } static void process_mkdir(u_int32_t id) { Attrib a; char *name; int r, mode, status = SSH2_FX_FAILURE; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) fatal_fr(r, "parse"); mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm & 07777 : 0777; debug3("request %u: mkdir", id); logit("mkdir name \"%s\" mode 0%o", name, mode); r = mkdir(name, mode); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(name); } static void process_rmdir(u_int32_t id) { char *name; int r, status; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: rmdir", id); logit("rmdir name \"%s\"", name); r = rmdir(name); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(name); } static void process_realpath(u_int32_t id) { char resolvedname[PATH_MAX]; char *path; int r; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal_fr(r, "parse"); if (path[0] == '\0') { free(path); path = xstrdup("."); } debug3("request %u: realpath", id); verbose("realpath \"%s\"", path); if (sftp_realpath(path, resolvedname) == NULL) { send_status(id, errno_to_portable(errno)); } else { Stat s; attrib_clear(&s.attrib); s.name = s.long_name = resolvedname; send_names(id, 1, &s); } free(path); } static void process_rename(u_int32_t id) { char *oldpath, *newpath; int r, status; struct stat sb; if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: rename", id); logit("rename old \"%s\" new \"%s\"", oldpath, newpath); status = SSH2_FX_FAILURE; if (lstat(oldpath, &sb) == -1) status = errno_to_portable(errno); else if (S_ISREG(sb.st_mode)) { /* Race-free rename of regular files */ if (link(oldpath, newpath) == -1) { if (errno == EOPNOTSUPP || errno == ENOSYS #ifdef EXDEV || errno == EXDEV #endif #ifdef LINK_OPNOTSUPP_ERRNO || errno == LINK_OPNOTSUPP_ERRNO #endif ) { struct stat st; /* * fs doesn't support links, so fall back to * stat+rename. This is racy. */ if (stat(newpath, &st) == -1) { if (rename(oldpath, newpath) == -1) status = errno_to_portable(errno); else status = SSH2_FX_OK; } } else { status = errno_to_portable(errno); } } else if (unlink(oldpath) == -1) { status = errno_to_portable(errno); /* clean spare link */ unlink(newpath); } else status = SSH2_FX_OK; } else if (stat(newpath, &sb) == -1) { if (rename(oldpath, newpath) == -1) status = errno_to_portable(errno); else status = SSH2_FX_OK; } send_status(id, status); free(oldpath); free(newpath); } static void process_readlink(u_int32_t id) { int r, len; char buf[PATH_MAX]; char *path; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: readlink", id); verbose("readlink \"%s\"", path); if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) send_status(id, errno_to_portable(errno)); else { Stat s; buf[len] = '\0'; attrib_clear(&s.attrib); s.name = s.long_name = buf; send_names(id, 1, &s); } free(path); } static void process_symlink(u_int32_t id) { char *oldpath, *newpath; int r, status; if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: symlink", id); logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); /* this will fail if 'newpath' exists */ r = symlink(oldpath, newpath); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(oldpath); free(newpath); } static void process_extended_posix_rename(u_int32_t id) { char *oldpath, *newpath; int r, status; if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: posix-rename", id); logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); r = rename(oldpath, newpath); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(oldpath); free(newpath); } static void process_extended_statvfs(u_int32_t id) { char *path; struct statvfs st; int r; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: statvfs", id); logit("statvfs \"%s\"", path); if (statvfs(path, &st) != 0) send_status(id, errno_to_portable(errno)); else send_statvfs(id, &st); free(path); } static void process_extended_fstatvfs(u_int32_t id) { int r, handle, fd; struct statvfs st; if ((r = get_handle(iqueue, &handle)) != 0) fatal_fr(r, "parse"); debug("request %u: fstatvfs \"%s\" (handle %u)", id, handle_to_name(handle), handle); if ((fd = handle_to_fd(handle)) < 0) { send_status(id, SSH2_FX_FAILURE); return; } if (fstatvfs(fd, &st) != 0) send_status(id, errno_to_portable(errno)); else send_statvfs(id, &st); } static void process_extended_hardlink(u_int32_t id) { char *oldpath, *newpath; int r, status; if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: hardlink", id); logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); r = link(oldpath, newpath); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(oldpath); free(newpath); } static void process_extended_fsync(u_int32_t id) { int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED; if ((r = get_handle(iqueue, &handle)) != 0) fatal_fr(r, "parse"); debug3("request %u: fsync (handle %u)", id, handle); verbose("fsync \"%s\"", handle_to_name(handle)); if ((fd = handle_to_fd(handle)) < 0) status = SSH2_FX_NO_SUCH_FILE; else if (handle_is_ok(handle, HANDLE_FILE)) { r = fsync(fd); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; } send_status(id, status); } 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_fr(r, "parse"); 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_limits(u_int32_t id) { struct sshbuf *msg; int r; uint64_t nfiles = 0; #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) struct rlimit rlim; #endif debug("request %u: limits", id); #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur > 5) nfiles = rlim.rlim_cur - 5; /* stdio(3) + syslog + spare */ #endif if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || /* max-packet-length */ (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH)) != 0 || /* max-read-length */ (r = sshbuf_put_u64(msg, SFTP_MAX_READ_LENGTH)) != 0 || /* max-write-length */ (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH - 1024)) != 0 || /* max-open-handles */ (r = sshbuf_put_u64(msg, nfiles)) != 0) fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } static void process_extended_expand(u_int32_t id) { char cwd[PATH_MAX], resolvedname[PATH_MAX]; char *path, *npath; int r; Stat s; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal_fr(r, "parse"); if (getcwd(cwd, sizeof(cwd)) == NULL) { send_status(id, errno_to_portable(errno)); goto out; } debug3("request %u: expand, original \"%s\"", id, path); if (path[0] == '\0') { /* empty path */ free(path); path = xstrdup("."); } else if (*path == '~') { /* ~ expand path */ /* Special-case for "~" and "~/" to respect homedir flag */ if (strcmp(path, "~") == 0) { free(path); path = xstrdup(cwd); } else if (strncmp(path, "~/", 2) == 0) { npath = xstrdup(path + 2); free(path); xasprintf(&path, "%s/%s", cwd, npath); free(npath); } else { /* ~user expansions */ if (tilde_expand(path, pw->pw_uid, &npath) != 0) { send_status_errmsg(id, errno_to_portable(ENOENT), "no such user"); goto out; } free(path); path = npath; } } else if (*path != '/') { /* relative path */ xasprintf(&npath, "%s/%s", cwd, path); free(path); path = npath; } verbose("expand \"%s\"", path); if (sftp_realpath(path, resolvedname) == NULL) { send_status(id, errno_to_portable(errno)); goto out; } attrib_clear(&s.attrib); s.name = s.long_name = resolvedname; send_names(id, 1, &s); out: free(path); } static void process_extended_copy_data(u_int32_t id) { u_char buf[64*1024]; int read_handle, read_fd, write_handle, write_fd; u_int64_t len, read_off, read_len, write_off; int r, copy_until_eof, status = SSH2_FX_OP_UNSUPPORTED; size_t ret; if ((r = get_handle(iqueue, &read_handle)) != 0 || (r = sshbuf_get_u64(iqueue, &read_off)) != 0 || (r = sshbuf_get_u64(iqueue, &read_len)) != 0 || (r = get_handle(iqueue, &write_handle)) != 0 || (r = sshbuf_get_u64(iqueue, &write_off)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: copy-data from \"%s\" (handle %d) off %llu len %llu " "to \"%s\" (handle %d) off %llu", id, handle_to_name(read_handle), read_handle, (unsigned long long)read_off, (unsigned long long)read_len, handle_to_name(write_handle), write_handle, (unsigned long long)write_off); /* For read length of 0, we read until EOF. */ if (read_len == 0) { read_len = (u_int64_t)-1 - read_off; copy_until_eof = 1; } else copy_until_eof = 0; read_fd = handle_to_fd(read_handle); write_fd = handle_to_fd(write_handle); /* Disallow reading & writing to the same handle or same path or dirs */ if (read_handle == write_handle || read_fd < 0 || write_fd < 0 || !strcmp(handle_to_name(read_handle), handle_to_name(write_handle))) { status = SSH2_FX_FAILURE; goto out; } if (lseek(read_fd, read_off, SEEK_SET) < 0) { status = errno_to_portable(errno); error("%s: read_seek failed", __func__); goto out; } if ((handle_to_flags(write_handle) & O_APPEND) == 0 && lseek(write_fd, write_off, SEEK_SET) < 0) { status = errno_to_portable(errno); error("%s: write_seek failed", __func__); goto out; } /* Process the request in chunks. */ while (read_len > 0 || copy_until_eof) { len = MINIMUM(sizeof(buf), read_len); read_len -= len; ret = atomicio(read, read_fd, buf, len); if (ret == 0 && errno == EPIPE) { status = copy_until_eof ? SSH2_FX_OK : SSH2_FX_EOF; break; } else if (ret == 0) { status = errno_to_portable(errno); error("%s: read failed: %s", __func__, strerror(errno)); break; } len = ret; handle_update_read(read_handle, len); ret = atomicio(vwrite, write_fd, buf, len); if (ret != len) { status = errno_to_portable(errno); error("%s: write failed: %llu != %llu: %s", __func__, (unsigned long long)ret, (unsigned long long)len, strerror(errno)); break; } handle_update_write(write_handle, len); } if (read_len == 0) status = SSH2_FX_OK; out: send_status(id, status); } static void process_extended_home_directory(u_int32_t id) { char *username; struct passwd *user_pw; int r; Stat s; if ((r = sshbuf_get_cstring(iqueue, &username, NULL)) != 0) fatal_fr(r, "parse"); debug3("request %u: home-directory \"%s\"", id, username); if (username[0] == '\0') { user_pw = pw; } else if ((user_pw = getpwnam(username)) == NULL) { send_status(id, SSH2_FX_FAILURE); goto out; } verbose("home-directory \"%s\"", user_pw->pw_dir); attrib_clear(&s.attrib); s.name = s.long_name = user_pw->pw_dir; send_names(id, 1, &s); out: free(username); } static void process_extended_get_users_groups_by_id(u_int32_t id) { struct passwd *user_pw; struct group *gr; struct sshbuf *uids, *gids, *usernames, *groupnames, *msg; int r; u_int n, nusers = 0, ngroups = 0; const char *name; if ((usernames = sshbuf_new()) == NULL || (groupnames = sshbuf_new()) == NULL || (msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_froms(iqueue, &uids)) != 0 || (r = sshbuf_froms(iqueue, &gids)) != 0) fatal_fr(r, "parse"); debug_f("uids len = %zu, gids len = %zu", sshbuf_len(uids), sshbuf_len(gids)); while (sshbuf_len(uids) != 0) { if ((r = sshbuf_get_u32(uids, &n)) != 0) fatal_fr(r, "parse inner uid"); user_pw = getpwuid((uid_t)n); name = user_pw == NULL ? "" : user_pw->pw_name; debug3_f("uid %u => \"%s\"", n, name); if ((r = sshbuf_put_cstring(usernames, name)) != 0) fatal_fr(r, "assemble uid reply"); nusers++; } while (sshbuf_len(gids) != 0) { if ((r = sshbuf_get_u32(gids, &n)) != 0) fatal_fr(r, "parse inner gid"); gr = getgrgid((gid_t)n); name = gr == NULL ? "" : gr->gr_name; debug3_f("gid %u => \"%s\"", n, name); if ((r = sshbuf_put_cstring(groupnames, name)) != 0) fatal_fr(r, "assemble gid reply"); nusers++; } verbose("users-groups-by-id: %u users, %u groups", nusers, ngroups); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_stringb(msg, usernames)) != 0 || (r = sshbuf_put_stringb(msg, groupnames)) != 0) fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(uids); sshbuf_free(gids); sshbuf_free(usernames); sshbuf_free(groupnames); sshbuf_free(msg); } static void process_extended(u_int32_t id) { char *request; int r; const struct sftp_handler *exthand; if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0) fatal_fr(r, "parse"); if ((exthand = extended_handler_byname(request)) == NULL) { error("Unknown extended request \"%.100s\"", request); send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ } else { if (!request_permitted(exthand)) send_status(id, SSH2_FX_PERMISSION_DENIED); else exthand->handler(id); } free(request); } /* stolen from ssh-agent */ static void process(void) { u_int msg_len; u_int buf_len; u_int consumed; u_char type; const u_char *cp; int i, r; u_int32_t id; buf_len = sshbuf_len(iqueue); if (buf_len < 5) return; /* Incomplete message. */ cp = sshbuf_ptr(iqueue); msg_len = get_u32(cp); if (msg_len > SFTP_MAX_MSG_LENGTH) { error("bad message from %s local user %s", client_addr, pw->pw_name); sftp_server_cleanup_exit(11); } if (buf_len < msg_len + 4) return; if ((r = sshbuf_consume(iqueue, 4)) != 0) fatal_fr(r, "consume"); buf_len -= 4; if ((r = sshbuf_get_u8(iqueue, &type)) != 0) fatal_fr(r, "parse type"); switch (type) { case SSH2_FXP_INIT: process_init(); init_done = 1; break; case SSH2_FXP_EXTENDED: if (!init_done) fatal("Received extended request before init"); if ((r = sshbuf_get_u32(iqueue, &id)) != 0) fatal_fr(r, "parse extended ID"); process_extended(id); break; default: if (!init_done) fatal("Received %u request before init", type); if ((r = sshbuf_get_u32(iqueue, &id)) != 0) fatal_fr(r, "parse ID"); for (i = 0; handlers[i].handler != NULL; i++) { if (type == handlers[i].type) { if (!request_permitted(&handlers[i])) { send_status(id, SSH2_FX_PERMISSION_DENIED); } else { handlers[i].handler(id); } break; } } if (handlers[i].handler == NULL) error("Unknown message %u", type); } /* discard the remaining bytes from the current packet */ if (buf_len < sshbuf_len(iqueue)) { error("iqueue grew unexpectedly"); sftp_server_cleanup_exit(255); } consumed = buf_len - sshbuf_len(iqueue); if (msg_len < consumed) { error("msg_len %u < consumed %u", msg_len, consumed); sftp_server_cleanup_exit(255); } if (msg_len > consumed && (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) fatal_fr(r, "consume"); } /* Cleanup handler that logs active handles upon normal exit */ void sftp_server_cleanup_exit(int i) { if (pw != NULL && client_addr != NULL) { handle_log_exit(); logit("session closed for local user %s from [%s]", pw->pw_name, client_addr); } _exit(i); } static void sftp_server_usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-ehR] [-d start_directory] [-f log_facility] " "[-l log_level]\n\t[-P denied_requests] " "[-p allowed_requests] [-u umask]\n" " %s -Q protocol_feature\n", __progname, __progname); exit(1); } int sftp_server_main(int argc, char **argv, struct passwd *user_pw) { int i, r, in, out, ch, skipargs = 0, log_stderr = 0; ssize_t len, olen; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; char *cp, *homedir = NULL, uidstr[32], buf[4*4096]; long mask; extern char *optarg; extern char *__progname; __progname = ssh_get_progname(argv[0]); log_init(__progname, log_level, log_facility, log_stderr); pw = pwcopy(user_pw); while (!skipargs && (ch = getopt(argc, argv, "d:f:l:P:p:Q:u:cehR")) != -1) { switch (ch) { case 'Q': if (strcasecmp(optarg, "requests") != 0) { fprintf(stderr, "Invalid query type\n"); exit(1); } for (i = 0; handlers[i].handler != NULL; i++) printf("%s\n", handlers[i].name); for (i = 0; extended_handlers[i].handler != NULL; i++) printf("%s\n", extended_handlers[i].name); exit(0); break; case 'R': readonly = 1; break; case 'c': /* * Ignore all arguments if we are invoked as a * shell using "sftp-server -c command" */ skipargs = 1; break; case 'e': log_stderr = 1; break; case 'l': log_level = log_level_number(optarg); if (log_level == SYSLOG_LEVEL_NOT_SET) error("Invalid log level \"%s\"", optarg); break; case 'f': log_facility = log_facility_number(optarg); if (log_facility == SYSLOG_FACILITY_NOT_SET) error("Invalid log facility \"%s\"", optarg); 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, "U", uidstr, (char *)NULL); free(cp); break; case 'p': if (request_allowlist != NULL) fatal("Permitted requests already set"); request_allowlist = xstrdup(optarg); break; case 'P': if (request_denylist != NULL) fatal("Refused requests already set"); request_denylist = xstrdup(optarg); break; case 'u': errno = 0; mask = strtol(optarg, &cp, 8); if (mask < 0 || mask > 0777 || *cp != '\0' || cp == optarg || (mask == 0 && errno != 0)) fatal("Invalid umask \"%s\"", optarg); (void)umask((mode_t)mask); break; case 'h': default: sftp_server_usage(); } } log_init(__progname, log_level, log_facility, log_stderr); /* * 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. */ 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); if ((cp = strchr(client_addr, ' ')) == NULL) { error("Malformed SSH_CONNECTION variable: \"%s\"", getenv("SSH_CONNECTION")); sftp_server_cleanup_exit(255); } *cp = '\0'; } else client_addr = xstrdup("UNKNOWN"); logit("session opened for local user %s from [%s]", pw->pw_name, client_addr); in = STDIN_FILENO; out = STDOUT_FILENO; #ifdef HAVE_CYGWIN setmode(in, O_BINARY); setmode(out, O_BINARY); #endif if ((iqueue = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((oqueue = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (homedir != NULL) { if (chdir(homedir) != 0) { error("chdir to \"%s\" failed: %s", homedir, strerror(errno)); } } for (;;) { struct pollfd pfd[2]; memset(pfd, 0, sizeof pfd); pfd[0].fd = pfd[1].fd = -1; /* * 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 ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && (r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH)) == 0) { pfd[0].fd = in; pfd[0].events = POLLIN; } else if (r != SSH_ERR_NO_BUFFER_SPACE) fatal_fr(r, "reserve"); olen = sshbuf_len(oqueue); if (olen > 0) { pfd[1].fd = out; pfd[1].events = POLLOUT; } if (poll(pfd, 2, -1) == -1) { if (errno == EINTR) continue; error("poll: %s", strerror(errno)); sftp_server_cleanup_exit(2); } /* copy stdin to iqueue */ if (pfd[0].revents & (POLLIN|POLLHUP)) { len = read(in, buf, sizeof buf); if (len == 0) { debug("read eof"); sftp_server_cleanup_exit(0); } else if (len == -1) { if (errno != EAGAIN && errno != EINTR) { error("read: %s", strerror(errno)); sftp_server_cleanup_exit(1); } } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) fatal_fr(r, "sshbuf_put"); } /* send oqueue to stdout */ if (pfd[1].revents & (POLLOUT|POLLHUP)) { len = write(out, sshbuf_ptr(oqueue), olen); if (len == 0 || (len == -1 && errno == EPIPE)) { debug("write eof"); sftp_server_cleanup_exit(0); } else if (len == -1) { sftp_server_cleanup_exit(1); if (errno != EAGAIN && errno != EINTR) { error("write: %s", strerror(errno)); sftp_server_cleanup_exit(1); } } else if ((r = sshbuf_consume(oqueue, len)) != 0) fatal_fr(r, "consume"); } /* * Process requests from client if we can fit the results * into the output buffer, otherwise stop processing input * and let the output queue drain. */ r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH); if (r == 0) process(); else if (r != SSH_ERR_NO_BUFFER_SPACE) fatal_fr(r, "reserve"); } } openssh-10.0p1/PaxHeaders.10889/sftp-usergroup.c100644 001750 001750 0000000003614775415623 0016325xustar0030 atime=1744182234.774242093 openssh-10.0p1/sftp-usergroup.c010064400017500001750000000127151477541562300147160ustar00djmdjm/* * Copyright (c) 2022 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. */ /* sftp client user/group lookup and caching */ #include "includes.h" #include #include #include #include #include #include "log.h" #include "xmalloc.h" #include "sftp-common.h" #include "sftp-client.h" #include "sftp-usergroup.h" /* Tree of id, name */ struct idname { u_int id; char *name; RB_ENTRY(idname) entry; /* XXX implement bounded cache as TAILQ */ }; static int idname_cmp(struct idname *a, struct idname *b) { if (a->id == b->id) return 0; return a->id > b->id ? 1 : -1; } RB_HEAD(idname_tree, idname); RB_GENERATE_STATIC(idname_tree, idname, entry, idname_cmp) static struct idname_tree user_idname = RB_INITIALIZER(&user_idname); static struct idname_tree group_idname = RB_INITIALIZER(&group_idname); static void idname_free(struct idname *idname) { if (idname == NULL) return; free(idname->name); free(idname); } static void idname_enter(struct idname_tree *tree, u_int id, const char *name) { struct idname *idname; if ((idname = xcalloc(1, sizeof(*idname))) == NULL) fatal_f("alloc"); idname->id = id; idname->name = xstrdup(name); if (RB_INSERT(idname_tree, tree, idname) != NULL) idname_free(idname); } static const char * idname_lookup(struct idname_tree *tree, u_int id) { struct idname idname, *found; memset(&idname, 0, sizeof(idname)); idname.id = id; if ((found = RB_FIND(idname_tree, tree, &idname)) != NULL) return found->name; return NULL; } static void freenames(char **names, u_int nnames) { u_int i; if (names == NULL) return; for (i = 0; i < nnames; i++) free(names[i]); free(names); } static void lookup_and_record(struct sftp_conn *conn, u_int *uids, u_int nuids, u_int *gids, u_int ngids) { int r; u_int i; char **usernames = NULL, **groupnames = NULL; if ((r = sftp_get_users_groups_by_id(conn, uids, nuids, gids, ngids, &usernames, &groupnames)) != 0) { debug_fr(r, "sftp_get_users_groups_by_id"); return; } for (i = 0; i < nuids; i++) { if (usernames[i] == NULL) { debug3_f("uid %u not resolved", uids[i]); continue; } debug3_f("record uid %u => \"%s\"", uids[i], usernames[i]); idname_enter(&user_idname, uids[i], usernames[i]); } for (i = 0; i < ngids; i++) { if (groupnames[i] == NULL) { debug3_f("gid %u not resolved", gids[i]); continue; } debug3_f("record gid %u => \"%s\"", gids[i], groupnames[i]); idname_enter(&group_idname, gids[i], groupnames[i]); } freenames(usernames, nuids); freenames(groupnames, ngids); } static int has_id(u_int id, u_int *ids, u_int nids) { u_int i; if (nids == 0) return 0; /* XXX O(N^2) */ for (i = 0; i < nids; i++) { if (ids[i] == id) break; } return i < nids; } static void collect_ids_from_glob(glob_t *g, int user, u_int **idsp, u_int *nidsp) { u_int id, i, n = 0, *ids = NULL; for (i = 0; g->gl_pathv[i] != NULL; i++) { if (user) { if (ruser_name(g->gl_statv[i]->st_uid) != NULL) continue; /* Already seen */ id = (u_int)g->gl_statv[i]->st_uid; } else { if (rgroup_name(g->gl_statv[i]->st_gid) != NULL) continue; /* Already seen */ id = (u_int)g->gl_statv[i]->st_gid; } if (has_id(id, ids, n)) continue; ids = xrecallocarray(ids, n, n + 1, sizeof(*ids)); ids[n++] = id; } *idsp = ids; *nidsp = n; } void get_remote_user_groups_from_glob(struct sftp_conn *conn, glob_t *g) { u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0; if (!sftp_can_get_users_groups_by_id(conn)) return; collect_ids_from_glob(g, 1, &uids, &nuids); collect_ids_from_glob(g, 0, &gids, &ngids); lookup_and_record(conn, uids, nuids, gids, ngids); free(uids); free(gids); } static void collect_ids_from_dirents(SFTP_DIRENT **d, int user, u_int **idsp, u_int *nidsp) { u_int id, i, n = 0, *ids = NULL; for (i = 0; d[i] != NULL; i++) { if (user) { if (ruser_name((uid_t)(d[i]->a.uid)) != NULL) continue; /* Already seen */ id = d[i]->a.uid; } else { if (rgroup_name((gid_t)(d[i]->a.gid)) != NULL) continue; /* Already seen */ id = d[i]->a.gid; } if (has_id(id, ids, n)) continue; ids = xrecallocarray(ids, n, n + 1, sizeof(*ids)); ids[n++] = id; } *idsp = ids; *nidsp = n; } void get_remote_user_groups_from_dirents(struct sftp_conn *conn, SFTP_DIRENT **d) { u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0; if (!sftp_can_get_users_groups_by_id(conn)) return; collect_ids_from_dirents(d, 1, &uids, &nuids); collect_ids_from_dirents(d, 0, &gids, &ngids); lookup_and_record(conn, uids, nuids, gids, ngids); free(uids); free(gids); } const char * ruser_name(uid_t uid) { return idname_lookup(&user_idname, (u_int)uid); } const char * rgroup_name(uid_t gid) { return idname_lookup(&group_idname, (u_int)gid); } openssh-10.0p1/PaxHeaders.10889/sftp-usergroup.h100644 001750 001750 0000000003614775415623 0016332xustar0030 atime=1744182234.774242093 openssh-10.0p1/sftp-usergroup.h010064400017500001750000000022241477541562300147150ustar00djmdjm/* * Copyright (c) 2022 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. */ /* sftp client user/group lookup and caching */ /* Lookup uids/gids and populate cache */ void get_remote_user_groups_from_glob(struct sftp_conn *conn, glob_t *g); void get_remote_user_groups_from_dirents(struct sftp_conn *conn, SFTP_DIRENT **d); /* Return user/group name from cache or NULL if not found */ const char *ruser_name(uid_t uid); const char *rgroup_name(uid_t gid); openssh-10.0p1/PaxHeaders.10889/sftp.0100644 001750 001750 0000000003614775415623 0014211xustar0030 atime=1744182234.774242093 openssh-10.0p1/sftp.0010064400017500001750000000463471477541562300126120ustar00djmdjmSFTP(1) General Commands Manual SFTP(1) NAME sftp M-bM-^@M-^S OpenSSH secure file transfer SYNOPSIS sftp [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher] [-D sftp_server_command] [-F ssh_config] [-i identity_file] [-J destination] [-l limit] [-o ssh_option] [-P port] [-R num_requests] [-S program] [-s subsystem | sftp_server] [-X sftp_option] destination DESCRIPTION sftp is a 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. The destination may be specified either as [user@]host[:path] or as a URI in the form sftp://[user@]host[:port][/path]. If the destination includes a path and it is not a directory, sftp will retrieve files automatically if a non-interactive authentication method is used; otherwise it will do so after successful interactive authentication. If no path is specified, or if the path is a directory, sftp will log in to the specified 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 path to be interpreted as a directory. 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. The options are as follows: -4 Forces sftp to use IPv4 addresses only. -6 Forces sftp to use IPv6 addresses only. -A Allows forwarding of ssh-agent(1) to the remote system. The default is not to forward an authentication agent. -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 to obviate the need to enter a password at connection time (see sshd(8) and ssh-keygen(1) for details). 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, copy, cp, 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*). Echo of the command may be suppressed by prefixing the command with a M-bM-^@M-^X@M-bM-^@M-^Y character. These two prefixes may be combined in any order, for example -@ls /bsd. -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_command Connect directly to a local sftp server (rather than via ssh(1)). A command and arguments may be specified, for example "/path/sftp-server -el debug3". 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). -J destination Connect to the target host by first making an sftp connection to the jump host described by 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 ProxyJump configuration directive. This option is directly passed to ssh(1). -l limit Limits the used bandwidth, specified in Kbit/s. -N Disables quiet mode, e.g. to override the implicit quiet mode set by the -b flag. -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). AddKeysToAgent AddressFamily BatchMode BindAddress BindInterface CASignatureAlgorithms CanonicalDomains CanonicalizeFallbackLocal CanonicalizeHostname CanonicalizeMaxDots CanonicalizePermittedCNAMEs CertificateFile ChannelTimeout CheckHostIP Ciphers ClearAllForwardings Compression ConnectTimeout ConnectionAttempts ControlMaster ControlPath ControlPersist DynamicForward EnableEscapeCommandline EnableSSHKeysign EscapeChar ExitOnForwardFailure FingerprintHash ForkAfterAuthentication ForwardAgent ForwardX11 ForwardX11Timeout ForwardX11Trusted GSSAPIAuthentication GSSAPIDelegateCredentials GatewayPorts GlobalKnownHostsFile HashKnownHosts Host HostKeyAlgorithms HostKeyAlias HostbasedAcceptedAlgorithms HostbasedAuthentication Hostname IPQoS IdentitiesOnly IdentityAgent IdentityFile IgnoreUnknown Include KbdInteractiveAuthentication KbdInteractiveDevices KexAlgorithms KnownHostsCommand LocalCommand LocalForward LogLevel LogVerbose MACs NoHostAuthenticationForLocalhost NumberOfPasswordPrompts ObscureKeystrokeTiming PKCS11Provider PasswordAuthentication PermitLocalCommand PermitRemoteOpen Port PreferredAuthentications ProxyCommand ProxyJump ProxyUseFdpass PubkeyAcceptedAlgorithms PubkeyAuthentication RekeyLimit RemoteCommand RemoteForward RequestTTY RequiredRSASize RevokedHostKeys SecurityKeyProvider SendEnv ServerAliveCountMax ServerAliveInterval SessionType SetEnv StdinNull StreamLocalBindMask StreamLocalBindUnlink StrictHostKeyChecking SyslogFacility TCPKeepAlive Tag Tunnel TunnelDevice UpdateHostKeys User UserKnownHostsFile VerifyHostKeyDNS VisualHostKey XAuthLocation -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 when the remote sshd(8) does not have an sftp subsystem configured. -v Raise logging level. This option is also passed to ssh. -X sftp_option Specify an option that controls aspects of SFTP protocol behaviour. The valid options are: nrequests=value Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download or upload. By default 64 requests may be active concurrently. buffer=value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By default a 32KB buffer is used. 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. If path is not specified, then change directory to the one the session started in. chgrp [-h] grp path Change group of file path to grp. path may contain glob(7) characters and may match multiple files. grp must be a numeric GID. If the -h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. chmod [-h] mode path Change permissions of file path to mode. path may contain glob(7) characters and may match multiple files. If the -h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. chown [-h] own path Change owner of file path to own. path may contain glob(7) characters and may match multiple files. own must be a numeric UID. If the -h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. copy oldpath newpath Copy remote file from oldpath to newpath. Note that this is only supported by servers that implement the "copy-data" extension. cp oldpath newpath Alias to copy command. 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 [-afpR] 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(7) 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 the -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. If path is not specified, then change directory to the local user's home directory. 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(7) 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(7) 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 [-afpR] 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(7) 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 the -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 [-fpR] remote-path [local-path] Resume download of remote-path. Equivalent to get with the -a flag set. reput [-fpR] 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), ssh_config(5), glob(7), 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 7.6 December 6, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/sftp.1100644 001750 001750 0000000003614775415623 0014212xustar0030 atime=1744182234.774242093 openssh-10.0p1/sftp.1010064400017500001750000000432071477541562300126030ustar00djmdjm.\" $OpenBSD: sftp.1,v 1.144 2024/12/06 15:12:56 djm Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .Dd $Mdocdate: December 6 2024 $ .Dt SFTP 1 .Os .Sh NAME .Nm sftp .Nd OpenSSH secure file transfer .Sh SYNOPSIS .Nm sftp .Op Fl 46AaCfNpqrv .Op Fl B Ar buffer_size .Op Fl b Ar batchfile .Op Fl c Ar cipher .Op Fl D Ar sftp_server_command .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 .Op Fl X Ar sftp_option .Ar destination .Sh DESCRIPTION .Nm 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. .Pp 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 If no .Ar path is specified, or if the .Ar path is a directory, .Nm 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 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 4 Forces .Nm to use IPv4 addresses only. .It Fl 6 Forces .Nm to use IPv6 addresses only. .It Fl A Allows forwarding of .Xr ssh-agent 1 to the remote system. The default is not to forward an authentication agent. .It Fl a Attempt to continue interrupted transfers rather than overwriting existing partial or complete copies of files. If the partial contents differ from those being transferred, then the resultant file is likely to be corrupt. .It Fl B Ar buffer_size Specify the size of the buffer that .Nm uses when transferring files. Larger buffers require fewer round trips at the cost of higher memory consumption. The default is 32768 bytes. .It Fl b Ar batchfile Batch mode reads a series of commands from an input .Ar batchfile instead of .Em stdin . Since it lacks user interaction, it should be used in conjunction with 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 .Sq \- 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 rm , mkdir , chdir , ls , .Ic lchdir , copy , cp , 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 flag). .It Fl c Ar cipher Selects the cipher to use for encrypting the data transfers. This option is directly passed to .Xr ssh 1 . .It Fl D Ar sftp_server_command Connect directly to a local sftp server (rather than via .Xr ssh 1 ) . A command and arguments may be specified, for example .Qq /path/sftp-server -el debug3 . This option may be useful in debugging the client and server. .It Fl F Ar ssh_config Specifies an alternative per-user configuration file for .Xr ssh 1 . This option is directly passed to .Xr ssh 1 . .It Fl 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. .It Fl i Ar identity_file 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 in the format used in .Xr ssh_config 5 . This is useful for specifying options for which there is no separate .Nm sftp command-line flag. For example, to specify an alternate port use: .Ic sftp -oPort=24 . For full details of the options listed below, and their possible values, see .Xr ssh_config 5 . .Pp .Bl -tag -width Ds -offset indent -compact .It AddKeysToAgent .It AddressFamily .It BatchMode .It BindAddress .It BindInterface .It CASignatureAlgorithms .It CanonicalDomains .It CanonicalizeFallbackLocal .It CanonicalizeHostname .It CanonicalizeMaxDots .It CanonicalizePermittedCNAMEs .It CertificateFile .It ChannelTimeout .It CheckHostIP .It Ciphers .It ClearAllForwardings .It Compression .It ConnectTimeout .It ConnectionAttempts .It ControlMaster .It ControlPath .It ControlPersist .It DynamicForward .It EnableEscapeCommandline .It EnableSSHKeysign .It EscapeChar .It ExitOnForwardFailure .It FingerprintHash .It ForkAfterAuthentication .It ForwardAgent .It ForwardX11 .It ForwardX11Timeout .It ForwardX11Trusted .It GSSAPIAuthentication .It GSSAPIDelegateCredentials .It GatewayPorts .It GlobalKnownHostsFile .It HashKnownHosts .It Host .It HostKeyAlgorithms .It HostKeyAlias .It HostbasedAcceptedAlgorithms .It HostbasedAuthentication .It Hostname .It IPQoS .It IdentitiesOnly .It IdentityAgent .It IdentityFile .It IgnoreUnknown .It Include .It KbdInteractiveAuthentication .It KbdInteractiveDevices .It KexAlgorithms .It KnownHostsCommand .It LocalCommand .It LocalForward .It LogLevel .It LogVerbose .It MACs .It NoHostAuthenticationForLocalhost .It NumberOfPasswordPrompts .It ObscureKeystrokeTiming .It PKCS11Provider .It PasswordAuthentication .It PermitLocalCommand .It PermitRemoteOpen .It Port .It PreferredAuthentications .It ProxyCommand .It ProxyJump .It ProxyUseFdpass .It PubkeyAcceptedAlgorithms .It PubkeyAuthentication .It RekeyLimit .It RemoteCommand .It RemoteForward .It RequestTTY .It RequiredRSASize .It RevokedHostKeys .It SecurityKeyProvider .It SendEnv .It ServerAliveCountMax .It ServerAliveInterval .It SessionType .It SetEnv .It StdinNull .It StreamLocalBindMask .It StreamLocalBindUnlink .It StrictHostKeyChecking .It SyslogFacility .It TCPKeepAlive .It Tag .It Tunnel .It TunnelDevice .It UpdateHostKeys .It User .It UserKnownHostsFile .It VerifyHostKeyDNS .It VisualHostKey .It XAuthLocation .El .It Fl P Ar port Specifies the port to connect to on the remote host. .It Fl p Preserves modification times, access times, and modes from the original files transferred. .It Fl q Quiet mode: disables the progress meter as well as warning and diagnostic messages from .Xr ssh 1 . .It Fl R Ar 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. .It Fl r Recursively copy entire directories when uploading and downloading. Note that .Nm does not follow symbolic links encountered in the tree traversal. .It Fl S Ar program Name of the .Ar program to use for the encrypted connection. The program must understand .Xr ssh 1 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 when the remote .Xr sshd 8 does not have an sftp subsystem configured. .It Fl v Raise logging level. This option is also passed to ssh. .It Fl X Ar sftp_option Specify an option that controls aspects of SFTP protocol behaviour. The valid options are: .Bl -tag -width Ds .It Cm nrequests Ns = Ns Ar value Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download or upload. By default 64 requests may be active concurrently. .It Cm buffer Ns = Ns Ar value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By default a 32KB buffer is used. .El .El .Sh INTERACTIVE COMMANDS Once in interactive mode, .Nm understands a set of commands similar to those of .Xr 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 .Xr glob 3 must be escaped with backslashes .Pq Sq \e . .Bl -tag -width Ds .It Ic bye Quit .Nm sftp . .It Ic cd Op Ar path Change remote directory to .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 . .Ar path may contain .Xr glob 7 characters and may match multiple files. .Ar grp must be a numeric GID. .Pp If the .Fl h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. .It Xo Ic chmod .Op Fl h .Ar mode .Ar path .Xc Change permissions of file .Ar path to .Ar mode . .Ar path may contain .Xr glob 7 characters and may match multiple files. .Pp If the .Fl h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. .It Xo Ic chown .Op Fl h .Ar own .Ar path .Xc Change owner of file .Ar path to .Ar own . .Ar path may contain .Xr glob 7 characters and may match multiple files. .Ar own must be a numeric UID. .Pp If the .Fl h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. .It Ic copy Ar oldpath Ar newpath Copy remote file from .Ar oldpath to .Ar newpath . .Pp Note that this is only supported by servers that implement the "copy-data" extension. .It Ic cp Ar oldpath Ar newpath Alias to .Ic copy command. .It Xo Ic df .Op Fl hi .Op Ar path .Xc Display usage information for the filesystem holding the current directory (or .Ar path if specified). If the .Fl h flag is specified, the capacity information will be displayed using "human-readable" suffixes. The .Fl i flag requests display of inode information in addition to capacity information. This command is only supported on servers that implement the .Dq statvfs@openssh.com extension. .It Ic exit Quit .Nm sftp . .It Xo Ic get .Op Fl afpR .Ar remote-path .Op Ar local-path .Xc Retrieve the .Ar 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. .Ar remote-path may contain .Xr glob 7 characters and may match multiple files. If it does and .Ar local-path is specified, then .Ar local-path must specify a directory. .Pp If the .Fl 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. .Pp If the .Fl f flag is specified, then .Xr fsync 2 will be called after the file transfer has completed to flush the file to disk. .Pp 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 .\" 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 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 or current directory if .Ar path is not specified. .Ar ls-options may contain any flags supported by the local system's .Xr ls 1 command. .Ar path may contain .Xr glob 7 characters and may match multiple files. .It Ic lmkdir Ar path Create local directory specified by .Ar path . .It Xo Ic ln .Op Fl s .Ar oldpath .Ar newpath .Xc Create a link from .Ar oldpath to .Ar newpath . If the .Fl s flag is specified the created link is a symbolic link, otherwise it is a hard link. .It Ic lpwd Print local working directory. .It Xo Ic ls .Op Fl 1afhlnrSt .Op Ar path .Xc Display a remote directory listing of either .Ar path or the current directory if .Ar path is not specified. .Ar path may contain .Xr glob 7 characters and may match multiple files. .Pp The following flags are recognized and alter the behaviour of .Ic ls accordingly: .Bl -tag -width Ds .It Fl 1 Produce single columnar output. .It Fl a List files beginning with a dot .Pq Sq \&. . .It Fl f Do not sort the listing. The default sort order is lexicographical. .It Fl 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.). .It Fl l Display additional details including permissions and ownership information. .It Fl n Produce a long listing with user and group information presented numerically. .It Fl r Reverse the sort order of the listing. .It Fl S Sort the listing by file size. .It Fl t Sort the listing by last modification time. .El .It Ic lumask Ar umask Set local umask to .Ar umask . .It Ic mkdir Ar path Create remote directory specified by .Ar path . .It Ic progress Toggle display of progress meter. .It Xo Ic put .Op Fl afpR .Ar local-path .Op Ar remote-path .Xc Upload .Ar 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. .Ar local-path may contain .Xr glob 7 characters and may match multiple files. If it does and .Ar remote-path is specified, then .Ar remote-path must specify a directory. .Pp If the .Fl 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. .Pp If the .Fl f flag is specified, then a request will be sent to the server to call .Xr fsync 2 after the file has been transferred. Note that this is only supported by servers that implement the "fsync@openssh.com" extension. .Pp 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 .\" 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 pwd Display remote working directory. .It Ic quit Quit .Nm sftp . .It Xo Ic reget .Op Fl fpR .Ar remote-path .Op Ar local-path .Xc Resume download of .Ar remote-path . Equivalent to .Ic get with the .Fl a flag set. .It Xo Ic reput .Op Fl fpR .Ar local-path .Op Ar remote-path .Xc Resume upload of .Ar local-path . Equivalent to .Ic put with the .Fl a flag set. .It Ic rename Ar oldpath newpath Rename remote file from .Ar oldpath to .Ar newpath . .It Ic rm Ar path Delete remote file specified by .Ar path . .It Ic rmdir Ar path Remove remote directory specified by .Ar path . .It Ic symlink Ar oldpath newpath Create a symbolic link from .Ar oldpath to .Ar newpath . .It Ic version Display the .Nm protocol version. .It Ic \&! Ns Ar command Execute .Ar command in local shell. .It Ic \&! Escape to local shell. .It Ic \&? Synonym for help. .El .Sh SEE ALSO .Xr ftp 1 , .Xr ls 1 , .Xr scp 1 , .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-keygen 1 , .Xr ssh_config 5 , .Xr glob 7 , .Xr sftp-server 8 , .Xr sshd 8 .Rs .%A T. Ylonen .%A S. Lehtinen .%T "SSH File Transfer Protocol" .%N draft-ietf-secsh-filexfer-00.txt .%D January 2001 .%O work in progress material .Re openssh-10.0p1/PaxHeaders.10889/sftp.c100644 001750 001750 0000000003614775415623 0014274xustar0030 atime=1744182234.784985614 openssh-10.0p1/sftp.c010064400017500001750000001774641477541562300127020ustar00djmdjm/* $OpenBSD: sftp.c,v 1.240 2025/03/28 06:04:07 dtucker Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #ifdef HAVE_SYS_STAT_H # include #endif #include #include #ifdef HAVE_SYS_STATVFS_H #include #endif #include #include #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_LIBGEN_H #include #endif #ifdef HAVE_LOCALE_H # include #endif #ifdef USE_LIBEDIT #include #else typedef void EditLine; #endif #include #include #include #include #include #include #include #ifdef HAVE_UTIL_H # include #endif #include "xmalloc.h" #include "log.h" #include "pathnames.h" #include "misc.h" #include "utf8.h" #include "sftp.h" #include "ssherr.h" #include "sshbuf.h" #include "sftp-common.h" #include "sftp-client.h" #include "sftp-usergroup.h" /* File to read commands from */ FILE* infile; /* Are we in batchfile mode? */ int batchmode = 0; /* PID of ssh transport process */ static volatile pid_t sshpid = -1; /* Suppress diagnostic messages */ int quiet = 0; /* This is set to 0 if the progressmeter is not desired. */ int showprogress = 1; /* When this option is set, we always recursively download/upload directories */ int global_rflag = 0; /* When this option is set, we resume download or upload if possible */ int global_aflag = 0; /* When this option is set, the file transfers will always preserve times */ int global_pflag = 0; /* When this option is set, transfers will have fsync() called on each file */ int global_fflag = 0; /* SIGINT received during command processing */ 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 { struct sftp_conn *conn; char **remote_pathp; }; int sftp_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ extern char *__progname; /* Separators for interactive commands */ #define WHITESPACE " \t\r\n" /* ls flags */ #define LS_LONG_VIEW 0x0001 /* Full view ala ls -l */ #define LS_SHORT_VIEW 0x0002 /* Single row view ala ls -1 */ #define LS_NUMERIC_VIEW 0x0004 /* Long view with numeric uid/gid */ #define LS_NAME_SORT 0x0008 /* Sort by name (default) */ #define LS_TIME_SORT 0x0010 /* Sort by mtime */ #define LS_SIZE_SORT 0x0020 /* Sort by file size */ #define LS_REVERSE_SORT 0x0040 /* Reverse sort order */ #define LS_SHOW_ALL 0x0080 /* Don't skip filenames starting with '.' */ #define LS_SI_UNITS 0x0100 /* Display sizes as K, M, G, etc. */ #define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW|LS_SI_UNITS) #define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT) /* Commands for interactive mode */ enum sftp_command { I_CHDIR = 1, I_CHGRP, I_CHMOD, I_CHOWN, I_COPY, I_DF, I_GET, I_HELP, I_LCHDIR, I_LINK, I_LLS, I_LMKDIR, I_LPWD, I_LS, I_LUMASK, I_MKDIR, I_PUT, I_PWD, I_QUIT, I_REGET, I_RENAME, I_REPUT, I_RM, I_RMDIR, I_SHELL, I_SYMLINK, I_VERSION, I_PROGRESS, }; struct CMD { const char *c; const int n; const int t; /* Completion type for the first argument */ const int t2; /* completion type for the optional second argument */ }; /* Type of completion */ #define NOARGS 0 #define REMOTE 1 #define LOCAL 2 static const struct CMD cmds[] = { { "bye", I_QUIT, NOARGS, NOARGS }, { "cd", I_CHDIR, REMOTE, NOARGS }, { "chdir", I_CHDIR, REMOTE, NOARGS }, { "chgrp", I_CHGRP, REMOTE, NOARGS }, { "chmod", I_CHMOD, REMOTE, NOARGS }, { "chown", I_CHOWN, REMOTE, NOARGS }, { "copy", I_COPY, REMOTE, LOCAL }, { "cp", I_COPY, REMOTE, LOCAL }, { "df", I_DF, REMOTE, NOARGS }, { "dir", I_LS, REMOTE, NOARGS }, { "exit", I_QUIT, NOARGS, NOARGS }, { "get", I_GET, REMOTE, LOCAL }, { "help", I_HELP, NOARGS, NOARGS }, { "lcd", I_LCHDIR, LOCAL, NOARGS }, { "lchdir", I_LCHDIR, LOCAL, NOARGS }, { "lls", I_LLS, LOCAL, NOARGS }, { "lmkdir", I_LMKDIR, LOCAL, NOARGS }, { "ln", I_LINK, REMOTE, REMOTE }, { "lpwd", I_LPWD, LOCAL, NOARGS }, { "ls", I_LS, REMOTE, NOARGS }, { "lumask", I_LUMASK, NOARGS, NOARGS }, { "mkdir", I_MKDIR, REMOTE, NOARGS }, { "mget", I_GET, REMOTE, LOCAL }, { "mput", I_PUT, LOCAL, REMOTE }, { "progress", I_PROGRESS, NOARGS, NOARGS }, { "put", I_PUT, LOCAL, REMOTE }, { "pwd", I_PWD, REMOTE, NOARGS }, { "quit", I_QUIT, NOARGS, NOARGS }, { "reget", I_REGET, REMOTE, LOCAL }, { "rename", I_RENAME, REMOTE, REMOTE }, { "reput", I_REPUT, LOCAL, REMOTE }, { "rm", I_RM, REMOTE, NOARGS }, { "rmdir", I_RMDIR, REMOTE, NOARGS }, { "symlink", I_SYMLINK, REMOTE, REMOTE }, { "version", I_VERSION, NOARGS, NOARGS }, { "!", I_SHELL, NOARGS, NOARGS }, { "?", I_HELP, NOARGS, NOARGS }, { NULL, -1, -1, -1 } }; static void killchild(int signo) { pid_t pid; pid = sshpid; if (pid > 1) { kill(pid, SIGTERM); (void)waitpid(pid, NULL, 0); } _exit(1); } static void suspchild(int signo) { int save_errno = errno; if (sshpid > 1) { kill(sshpid, signo); while (waitpid(sshpid, NULL, WUNTRACED) == -1 && errno == EINTR) continue; } kill(getpid(), SIGSTOP); errno = save_errno; } static void cmd_interrupt(int signo) { const char msg[] = "\rInterrupt \n"; int olderrno = errno; (void)write(STDERR_FILENO, msg, sizeof(msg) - 1); interrupted = 1; errno = olderrno; } static void read_interrupt(int signo) { interrupted = 1; } 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) { if (!quiet) (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 [-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" "copy oldpath newpath Copy remote file\n" "cp oldpath newpath Copy remote file\n" "df [-hi] [path] Display statistics for current directory or\n" " filesystem containing 'path'\n" "exit Quit sftp\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" "lmkdir path Create local directory\n" "ln [-s] oldpath newpath Link remote file (-s for symlink)\n" "lpwd Print local working directory\n" "ls [-1afhlnrSt] [path] Display remote directory listing\n" "lumask umask Set local umask to 'umask'\n" "mkdir path Create remote directory\n" "progress Toggle display of progress meter\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" "version Show SFTP version\n" "!command Execute 'command' in local shell\n" "! Escape to local shell\n" "? Synonym for help\n"); } static void local_do_shell(const char *args) { int status; char *shell; pid_t pid; if (!*args) args = NULL; if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; if ((pid = fork()) == -1) fatal("Couldn't fork: %s", strerror(errno)); if (pid == 0) { /* XXX: child has pipe fds to ssh subproc open - issue? */ if (args) { debug3("Executing %s -c \"%s\"", shell, args); execl(shell, shell, "-c", args, (char *)NULL); } else { debug3("Executing %s", shell); execl(shell, shell, (char *)NULL); } fprintf(stderr, "Couldn't execute \"%s\": %s\n", shell, strerror(errno)); _exit(1); } while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for child: %s", strerror(errno)); if (!WIFEXITED(status)) error("Shell exited abnormally"); else if (WEXITSTATUS(status)) error("Shell exited with status %d", WEXITSTATUS(status)); } static void local_do_ls(const char *args) { if (!args || !*args) local_do_shell(_PATH_LS); else { int len = strlen(_PATH_LS " ") + strlen(args) + 1; char *buf = xmalloc(len); /* XXX: quoting - rip quoting code from ftp? */ snprintf(buf, len, _PATH_LS " %s", args); local_do_shell(buf); free(buf); } } /* Strip one path (usually the pwd) from the start of another */ static char * path_strip(const char *path, const char *strip) { size_t len; if (strip == NULL) return (xstrdup(path)); len = strlen(strip); if (strncmp(path, strip, len) == 0) { if (strip[len - 1] != '/' && path[len] == '/') len++; return (xstrdup(path + len)); } return (xstrdup(path)); } static int parse_getput_flags(const char *cmd, char **argv, int argc, int *aflag, int *fflag, int *pflag, int *rflag) { extern int opterr, optind, optopt, optreset; int ch; optind = optreset = 1; opterr = 0; *aflag = *fflag = *rflag = *pflag = 0; while ((ch = getopt(argc, argv, "afPpRr")) != -1) { switch (ch) { case 'a': *aflag = 1; break; case 'f': *fflag = 1; break; case 'p': case 'P': *pflag = 1; break; case 'r': case 'R': *rflag = 1; break; default: error("%s: Invalid flag -%c", cmd, optopt); return -1; } } return optind; } static int parse_link_flags(const char *cmd, char **argv, int argc, int *sflag) { extern int opterr, optind, optopt, optreset; int ch; optind = optreset = 1; opterr = 0; *sflag = 0; while ((ch = getopt(argc, argv, "s")) != -1) { switch (ch) { case 's': *sflag = 1; break; default: error("%s: Invalid flag -%c", cmd, optopt); return -1; } } return optind; } static int parse_rename_flags(const char *cmd, char **argv, int argc, int *lflag) { extern int opterr, optind, optopt, optreset; int ch; optind = optreset = 1; opterr = 0; *lflag = 0; while ((ch = getopt(argc, argv, "l")) != -1) { switch (ch) { case 'l': *lflag = 1; break; default: error("%s: Invalid flag -%c", cmd, optopt); return -1; } } return optind; } static int parse_ls_flags(char **argv, int argc, int *lflag) { extern int opterr, optind, optopt, optreset; int ch; optind = optreset = 1; opterr = 0; *lflag = LS_NAME_SORT; while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) { switch (ch) { case '1': *lflag &= ~VIEW_FLAGS; *lflag |= LS_SHORT_VIEW; break; case 'S': *lflag &= ~SORT_FLAGS; *lflag |= LS_SIZE_SORT; break; case 'a': *lflag |= LS_SHOW_ALL; break; case 'f': *lflag &= ~SORT_FLAGS; break; case 'h': *lflag |= LS_SI_UNITS; break; case 'l': *lflag &= ~LS_SHORT_VIEW; *lflag |= LS_LONG_VIEW; break; case 'n': *lflag &= ~LS_SHORT_VIEW; *lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW; break; case 'r': *lflag |= LS_REVERSE_SORT; break; case 't': *lflag &= ~SORT_FLAGS; *lflag |= LS_TIME_SORT; break; default: error("ls: Invalid flag -%c", optopt); return -1; } } return optind; } static int parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag) { extern int opterr, optind, optopt, optreset; int ch; optind = optreset = 1; opterr = 0; *hflag = *iflag = 0; while ((ch = getopt(argc, argv, "hi")) != -1) { switch (ch) { case 'h': *hflag = 1; break; case 'i': *iflag = 1; break; default: error("%s: Invalid flag -%c", cmd, optopt); return -1; } } return optind; } 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; int ch; optind = optreset = 1; opterr = 0; while ((ch = getopt(argc, argv, "")) != -1) { switch (ch) { default: error("%s: Invalid flag -%c", cmd, optopt); return -1; } } return optind; } static char * escape_glob(const char *s) { size_t i, o, len; char *ret; len = strlen(s); ret = xcalloc(2, len + 1); for (i = o = 0; i < len; i++) { if (strchr("[]?*\\", s[i]) != NULL) ret[o++] = '\\'; ret[o++] = s[i]; } ret[o++] = '\0'; return ret; } /* * Arg p must be dynamically allocated. make_absolute will either return it * or free it and allocate a new one. Caller must free returned string. */ static char * make_absolute_pwd_glob(char *p, const char *pwd) { char *ret, *escpwd; escpwd = escape_glob(pwd); if (p == NULL) return escpwd; ret = sftp_make_absolute(p, escpwd); free(escpwd); return ret; } static int local_is_dir(const char *path) { struct stat sb; if (stat(path, &sb) == -1) return 0; return S_ISDIR(sb.st_mode); } static int process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, int pflag, int rflag, int resume, int fflag) { char *filename, *abs_src = NULL, *abs_dst = NULL, *tmp = NULL; glob_t g; int i, r, err = 0; abs_src = make_absolute_pwd_glob(xstrdup(src), pwd); memset(&g, 0, sizeof(g)); debug3("Looking up %s", abs_src); if ((r = sftp_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) { if (r == GLOB_NOSPACE) { error("Too many matches for \"%s\".", abs_src); } else { error("File \"%s\" not found.", abs_src); } err = -1; goto out; } /* * If multiple matches then dst must be a directory or * unspecified. */ if (g.gl_matchc > 1 && dst != NULL && !local_is_dir(dst)) { error("Multiple source paths, but destination " "\"%s\" is not a directory", dst); err = -1; goto out; } for (i = 0; g.gl_pathv[i] && !interrupted; i++) { tmp = xstrdup(g.gl_pathv[i]); if ((filename = basename(tmp)) == NULL) { error("basename %s: %s", tmp, strerror(errno)); free(tmp); err = -1; goto out; } if (g.gl_matchc == 1 && dst) { if (local_is_dir(dst)) { abs_dst = sftp_path_append(dst, filename); } else { abs_dst = xstrdup(dst); } } else if (dst) { abs_dst = sftp_path_append(dst, filename); } else { abs_dst = xstrdup(filename); } free(tmp); resume |= global_aflag; if (!quiet && resume) mprintf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst); else if (!quiet && !resume) mprintf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); /* XXX follow link flag */ if (sftp_globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst, NULL, pflag || global_pflag, 1, resume, fflag || global_fflag, 0, 0) == -1) err = -1; } else { if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL, pflag || global_pflag, resume, fflag || global_fflag, 0) == -1) err = -1; } free(abs_dst); abs_dst = NULL; } out: free(abs_src); globfree(&g); return(err); } static int 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; char *tmp = NULL, *filename = NULL; glob_t g; int err = 0; int i, dst_is_dir = 1; struct stat sb; if (dst) { tmp_dst = xstrdup(dst); tmp_dst = sftp_make_absolute(tmp_dst, pwd); } memset(&g, 0, sizeof(g)); debug3("Looking up %s", src); if (glob(src, GLOB_NOCHECK | GLOB_MARK, NULL, &g)) { error("File \"%s\" not found.", src); err = -1; goto out; } /* If we aren't fetching to pwd then stash this status for later */ if (tmp_dst != NULL) dst_is_dir = sftp_remote_is_dir(conn, tmp_dst); /* If multiple matches, dst may be directory or unspecified */ if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) { error("Multiple paths match, but destination " "\"%s\" is not a directory", tmp_dst); err = -1; goto out; } for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (stat(g.gl_pathv[i], &sb) == -1) { err = -1; error("stat %s: %s", g.gl_pathv[i], strerror(errno)); continue; } tmp = xstrdup(g.gl_pathv[i]); if ((filename = basename(tmp)) == NULL) { error("basename %s: %s", tmp, strerror(errno)); free(tmp); err = -1; goto out; } free(abs_dst); abs_dst = NULL; if (g.gl_matchc == 1 && tmp_dst) { /* If directory specified, append filename */ if (dst_is_dir) abs_dst = sftp_path_append(tmp_dst, filename); else abs_dst = xstrdup(tmp_dst); } else if (tmp_dst) { abs_dst = sftp_path_append(tmp_dst, filename); } else { abs_dst = sftp_make_absolute(xstrdup(filename), pwd); } free(tmp); resume |= global_aflag; if (!quiet && resume) mprintf("Resuming upload of %s to %s\n", g.gl_pathv[i], abs_dst); else if (!quiet && !resume) mprintf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); /* XXX follow_link_flag */ if (sftp_globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, 1, resume, fflag || global_fflag, 0, 0) == -1) err = -1; } else { if (sftp_upload(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, resume, fflag || global_fflag, 0) == -1) err = -1; } } out: free(abs_dst); free(tmp_dst); globfree(&g); return(err); } static int sdirent_comp(const void *aa, const void *bb) { SFTP_DIRENT *a = *(SFTP_DIRENT **)aa; SFTP_DIRENT *b = *(SFTP_DIRENT **)bb; 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(a->filename, b->filename)); else if (sort_flag & LS_TIME_SORT) return (rmul * NCMP(a->a.mtime, b->a.mtime)); else if (sort_flag & LS_SIZE_SORT) return (rmul * NCMP(a->a.size, b->a.size)); fatal("Unknown ls sort type"); } /* sftp ls.1 replacement for directories */ static int 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; SFTP_DIRENT **d; if ((n = sftp_readdir(conn, path, &d)) != 0) return (n); if (!(lflag & LS_SHORT_VIEW)) { u_int m = 0, width = 80; struct winsize ws; char *tmp; /* 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 = MAXIMUM(m, strlen(d[n]->filename)); } /* Add any subpath that also needs to be counted */ tmp = path_strip(path, strip_path); m += strlen(tmp); free(tmp); if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) width = ws.ws_col; columns = width / (m + 2); columns = MAXIMUM(columns, 1); colspace = width / columns; colspace = MINIMUM(colspace, width); } if (lflag & SORT_FLAGS) { for (n = 0; d[n] != NULL; n++) ; /* count entries */ sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT); qsort(d, n, sizeof(*d), sdirent_comp); } get_remote_user_groups_from_dirents(conn, d); for (n = 0; d[n] != NULL && !interrupted; n++) { char *tmp, *fname; if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL)) continue; tmp = sftp_path_append(path, d[n]->filename); fname = path_strip(tmp, strip_path); free(tmp); if (lflag & LS_LONG_VIEW) { if ((lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) != 0 || sftp_can_get_users_groups_by_id(conn)) { char *lname; struct stat sb; memset(&sb, 0, sizeof(sb)); attrib_to_stat(&d[n]->a, &sb); lname = ls_file(fname, &sb, 1, (lflag & LS_SI_UNITS), ruser_name(sb.st_uid), rgroup_name(sb.st_gid)); mprintf("%s\n", lname); free(lname); } else mprintf("%s\n", d[n]->longname); } else { mprintf("%-*s", colspace, fname); if (c >= columns) { printf("\n"); c = 1; } else c++; } free(fname); } if (!(lflag & LS_LONG_VIEW) && (c != 1)) printf("\n"); sftp_free_dirents(d); 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) if (timespeccmp(&as->st_mtim, &bs->st_mtim, ==)) return 0; return timespeccmp(&as->st_mtim, &bs->st_mtim, <) ? rmul : -rmul; #elif defined(HAVE_STRUCT_STAT_ST_MTIME) return (rmul * NCMP(as->st_mtime, bs->st_mtime)); #else 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, const char *path, const char *strip_path, int lflag) { char *fname, *lname; glob_t g; int err, r; struct winsize ws; u_int i, j, nentries, *indices = NULL, c = 1; u_int colspace = 0, columns = 1, m = 0, width = 80; memset(&g, 0, sizeof(g)); if ((r = sftp_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT, NULL, &g)) != 0 || (g.gl_pathc && !g.gl_matchc)) { if (g.gl_pathc) globfree(&g); if (r == GLOB_NOSPACE) { error("Can't ls: Too many matches for \"%s\"", path); } else { error("Can't ls: \"%s\" not found", path); } return -1; } if (interrupted) goto out; /* * If the glob returns a single match and it is a directory, * then just list its contents. */ if (g.gl_matchc == 1 && g.gl_statv[0] != NULL && S_ISDIR(g.gl_statv[0]->st_mode)) { err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag); globfree(&g); return err; } if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) width = ws.ws_col; if (!(lflag & LS_SHORT_VIEW)) { /* Count entries for sort and find longest filename */ for (i = 0; g.gl_pathv[i]; i++) m = MAXIMUM(m, strlen(g.gl_pathv[i])); columns = width / (m + 2); columns = MAXIMUM(columns, 1); colspace = width / columns; } /* * 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 = xcalloc(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; } get_remote_user_groups_from_glob(conn, &g); 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) { error("no stat information for %s", fname); free(fname); continue; } lname = ls_file(fname, g.gl_statv[i], 1, (lflag & LS_SI_UNITS), ruser_name(g.gl_statv[i]->st_uid), rgroup_name(g.gl_statv[i]->st_gid)); mprintf("%s\n", lname); free(lname); } else { mprintf("%-*s", colspace, fname); if (c >= columns) { printf("\n"); c = 1; } else c++; } free(fname); } if (!(lflag & LS_LONG_VIEW) && (c != 1)) printf("\n"); out: if (g.gl_pathc) globfree(&g); free(indices); return 0; } static int do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) { struct sftp_statvfs st; 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 (sftp_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) { printf(" Inodes Used Avail " "(root) %%Capacity\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, s_icapacity); } else if (hflag) { strlcpy(s_used, "error", sizeof(s_used)); strlcpy(s_avail, "error", sizeof(s_avail)); strlcpy(s_root, "error", sizeof(s_root)); strlcpy(s_total, "error", sizeof(s_total)); fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used); fmt_scaled(st.f_bavail * st.f_frsize, s_avail); 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 %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 %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), s_dcapacity); } return 0; } /* * Undo escaping of glob sequences in place. Used to undo extra escaping * applied in makeargv() when the string is destined for a function that * does not glob it. */ static void undo_glob_escape(char *s) { size_t i, j; for (i = j = 0;;) { if (s[i] == '\0') { s[j] = '\0'; return; } if (s[i] != '\\') { s[j++] = s[i++]; continue; } /* s[i] == '\\' */ ++i; switch (s[i]) { case '?': case '[': case '*': case '\\': s[j++] = s[i++]; break; case '\0': s[j++] = '\\'; s[j] = '\0'; return; default: s[j++] = '\\'; s[j++] = s[i++]; break; } } } /* * Split a string into an argument vector using sh(1)-style quoting, * comment and escaping rules, but with some tweaks to handle glob(3) * wildcards. * The "sloppy" flag allows for recovery from missing terminating quote, for * use in parsing incomplete commandlines during tab autocompletion. * * Returns NULL on error or a NULL-terminated array of arguments. * * If "lastquote" is not NULL, the quoting character used for the last * argument is placed in *lastquote ("\0", "'" or "\""). * * If "terminated" is not NULL, *terminated will be set to 1 when the * last argument's quote has been properly terminated or 0 otherwise. * This parameter is only of use if "sloppy" is set. */ #define MAXARGS 128 #define MAXARGLEN 8192 static char ** makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, u_int *terminated) { int argc, quot; size_t i, j; static char argvs[MAXARGLEN]; static char *argv[MAXARGS + 1]; enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q; *argcp = argc = 0; if (strlen(arg) > sizeof(argvs) - 1) { args_too_longs: error("string too long"); return NULL; } if (terminated != NULL) *terminated = 1; if (lastquote != NULL) *lastquote = '\0'; state = MA_START; i = j = 0; for (;;) { if ((size_t)argc >= sizeof(argv) / sizeof(*argv)){ error("Too many arguments."); return NULL; } if (isspace((unsigned char)arg[i])) { if (state == MA_UNQUOTED) { /* Terminate current argument */ argvs[j++] = '\0'; argc++; state = MA_START; } else if (state != MA_START) argvs[j++] = arg[i]; } else if (arg[i] == '"' || arg[i] == '\'') { q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE; if (state == MA_START) { argv[argc] = argvs + j; state = q; if (lastquote != NULL) *lastquote = arg[i]; } else if (state == MA_UNQUOTED) state = q; else if (state == q) state = MA_UNQUOTED; else argvs[j++] = arg[i]; } else if (arg[i] == '\\') { if (state == MA_SQUOTE || state == MA_DQUOTE) { quot = state == MA_SQUOTE ? '\'' : '"'; /* Unescape quote we are in */ /* XXX support \n and friends? */ if (arg[i + 1] == quot) { i++; argvs[j++] = arg[i]; } else if (arg[i + 1] == '?' || arg[i + 1] == '[' || arg[i + 1] == '*') { /* * Special case for sftp: append * double-escaped glob sequence - * glob will undo one level of * escaping. NB. string can grow here. */ if (j >= sizeof(argvs) - 5) goto args_too_longs; argvs[j++] = '\\'; argvs[j++] = arg[i++]; argvs[j++] = '\\'; argvs[j++] = arg[i]; } else { argvs[j++] = arg[i++]; argvs[j++] = arg[i]; } } else { if (state == MA_START) { argv[argc] = argvs + j; state = MA_UNQUOTED; if (lastquote != NULL) *lastquote = '\0'; } if (arg[i + 1] == '?' || arg[i + 1] == '[' || arg[i + 1] == '*' || arg[i + 1] == '\\') { /* * Special case for sftp: append * escaped glob sequence - * glob will undo one level of * escaping. */ argvs[j++] = arg[i++]; argvs[j++] = arg[i]; } else { /* Unescape everything */ /* XXX support \n and friends? */ i++; argvs[j++] = arg[i]; } } } else if (arg[i] == '#') { if (state == MA_SQUOTE || state == MA_DQUOTE) argvs[j++] = arg[i]; else goto string_done; } else if (arg[i] == '\0') { if (state == MA_SQUOTE || state == MA_DQUOTE) { if (sloppy) { state = MA_UNQUOTED; if (terminated != NULL) *terminated = 0; goto string_done; } error("Unterminated quoted argument"); return NULL; } string_done: if (state == MA_UNQUOTED) { argvs[j++] = '\0'; argc++; } break; } else { if (state == MA_START) { argv[argc] = argvs + j; state = MA_UNQUOTED; if (lastquote != NULL) *lastquote = '\0'; } if ((state == MA_SQUOTE || state == MA_DQUOTE) && (arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) { /* * Special case for sftp: escape quoted * glob(3) wildcards. NB. string can grow * here. */ if (j >= sizeof(argvs) - 3) goto args_too_longs; argvs[j++] = '\\'; argvs[j++] = arg[i]; } else argvs[j++] = arg[i]; } i++; } *argcp = argc; return argv; } static int 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) { const char *cmd, *cp = *cpp; char *cp2, **argv; int base = 0; long long ll; int path1_mandatory = 0, i, cmdnum, optidx, argc; /* Skip leading whitespace */ cp = cp + strspn(cp, WHITESPACE); /* * Check for leading '-' (disable error processing) and '@' (suppress * command echo) */ *ignore_errors = 0; *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 == '#') return (0); if ((argv = makeargv(cp, &argc, 0, NULL, NULL)) == NULL) return -1; /* Figure out which command we have */ for (i = 0; cmds[i].c != NULL; i++) { if (argv[0] != NULL && strcasecmp(cmds[i].c, argv[0]) == 0) break; } cmdnum = cmds[i].n; cmd = cmds[i].c; /* Special case */ if (*cp == '!') { cp++; cmdnum = I_SHELL; } else if (cmdnum == -1) { error("Invalid command."); return -1; } /* Get arguments and parse flags */ *aflag = *fflag = *hflag = *iflag = *lflag = *pflag = 0; *rflag = *sflag = 0; *path1 = *path2 = NULL; optidx = 1; switch (cmdnum) { case I_GET: case I_REGET: case I_REPUT: case I_PUT: if ((optidx = parse_getput_flags(cmd, argv, argc, aflag, fflag, pflag, rflag)) == -1) return -1; /* Get first pathname (mandatory) */ if (argc - optidx < 1) { error("You must specify at least one path after a " "%s command.", cmd); return -1; } *path1 = xstrdup(argv[optidx]); /* Get second pathname (optional) */ if (argc - optidx > 1) { *path2 = xstrdup(argv[optidx + 1]); /* Destination is not globbed */ undo_glob_escape(*path2); } break; case I_LINK: if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) return -1; goto parse_two_paths; case I_COPY: if ((optidx = parse_no_flags(cmd, argv, argc)) == -1) return -1; goto parse_two_paths; case I_RENAME: if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1) return -1; goto parse_two_paths; case I_SYMLINK: if ((optidx = parse_no_flags(cmd, argv, argc)) == -1) return -1; parse_two_paths: if (argc - optidx < 2) { error("You must specify two paths after a %s " "command.", cmd); return -1; } *path1 = xstrdup(argv[optidx]); *path2 = xstrdup(argv[optidx + 1]); /* Paths are not globbed */ undo_glob_escape(*path1); undo_glob_escape(*path2); break; case I_RM: case I_MKDIR: case I_RMDIR: case I_LMKDIR: path1_mandatory = 1; /* FALLTHROUGH */ case I_CHDIR: case I_LCHDIR: 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; } *path1 = xstrdup(argv[optidx]); /* Only "rm" globs */ if (cmdnum != I_RM) undo_glob_escape(*path1); break; case I_DF: if ((optidx = parse_df_flags(cmd, argv, argc, hflag, iflag)) == -1) return -1; /* Default to current directory if no path specified */ if (argc - optidx < 1) *path1 = NULL; else { *path1 = xstrdup(argv[optidx]); undo_glob_escape(*path1); } break; case I_LS: if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1) return(-1); /* Path is optional */ if (argc - optidx > 0) *path1 = xstrdup(argv[optidx]); break; case I_LLS: /* Skip ls command and following whitespace */ cp = cp + strlen(cmd) + strspn(cp, WHITESPACE); case I_SHELL: /* Uses the rest of the line */ break; case I_LUMASK: case I_CHMOD: base = 8; /* FALLTHROUGH */ case I_CHOWN: case I_CHGRP: if ((optidx = parse_ch_flags(cmd, argv, argc, hflag)) == -1) return -1; /* Get numeric arg (mandatory) */ if (argc - optidx < 1) goto need_num_arg; errno = 0; ll = strtoll(argv[optidx], &cp2, base); if (cp2 == argv[optidx] || *cp2 != '\0' || ((ll == LLONG_MIN || ll == LLONG_MAX) && errno == ERANGE) || ll < 0 || ll > UINT32_MAX) { need_num_arg: error("You must supply a numeric argument " "to the %s command.", cmd); return -1; } *n_arg = ll; if (cmdnum == I_LUMASK) break; /* Get pathname (mandatory) */ if (argc - optidx < 2) { error("You must specify a path after a %s command.", cmd); return -1; } *path1 = xstrdup(argv[optidx + 1]); break; case I_QUIT: case I_PWD: case I_LPWD: case I_HELP: case I_VERSION: case I_PROGRESS: if ((optidx = parse_no_flags(cmd, argv, argc)) == -1) return -1; break; default: fatal("Command not implemented"); } *cpp = cp; return(cmdnum); } static int parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, const char *startdir, int err_abort, int echo_command) { const char *ocmd = cmd; char *path1, *path2, *tmp; 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; Attrib a, aa; char path_buf[PATH_MAX]; int err = 0; glob_t g; path1 = path2 = NULL; 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 */ switch (cmdnum) { case 0: /* Blank line */ break; case -1: /* Unrecognized command */ err = -1; break; case I_REGET: aflag = 1; /* FALLTHROUGH */ case I_GET: err = process_get(conn, path1, path2, *pwd, pflag, rflag, aflag, fflag); break; case I_REPUT: aflag = 1; /* FALLTHROUGH */ case I_PUT: err = process_put(conn, path1, path2, *pwd, pflag, rflag, aflag, fflag); break; case I_COPY: path1 = sftp_make_absolute(path1, *pwd); path2 = sftp_make_absolute(path2, *pwd); err = sftp_copy(conn, path1, path2); break; case I_RENAME: path1 = sftp_make_absolute(path1, *pwd); path2 = sftp_make_absolute(path2, *pwd); err = sftp_rename(conn, path1, path2, lflag); break; case I_SYMLINK: sflag = 1; /* FALLTHROUGH */ case I_LINK: if (!sflag) path1 = sftp_make_absolute(path1, *pwd); path2 = sftp_make_absolute(path2, *pwd); err = (sflag ? sftp_symlink : sftp_hardlink)(conn, path1, path2); break; case I_RM: path1 = make_absolute_pwd_glob(path1, *pwd); sftp_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!quiet) mprintf("Removing %s\n", g.gl_pathv[i]); err = sftp_rm(conn, g.gl_pathv[i]); if (err != 0 && err_abort) break; } break; case I_MKDIR: path1 = sftp_make_absolute(path1, *pwd); attrib_clear(&a); a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = 0777; err = sftp_mkdir(conn, path1, &a, 1); break; case I_RMDIR: path1 = sftp_make_absolute(path1, *pwd); err = sftp_rmdir(conn, path1); break; case I_CHDIR: if (path1 == NULL || *path1 == '\0') path1 = xstrdup(startdir); path1 = sftp_make_absolute(path1, *pwd); if ((tmp = sftp_realpath(conn, path1)) == NULL) { err = 1; break; } if (sftp_stat(conn, tmp, 0, &aa) != 0) { free(tmp); err = 1; break; } if (!(aa.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { error("Can't change directory: Can't check target"); free(tmp); err = 1; break; } if (!S_ISDIR(aa.perm)) { error("Can't change directory: \"%s\" is not " "a directory", tmp); free(tmp); err = 1; break; } free(*pwd); *pwd = tmp; break; case I_LS: if (!path1) { do_ls_dir(conn, *pwd, *pwd, lflag); break; } /* Strip pwd off beginning of non-absolute paths */ tmp = NULL; if (!path_absolute(path1)) tmp = *pwd; path1 = make_absolute_pwd_glob(path1, *pwd); err = do_globbed_ls(conn, path1, tmp, lflag); break; case I_DF: /* Default to current directory if no path specified */ if (path1 == NULL) path1 = xstrdup(*pwd); path1 = sftp_make_absolute(path1, *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; if (chdir(path1) == -1) { error("Couldn't change local directory to " "\"%s\": %s", path1, strerror(errno)); err = 1; } break; case I_LMKDIR: if (mkdir(path1, 0777) == -1) { error("Couldn't create local directory " "\"%s\": %s", path1, strerror(errno)); err = 1; } break; case I_LLS: local_do_ls(cmd); break; case I_SHELL: local_do_shell(cmd); break; case I_LUMASK: umask(n_arg); printf("Local umask: %03lo\n", n_arg); break; case I_CHMOD: path1 = make_absolute_pwd_glob(path1, *pwd); attrib_clear(&a); a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = n_arg; sftp_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!quiet) mprintf("Changing mode on %s\n", g.gl_pathv[i]); err = (hflag ? sftp_lsetstat : sftp_setstat)(conn, g.gl_pathv[i], &a); if (err != 0 && err_abort) break; } break; case I_CHOWN: case I_CHGRP: path1 = make_absolute_pwd_glob(path1, *pwd); sftp_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if ((hflag ? sftp_lstat : sftp_stat)(conn, g.gl_pathv[i], 0, &aa) != 0) { if (err_abort) { err = -1; break; } else continue; } if (!(aa.flags & SSH2_FILEXFER_ATTR_UIDGID)) { error("Can't get current ownership of " "remote file \"%s\"", g.gl_pathv[i]); if (err_abort) { err = -1; break; } else continue; } aa.flags &= SSH2_FILEXFER_ATTR_UIDGID; if (cmdnum == I_CHOWN) { if (!quiet) mprintf("Changing owner on %s\n", g.gl_pathv[i]); aa.uid = n_arg; } else { if (!quiet) mprintf("Changing group on %s\n", g.gl_pathv[i]); aa.gid = n_arg; } err = (hflag ? sftp_lsetstat : sftp_setstat)(conn, g.gl_pathv[i], &aa); if (err != 0 && err_abort) break; } break; case I_PWD: mprintf("Remote working directory: %s\n", *pwd); break; case I_LPWD: if (!getcwd(path_buf, sizeof(path_buf))) { error("Couldn't get local cwd: %s", strerror(errno)); err = -1; break; } mprintf("Local working directory: %s\n", path_buf); break; case I_QUIT: /* Processed below */ break; case I_HELP: help(); break; case I_VERSION: printf("SFTP protocol version %u\n", sftp_proto_version(conn)); break; case I_PROGRESS: showprogress = !showprogress; if (showprogress) printf("Progress meter enabled\n"); else printf("Progress meter disabled\n"); break; default: fatal("%d is not implemented", cmdnum); } if (g.gl_pathc) globfree(&g); free(path1); free(path2); /* If an unignored error occurs in batch mode we should abort. */ if (err_abort && err != 0) return (-1); else if (cmdnum == I_QUIT) return (1); return (0); } #ifdef USE_LIBEDIT static char * prompt(EditLine *el) { return ("sftp> "); } /* Display entries in 'list' after skipping the first 'len' chars */ static void complete_display(char **list, u_int len) { u_int y, m = 0, width = 80, columns = 1, colspace = 0, llen; struct winsize ws; char *tmp; /* Count entries for sort and find longest */ for (y = 0; list[y]; 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 = MAXIMUM(columns, 1); colspace = width / columns; colspace = MINIMUM(colspace, width); printf("\n"); m = 1; for (y = 0; list[y]; y++) { llen = strlen(list[y]); tmp = llen > len ? list[y] + len : ""; mprintf("%-*s", colspace, tmp); if (m >= columns) { printf("\n"); m = 1; } else m++; } printf("\n"); } /* * Given a "list" of words that begin with a common prefix of "word", * attempt to find an autocompletion to extends "word" by the next * characters common to all entries in "list". */ static char * complete_ambiguous(const char *word, char **list, size_t count) { if (word == NULL) return NULL; if (count > 0) { u_int y, matchlen = strlen(list[0]); /* Find length of common stem */ for (y = 1; list[y]; y++) { u_int x; for (x = 0; x < matchlen; x++) if (list[0][x] != list[y][x]) break; matchlen = x; } if (matchlen > strlen(word)) { char *tmp = xstrdup(list[0]); tmp[matchlen] = '\0'; return tmp; } } return xstrdup(word); } /* Autocomplete a sftp command */ static int complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote, int terminated) { u_int y, count = 0, cmdlen, tmplen; char *tmp, **list, argterm[3]; const LineInfo *lf; list = xcalloc((sizeof(cmds) / sizeof(*cmds)) + 1, sizeof(char *)); /* No command specified: display all available commands */ if (cmd == NULL) { for (y = 0; cmds[y].c; y++) list[count++] = xstrdup(cmds[y].c); list[count] = NULL; complete_display(list, 0); for (y = 0; list[y] != NULL; y++) free(list[y]); free(list); return count; } /* Prepare subset of commands that start with "cmd" */ cmdlen = strlen(cmd); for (y = 0; cmds[y].c; y++) { if (!strncasecmp(cmd, cmds[y].c, cmdlen)) list[count++] = xstrdup(cmds[y].c); } list[count] = NULL; if (count == 0) { free(list); return 0; } /* Complete ambiguous command */ tmp = complete_ambiguous(cmd, list, count); if (count > 1) complete_display(list, 0); for (y = 0; list[y]; y++) free(list[y]); free(list); if (tmp != NULL) { tmplen = strlen(tmp); cmdlen = strlen(cmd); /* If cmd may be extended then do so */ if (tmplen > cmdlen) if (el_insertstr(el, tmp + cmdlen) == -1) fatal("el_insertstr failed."); lf = el_line(el); /* Terminate argument cleanly */ if (count == 1) { y = 0; if (!terminated) argterm[y++] = quote; if (lastarg || *(lf->cursor) != ' ') argterm[y++] = ' '; argterm[y] = '\0'; if (y > 0 && el_insertstr(el, argterm) == -1) fatal("el_insertstr failed."); } free(tmp); } return count; } /* * Determine whether a particular sftp command's arguments (if any) represent * local or remote files. The "cmdarg" argument specifies the actual argument * and accepts values 1 or 2. */ static int complete_is_remote(char *cmd, int cmdarg) { int i; if (cmd == NULL) return -1; for (i = 0; cmds[i].c; i++) { if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c))) { if (cmdarg == 1) return cmds[i].t; else if (cmdarg == 2) return cmds[i].t2; break; } } return -1; } /* Autocomplete a filename "file" */ static int complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, char *file, int remote, int lastarg, char quote, int terminated) { glob_t g; char *tmp, *tmp2, ins[8]; u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs; int clen; const LineInfo *lf; /* Glob from "file" location */ if (file == NULL) tmp = xstrdup("*"); else xasprintf(&tmp, "%s*", file); /* Check if the path is absolute. */ isabs = path_absolute(tmp); memset(&g, 0, sizeof(g)); if (remote != LOCAL) { tmp = make_absolute_pwd_glob(tmp, remote_path); sftp_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); } else (void)glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); /* Determine length of pwd so we can trim completion display */ for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) { /* Terminate counting on first unescaped glob metacharacter */ if (tmp[tmplen] == '*' || tmp[tmplen] == '?') { if (tmp[tmplen] != '*' || tmp[tmplen + 1] != '\0') hadglob = 1; break; } if (tmp[tmplen] == '\\' && tmp[tmplen + 1] != '\0') tmplen++; if (tmp[tmplen] == '/') pwdlen = tmplen + 1; /* track last seen '/' */ } free(tmp); tmp = NULL; if (g.gl_matchc == 0) goto out; if (g.gl_matchc > 1) complete_display(g.gl_pathv, pwdlen); /* Don't try to extend globs */ if (file == NULL || hadglob) goto out; tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc); tmp = path_strip(tmp2, isabs ? NULL : remote_path); free(tmp2); if (tmp == NULL) goto out; tmplen = strlen(tmp); filelen = strlen(file); /* Count the number of escaped characters in the input string. */ cesc = isesc = 0; for (i = 0; i < filelen; i++) { if (!isesc && file[i] == '\\' && i + 1 < filelen){ isesc = 1; cesc++; } else isesc = 0; } if (tmplen > (filelen - cesc)) { tmp2 = tmp + filelen - cesc; len = strlen(tmp2); /* quote argument on way out */ for (i = 0; i < len; i += clen) { if ((clen = mblen(tmp2 + i, len - i)) < 0 || (size_t)clen > sizeof(ins) - 2) fatal("invalid multibyte character"); ins[0] = '\\'; memcpy(ins + 1, tmp2 + i, clen); ins[clen + 1] = '\0'; switch (tmp2[i]) { case '\'': case '"': case '\\': case '\t': case '[': case ' ': case '#': case '*': if (quote == '\0' || tmp2[i] == quote) { if (el_insertstr(el, ins) == -1) fatal("el_insertstr " "failed."); break; } /* FALLTHROUGH */ default: if (el_insertstr(el, ins + 1) == -1) fatal("el_insertstr failed."); break; } } } lf = el_line(el); if (g.gl_matchc == 1) { i = 0; if (!terminated && quote != '\0') ins[i++] = quote; if (*(lf->cursor - 1) != '/' && (lastarg || *(lf->cursor) != ' ')) ins[i++] = ' '; ins[i] = '\0'; if (i > 0 && el_insertstr(el, ins) == -1) fatal("el_insertstr failed."); } free(tmp); out: globfree(&g); return g.gl_matchc; } /* tab-completion hook function, called via libedit */ static unsigned char complete(EditLine *el, int ch) { char **argv, *line, quote; int argc, carg; u_int cursor, len, terminated, ret = CC_ERROR; const LineInfo *lf; struct complete_ctx *complete_ctx; lf = el_line(el); if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0) fatal_f("el_get failed"); /* Figure out which argument the cursor points to */ cursor = lf->cursor - lf->buffer; line = xmalloc(cursor + 1); memcpy(line, lf->buffer, cursor); line[cursor] = '\0'; argv = makeargv(line, &carg, 1, "e, &terminated); free(line); /* Get all the arguments on the line */ len = lf->lastchar - lf->buffer; line = xmalloc(len + 1); memcpy(line, lf->buffer, len); line[len] = '\0'; argv = makeargv(line, &argc, 1, NULL, NULL); /* Ensure cursor is at EOL or a argument boundary */ if (line[cursor] != ' ' && line[cursor] != '\0' && line[cursor] != '\n') { free(line); return ret; } if (carg == 0) { /* Show all available commands */ complete_cmd_parse(el, NULL, argc == carg, '\0', 1); ret = CC_REDISPLAY; } else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ') { /* Handle the command parsing */ if (complete_cmd_parse(el, argv[0], argc == carg, quote, terminated) != 0) ret = CC_REDISPLAY; } else if (carg >= 1) { /* Handle file parsing */ int remote = 0; int i = 0, cmdarg = 0; char *filematch = NULL; if (carg > 1 && line[cursor-1] != ' ') filematch = argv[carg - 1]; for (i = 1; i < carg; i++) { /* Skip flags */ if (argv[i][0] != '-') cmdarg++; } /* * If previous argument is complete, then offer completion * on the next one. */ if (line[cursor - 1] == ' ') cmdarg++; remote = complete_is_remote(argv[0], cmdarg); if ((remote == REMOTE || remote == LOCAL) && complete_match(el, complete_ctx->conn, *complete_ctx->remote_pathp, filematch, remote, carg == argc, quote, terminated) != 0) ret = CC_REDISPLAY; } free(line); return ret; } #endif /* USE_LIBEDIT */ static int interactive_loop(struct sftp_conn *conn, char *file1, char *file2) { char *remote_path; char *dir = NULL, *startdir = NULL; char cmd[2048]; int err, interactive; EditLine *el = NULL; #ifdef USE_LIBEDIT History *hl = NULL; HistEvent hev; extern char *__progname; struct complete_ctx complete_ctx; if (!batchmode && isatty(STDIN_FILENO)) { if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL) fatal("Couldn't initialise editline"); if ((hl = history_init()) == NULL) fatal("Couldn't initialise editline history"); history(hl, &hev, H_SETSIZE, 100); el_set(el, EL_HIST, history, hl); el_set(el, EL_PROMPT, prompt); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_TERMINAL, NULL); el_set(el, EL_SIGNAL, 1); el_source(el, NULL); /* Tab Completion */ el_set(el, EL_ADDFN, "ftp-complete", "Context sensitive argument completion", complete); complete_ctx.conn = conn; complete_ctx.remote_pathp = &remote_path; el_set(el, EL_CLIENTDATA, (void*)&complete_ctx); 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\\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 */ el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL); } #endif /* USE_LIBEDIT */ if ((remote_path = sftp_realpath(conn, ".")) == NULL) fatal("Need cwd"); startdir = xstrdup(remote_path); if (file1 != NULL) { dir = xstrdup(file1); dir = sftp_make_absolute(dir, remote_path); if (sftp_remote_is_dir(conn, dir) && file2 == NULL) { if (!quiet) mprintf("Changing to: %s\n", dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); if (parse_dispatch_command(conn, cmd, &remote_path, startdir, 1, 0) != 0) { free(dir); free(startdir); free(remote_path); free(conn); return (-1); } } else { /* XXX this is wrong wrt quoting */ snprintf(cmd, sizeof cmd, "get%s %s%s%s", global_aflag ? " -a" : "", dir, file2 == NULL ? "" : " ", file2 == NULL ? "" : file2); err = parse_dispatch_command(conn, cmd, &remote_path, startdir, 1, 0); free(dir); free(startdir); free(remote_path); free(conn); return (err); } free(dir); } setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0); interactive = !batchmode && isatty(STDIN_FILENO); err = 0; for (;;) { struct sigaction sa; interrupted = 0; memset(&sa, 0, sizeof(sa)); sa.sa_handler = interactive ? read_interrupt : killchild; if (sigaction(SIGINT, &sa, NULL) == -1) { debug3("sigaction(%s): %s", strsignal(SIGINT), strerror(errno)); break; } if (el == NULL) { if (interactive) { printf("sftp> "); fflush(stdout); } if (fgets(cmd, sizeof(cmd), infile) == NULL) { if (interactive) printf("\n"); if (interrupted) continue; break; } } else { #ifdef USE_LIBEDIT const char *line; int count = 0; if ((line = el_gets(el, &count)) == NULL || count <= 0) { printf("\n"); if (interrupted) continue; break; } history(hl, &hev, H_ENTER, line); if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) { fprintf(stderr, "Error: input line too long\n"); continue; } #endif /* USE_LIBEDIT */ } cmd[strcspn(cmd, "\n")] = '\0'; /* Handle user interrupts gracefully during commands */ interrupted = 0; ssh_signal(SIGINT, cmd_interrupt); err = parse_dispatch_command(conn, cmd, &remote_path, startdir, batchmode, !interactive && el == NULL); if (err != 0) break; } ssh_signal(SIGCHLD, SIG_DFL); free(remote_path); free(startdir); free(conn); #ifdef USE_LIBEDIT if (el != NULL) el_end(el); #endif /* USE_LIBEDIT */ /* err == 1 signifies normal "quit" exit */ return (err >= 0 ? 0 : -1); } static void connect_to_server(char *path, char **args, int *in, int *out) { int c_in, c_out; #ifdef USE_PIPES int pin[2], pout[2]; if ((pipe(pin) == -1) || (pipe(pout) == -1)) fatal("pipe: %s", strerror(errno)); *in = pin[0]; *out = pout[1]; c_in = pout[0]; c_out = pin[1]; #else /* USE_PIPES */ int inout[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) fatal("socketpair: %s", strerror(errno)); *in = *out = inout[0]; c_in = c_out = inout[1]; #endif /* USE_PIPES */ if ((sshpid = fork()) == -1) fatal("fork: %s", strerror(errno)); else if (sshpid == 0) { if ((dup2(c_in, STDIN_FILENO) == -1) || (dup2(c_out, STDOUT_FILENO) == -1)) { fprintf(stderr, "dup2: %s\n", strerror(errno)); _exit(1); } close(*in); close(*out); close(c_in); close(c_out); /* * The underlying ssh is in the same process group, so we must * ignore SIGINT if we want to gracefully abort commands, * otherwise the signal will make it to the ssh process and * kill it too. Contrawise, since sftp sends SIGTERMs to the * underlying ssh, it must *not* ignore that signal. */ ssh_signal(SIGINT, SIG_IGN); ssh_signal(SIGTERM, SIG_DFL); execvp(path, args); fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); _exit(1); } 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); } static void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" " [-D sftp_server_command] [-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" " [-X sftp_option] destination\n", __progname); exit(1); } int main(int argc, char **argv) { int r, in, out, ch, err, tmp, port = -1, noisy = 0; char *host = NULL, *user, *cp, **cpp, *file2 = NULL; int debug_level = 0; char *file1 = NULL, *sftp_server = NULL; char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; const char *errstr; LogLevel ll = SYSLOG_LEVEL_INFO; arglist args; extern int optind; extern char *optarg; struct sftp_conn *conn; size_t copy_buffer_len = 0; size_t num_requests = 0; long long llv, limit_kbps = 0; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); msetlocale(); __progname = ssh_get_progname(argv[0]); memset(&args, '\0', sizeof(args)); args.list = NULL; addargs(&args, "%s", ssh_program); addargs(&args, "-oForwardX11 no"); addargs(&args, "-oPermitLocalCommand no"); addargs(&args, "-oClearAllForwardings yes"); addargs(&args, "-oControlMaster no"); ll = SYSLOG_LEVEL_INFO; infile = stdin; while ((ch = getopt(argc, argv, "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:X:")) != -1) { switch (ch) { /* Passed through to ssh(1) */ case 'A': case '4': case '6': case 'C': addargs(&args, "-%c", ch); break; /* Passed through to ssh(1) with argument */ case 'F': case 'J': case 'c': case 'i': case 'o': addargs(&args, "-%c", ch); addargs(&args, "%s", optarg); break; case 'q': ll = SYSLOG_LEVEL_ERROR; quiet = 1; showprogress = 0; addargs(&args, "-%c", ch); break; case 'P': port = a2port(optarg); if (port <= 0) fatal("Bad port \"%s\"\n", optarg); break; case 'v': if (debug_level < 3) { addargs(&args, "-v"); ll = SYSLOG_LEVEL_DEBUG1 + debug_level; } debug_level++; break; case '1': fatal("SSH protocol v.1 is no longer supported"); break; case '2': /* accept silently */ break; case 'a': global_aflag = 1; break; case 'B': copy_buffer_len = strtol(optarg, &cp, 10); if (copy_buffer_len == 0 || *cp != '\0') fatal("Invalid buffer size \"%s\"", optarg); break; case 'b': if (batchmode) fatal("Batch file already specified."); /* Allow "-" as stdin */ if (strcmp(optarg, "-") != 0 && (infile = fopen(optarg, "r")) == NULL) fatal("%s (%s).", strerror(errno), optarg); showprogress = 0; quiet = batchmode = 1; addargs(&args, "-obatchmode yes"); break; case 'f': global_fflag = 1; break; case 'N': noisy = 1; /* Used to clear quiet mode after getopt */ break; case 'p': global_pflag = 1; break; case 'D': sftp_direct = optarg; break; case 'l': limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, &errstr); if (errstr != NULL) usage(); limit_kbps *= 1024; /* kbps */ break; case 'r': global_rflag = 1; break; case 'R': num_requests = strtol(optarg, &cp, 10); if (num_requests == 0 || *cp != '\0') fatal("Invalid number of requests \"%s\"", optarg); break; case 's': sftp_server = optarg; break; case 'S': ssh_program = optarg; replacearg(&args, 0, "%s", ssh_program); break; case 'X': /* Please keep in sync with ssh.c -X */ if (strncmp(optarg, "buffer=", 7) == 0) { r = scan_scaled(optarg + 7, &llv); if (r == 0 && (llv <= 0 || llv > 256 * 1024)) { r = -1; errno = EINVAL; } if (r == -1) { fatal("Invalid buffer size \"%s\": %s", optarg + 7, strerror(errno)); } copy_buffer_len = (size_t)llv; } else if (strncmp(optarg, "nrequests=", 10) == 0) { llv = strtonum(optarg + 10, 1, 256 * 1024, &errstr); if (errstr != NULL) { fatal("Invalid number of requests " "\"%s\": %s", optarg + 10, errstr); } num_requests = (size_t)llv; } else { fatal("Invalid -X option"); } break; case 'h': default: usage(); } } /* Do this last because we want the user to be able to override it */ addargs(&args, "-oForwardAgent no"); if (!isatty(STDERR_FILENO)) showprogress = 0; if (noisy) quiet = 0; log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); if (sftp_direct == NULL) { if (optind == argc || argc > (optind + 2)) usage(); argv += optind; 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); if (!*host) { fprintf(stderr, "Missing hostname\n"); usage(); } 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) addargs(&args, "-s"); addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", (sftp_server != NULL ? sftp_server : "sftp")); connect_to_server(ssh_program, args.list, &in, &out); } else { if ((r = argv_split(sftp_direct, &tmp, &cpp, 1)) != 0) fatal_r(r, "Parse -D arguments"); if (cpp[0] == 0) fatal("No sftp server specified via -D"); connect_to_server(cpp[0], cpp, &in, &out); argv_free(cpp, tmp); } freeargs(&args); conn = sftp_init(in, out, copy_buffer_len, num_requests, limit_kbps); if (conn == NULL) fatal("Couldn't initialise connection to server"); if (!quiet) { if (sftp_direct == NULL) fprintf(stderr, "Connected to %s.\n", host); else fprintf(stderr, "Attached to %s.\n", sftp_direct); } err = interactive_loop(conn, file1, file2); #if !defined(USE_PIPES) shutdown(in, SHUT_RDWR); shutdown(out, SHUT_RDWR); #endif close(in); close(out); if (batchmode) fclose(infile); while (waitpid(sshpid, NULL, 0) == -1 && sshpid > 1) if (errno != EINTR) fatal("Couldn't wait for ssh process: %s", strerror(errno)); exit(err == 0 ? 0 : 1); } openssh-10.0p1/PaxHeaders.10889/sftp.h100644 001750 001750 0000000003614775415623 0014301xustar0030 atime=1744182234.784985614 openssh-10.0p1/sftp.h010064400017500001750000000065221477541562300126710ustar00djmdjm/* $OpenBSD: sftp.h,v 1.9 2008/06/13 00:12:02 dtucker 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. */ /* * draft-ietf-secsh-filexfer-01.txt */ /* version */ #define SSH2_FILEXFER_VERSION 3 /* client to server */ #define SSH2_FXP_INIT 1 #define SSH2_FXP_OPEN 3 #define SSH2_FXP_CLOSE 4 #define SSH2_FXP_READ 5 #define SSH2_FXP_WRITE 6 #define SSH2_FXP_LSTAT 7 #define SSH2_FXP_STAT_VERSION_0 7 #define SSH2_FXP_FSTAT 8 #define SSH2_FXP_SETSTAT 9 #define SSH2_FXP_FSETSTAT 10 #define SSH2_FXP_OPENDIR 11 #define SSH2_FXP_READDIR 12 #define SSH2_FXP_REMOVE 13 #define SSH2_FXP_MKDIR 14 #define SSH2_FXP_RMDIR 15 #define SSH2_FXP_REALPATH 16 #define SSH2_FXP_STAT 17 #define SSH2_FXP_RENAME 18 #define SSH2_FXP_READLINK 19 #define SSH2_FXP_SYMLINK 20 /* server to client */ #define SSH2_FXP_VERSION 2 #define SSH2_FXP_STATUS 101 #define SSH2_FXP_HANDLE 102 #define SSH2_FXP_DATA 103 #define SSH2_FXP_NAME 104 #define SSH2_FXP_ATTRS 105 #define SSH2_FXP_EXTENDED 200 #define SSH2_FXP_EXTENDED_REPLY 201 /* attributes */ #define SSH2_FILEXFER_ATTR_SIZE 0x00000001 #define SSH2_FILEXFER_ATTR_UIDGID 0x00000002 #define SSH2_FILEXFER_ATTR_PERMISSIONS 0x00000004 #define SSH2_FILEXFER_ATTR_ACMODTIME 0x00000008 #define SSH2_FILEXFER_ATTR_EXTENDED 0x80000000 /* portable open modes */ #define SSH2_FXF_READ 0x00000001 #define SSH2_FXF_WRITE 0x00000002 #define SSH2_FXF_APPEND 0x00000004 #define SSH2_FXF_CREAT 0x00000008 #define SSH2_FXF_TRUNC 0x00000010 #define SSH2_FXF_EXCL 0x00000020 /* statvfs@openssh.com f_flag flags */ #define SSH2_FXE_STATVFS_ST_RDONLY 0x00000001 #define SSH2_FXE_STATVFS_ST_NOSUID 0x00000002 /* status messages */ #define SSH2_FX_OK 0 #define SSH2_FX_EOF 1 #define SSH2_FX_NO_SUCH_FILE 2 #define SSH2_FX_PERMISSION_DENIED 3 #define SSH2_FX_FAILURE 4 #define SSH2_FX_BAD_MESSAGE 5 #define SSH2_FX_NO_CONNECTION 6 #define SSH2_FX_CONNECTION_LOST 7 #define SSH2_FX_OP_UNSUPPORTED 8 #define SSH2_FX_MAX 8 struct passwd; int sftp_server_main(int, char **, struct passwd *); void sftp_server_cleanup_exit(int) __attribute__((noreturn)); openssh-10.0p1/PaxHeaders.10889/sk-api.h100644 001750 001750 0000000003614775415623 0014511xustar0030 atime=1744182234.784985614 openssh-10.0p1/sk-api.h010064400017500001750000000056001477541562300130750ustar00djmdjm/* $OpenBSD: sk-api.h,v 1.15 2022/07/20 03:29:14 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SK_API_H #define _SK_API_H 1 #include #ifdef HAVE_STDINT_H #include #endif /* Flags */ #define SSH_SK_USER_PRESENCE_REQD 0x01 #define SSH_SK_USER_VERIFICATION_REQD 0x04 #define SSH_SK_FORCE_OPERATION 0x10 #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 #define SSH_SK_ERR_CREDENTIAL_EXISTS -5 struct sk_enroll_response { uint8_t flags; uint8_t *public_key; size_t public_key_len; uint8_t *key_handle; size_t key_handle_len; uint8_t *signature; size_t signature_len; uint8_t *attestation_cert; size_t attestation_cert_len; uint8_t *authdata; size_t authdata_len; }; struct sk_sign_response { uint8_t flags; uint32_t counter; uint8_t *sig_r; size_t sig_r_len; uint8_t *sig_s; size_t sig_s_len; }; struct sk_resident_key { uint32_t alg; size_t slot; char *application; struct sk_enroll_response key; uint8_t flags; uint8_t *user_id; size_t user_id_len; }; struct sk_option { char *name; char *value; uint8_t required; }; #define SSH_SK_VERSION_MAJOR 0x000a0000 /* current API version */ #define SSH_SK_VERSION_MAJOR_MASK 0xffff0000 /* Return the version of the middleware API */ uint32_t sk_api_version(void); /* Enroll a U2F key (private key generation) */ int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **options, struct sk_enroll_response **enroll_response); /* Sign a challenge */ int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len, const char *application, const uint8_t *key_handle, size_t key_handle_len, uint8_t flags, const char *pin, struct sk_option **options, struct sk_sign_response **sign_response); /* Enumerate all resident keys */ int sk_load_resident_keys(const char *pin, struct sk_option **options, struct sk_resident_key ***rks, size_t *nrks); #endif /* _SK_API_H */ openssh-10.0p1/PaxHeaders.10889/sk-usbhid.c100644 001750 001750 0000000003614775415623 0015211xustar0030 atime=1744182234.786938267 openssh-10.0p1/sk-usbhid.c010064400017500001750000001146521477541562300136050ustar00djmdjm/* $OpenBSD: sk-usbhid.c,v 1.47 2024/12/03 08:31:49 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl * Copyright (c) 2020 Pedro Martelletto * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef ENABLE_SK_INTERNAL #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #include #ifdef HAVE_SHA2_H #include #endif /* * Almost every use of OpenSSL in this file is for ECDSA-NISTP256. * This is strictly a larger hammer than necessary, but it reduces changes * with upstream. */ #ifndef OPENSSL_HAS_ECC # undef WITH_OPENSSL #endif #ifdef WITH_OPENSSL #include #include #include #include #include #include #endif /* WITH_OPENSSL */ #include #include /* backwards compat for libfido2 */ #ifndef HAVE_FIDO_CRED_PROT #define fido_cred_prot(x) (0) #endif #ifndef HAVE_FIDO_CRED_SET_PROT #define fido_cred_set_prot(x, y) (FIDO_ERR_UNSUPPORTED_OPTION) #endif #ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT #define fido_dev_supports_cred_prot(x) (0) #endif #ifndef HAVE_FIDO_DEV_GET_TOUCH_BEGIN #define fido_dev_get_touch_begin(x) (FIDO_ERR_UNSUPPORTED_OPTION) #endif #ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS #define fido_dev_get_touch_status(x, y, z) (FIDO_ERR_UNSUPPORTED_OPTION) #endif #ifndef FIDO_CRED_PROT_UV_REQUIRED #define FIDO_CRED_PROT_UV_REQUIRED 0 #endif #ifndef FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID #define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0 #endif # include "misc.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 */ #ifdef SK_DEBUG #define SSH_FIDO_INIT_ARG FIDO_DEBUG #else #define SSH_FIDO_INIT_ARG 0 #endif #define MAX_FIDO_DEVICES 8 #define FIDO_POLL_MS 50 #define SELECT_MS 15000 #define POLL_SLEEP_NS 200000000 #ifndef FIDO_ERR_OPERATION_DENIED #define FIDO_ERR_OPERATION_DENIED 0x27 #endif struct sk_usbhid { fido_dev_t *dev; char *path; }; /* Return the version of the middleware API */ uint32_t sk_api_version(void); /* Enroll a U2F key (private key generation) */ int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **options, struct sk_enroll_response **enroll_response); /* Sign a challenge */ int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len, const char *application, const uint8_t *key_handle, size_t key_handle_len, uint8_t flags, const char *pin, struct sk_option **options, struct sk_sign_response **sign_response); /* Load resident keys */ int sk_load_resident_keys(const char *pin, struct sk_option **options, struct sk_resident_key ***rks, size_t *nrks); static void skdebug(const char *func, const char *fmt, ...) __attribute__((__format__ (printf, 2, 3))); static void skdebug(const char *func, const char *fmt, ...) { #if !defined(SK_STANDALONE) char *msg; va_list ap; va_start(ap, fmt); xvasprintf(&msg, fmt, ap); va_end(ap); debug("%s: %s", func, msg); free(msg); #elif defined(SK_DEBUG) va_list ap; va_start(ap, fmt); fprintf(stderr, "%s: ", func); vfprintf(stderr, fmt, ap); fputc('\n', stderr); va_end(ap); #else (void)func; /* XXX */ (void)fmt; /* XXX */ #endif } uint32_t sk_api_version(void) { return SSH_SK_VERSION_MAJOR; } static struct sk_usbhid * sk_open(const char *path) { struct sk_usbhid *sk; int r; if (path == NULL) { skdebug(__func__, "path == NULL"); return NULL; } if ((sk = calloc(1, sizeof(*sk))) == NULL) { skdebug(__func__, "calloc sk failed"); return NULL; } if ((sk->path = strdup(path)) == NULL) { skdebug(__func__, "strdup path failed"); free(sk); return NULL; } if ((sk->dev = fido_dev_new()) == NULL) { skdebug(__func__, "fido_dev_new failed"); free(sk->path); free(sk); return NULL; } if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) { skdebug(__func__, "fido_dev_open %s failed: %s", sk->path, fido_strerr(r)); fido_dev_free(&sk->dev); free(sk->path); free(sk); return NULL; } return sk; } static void sk_close(struct sk_usbhid *sk) { if (sk == NULL) return; fido_dev_cancel(sk->dev); /* cancel any pending operation */ fido_dev_close(sk->dev); fido_dev_free(&sk->dev); free(sk->path); free(sk); } static struct sk_usbhid ** sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen) { const fido_dev_info_t *di; struct sk_usbhid **skv; size_t i; *nopen = 0; if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) { skdebug(__func__, "calloc skv failed"); return NULL; } for (i = 0; i < ndevs; i++) { if ((di = fido_dev_info_ptr(devlist, i)) == NULL) skdebug(__func__, "fido_dev_info_ptr failed"); else if ((skv[*nopen] = sk_open(fido_dev_info_path(di))) == NULL) skdebug(__func__, "sk_open failed"); else (*nopen)++; } if (*nopen == 0) { for (i = 0; i < ndevs; i++) sk_close(skv[i]); free(skv); skv = NULL; } return skv; } static void sk_closev(struct sk_usbhid **skv, size_t nsk) { size_t i; for (i = 0; i < nsk; i++) sk_close(skv[i]); free(skv); } static int sk_touch_begin(struct sk_usbhid **skv, size_t nsk) { size_t i, ok = 0; int r; for (i = 0; i < nsk; i++) if ((r = fido_dev_get_touch_begin(skv[i]->dev)) != FIDO_OK) skdebug(__func__, "fido_dev_get_touch_begin %s failed:" " %s", skv[i]->path, fido_strerr(r)); else ok++; return ok ? 0 : -1; } static int sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx) { struct timespec ts_pause; size_t npoll, i; int r; ts_pause.tv_sec = 0; ts_pause.tv_nsec = POLL_SLEEP_NS; nanosleep(&ts_pause, NULL); npoll = nsk; for (i = 0; i < nsk; i++) { if (skv[i] == NULL) continue; /* device discarded */ skdebug(__func__, "polling %s", skv[i]->path); if ((r = fido_dev_get_touch_status(skv[i]->dev, touch, FIDO_POLL_MS)) != FIDO_OK) { skdebug(__func__, "fido_dev_get_touch_status %s: %s", skv[i]->path, fido_strerr(r)); sk_close(skv[i]); /* discard device */ skv[i] = NULL; if (--npoll == 0) { skdebug(__func__, "no device left to poll"); return -1; } } else if (*touch) { *idx = i; return 0; } } *touch = 0; return 0; } #if !defined(HAVE_FIDO_ASSERT_SET_CLIENTDATA) || \ !defined(HAVE_FIDO_CRED_SET_CLIENTDATA) /* 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; #else SHA2_CTX ctx; #endif if (dlen != 32) return -1; #ifdef WITH_OPENSSL mdlen = dlen; if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL)) return -1; #else SHA256Init(&ctx); SHA256Update(&ctx, (const uint8_t *)m, mlen); SHA256Final(d, &ctx); #endif return 0; } #endif /* !HAVE_FIDO_ASSERT_SET_CLIENTDATA || !HAVE_FIDO_CRED_SET_CLIENTDATA */ #ifndef HAVE_FIDO_CRED_SET_CLIENTDATA static int fido_cred_set_clientdata(fido_cred_t *cred, const u_char *ptr, size_t len) { uint8_t d[32]; int r; if (sha256_mem(ptr, len, d, sizeof(d)) != 0) { skdebug(__func__, "hash challenge failed"); return FIDO_ERR_INTERNAL; } r = fido_cred_set_clientdata_hash(cred, d, sizeof(d)); explicit_bzero(d, sizeof(d)); if (r != FIDO_OK) { skdebug(__func__, "fido_cred_set_clientdata_hash failed: %s", fido_strerr(r)); } return r; } #endif /* HAVE_FIDO_CRED_SET_CLIENTDATA */ #ifndef HAVE_FIDO_ASSERT_SET_CLIENTDATA static int fido_assert_set_clientdata(fido_assert_t *assert, const u_char *ptr, size_t len) { uint8_t d[32]; int r; if (sha256_mem(ptr, len, d, sizeof(d)) != 0) { skdebug(__func__, "hash challenge failed"); return FIDO_ERR_INTERNAL; } r = fido_assert_set_clientdata_hash(assert, d, sizeof(d)); explicit_bzero(d, sizeof(d)); if (r != FIDO_OK) { skdebug(__func__, "fido_assert_set_clientdata_hash failed: %s", fido_strerr(r)); } return r; } #endif /* HAVE_FIDO_ASSERT_SET_CLIENTDATA */ #ifndef HAVE_FIDO_DEV_IS_WINHELLO static bool fido_dev_is_winhello(const fido_dev_t *fdev) { return 0; } #endif /* HAVE_FIDO_DEV_IS_WINHELLO */ /* Check if the specified key handle exists on a given sk. */ static int sk_try(const struct sk_usbhid *sk, const char *application, const uint8_t *key_handle, size_t key_handle_len) { fido_assert_t *assert = NULL; int r = FIDO_ERR_INTERNAL; uint8_t message[32]; memset(message, '\0', sizeof(message)); if ((assert = fido_assert_new()) == NULL) { skdebug(__func__, "fido_assert_new failed"); goto out; } /* generate an invalid signature on FIDO2 tokens */ if ((r = fido_assert_set_clientdata(assert, message, sizeof(message))) != FIDO_OK) { skdebug(__func__, "fido_assert_set_clientdata: %s", fido_strerr(r)); goto out; } if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); goto out; } if ((r = fido_assert_allow_cred(assert, key_handle, key_handle_len)) != FIDO_OK) { skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); goto out; } if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); goto out; } r = fido_dev_get_assert(sk->dev, assert, NULL); skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { /* U2F tokens may return this */ r = FIDO_OK; } out: fido_assert_free(&assert); return r != FIDO_OK ? -1 : 0; } static int check_sk_options(fido_dev_t *dev, const char *opt, int *ret) { fido_cbor_info_t *info; char * const *name; const bool *value; size_t len, i; int r; *ret = -1; if (!fido_dev_is_fido2(dev)) { skdebug(__func__, "device is not fido2"); return 0; } if ((info = fido_cbor_info_new()) == NULL) { skdebug(__func__, "fido_cbor_info_new failed"); return -1; } if ((r = fido_dev_get_cbor_info(dev, info)) != FIDO_OK) { skdebug(__func__, "fido_dev_get_cbor_info: %s", fido_strerr(r)); fido_cbor_info_free(&info); return -1; } name = fido_cbor_info_options_name_ptr(info); value = fido_cbor_info_options_value_ptr(info); len = fido_cbor_info_options_len(info); for (i = 0; i < len; i++) { if (!strcmp(name[i], opt)) { *ret = value[i]; break; } } fido_cbor_info_free(&info); if (*ret == -1) skdebug(__func__, "option %s is unknown", opt); else skdebug(__func__, "option %s is %s", opt, *ret ? "on" : "off"); return 0; } static struct sk_usbhid * sk_select_by_cred(const fido_dev_info_t *devlist, size_t ndevs, const char *application, const uint8_t *key_handle, size_t key_handle_len) { struct sk_usbhid **skv, *sk; size_t skvcnt, i; int internal_uv; if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { skdebug(__func__, "sk_openv failed"); return NULL; } if (skvcnt == 1 && check_sk_options(skv[0]->dev, "uv", &internal_uv) == 0 && internal_uv != -1) { sk = skv[0]; skv[0] = NULL; goto out; } sk = NULL; for (i = 0; i < skvcnt; i++) { if (sk_try(skv[i], application, key_handle, key_handle_len) == 0) { sk = skv[i]; skv[i] = NULL; skdebug(__func__, "found key in %s", sk->path); break; } } out: sk_closev(skv, skvcnt); return sk; } static struct sk_usbhid * sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs) { struct sk_usbhid **skv, *sk; struct timeval tv_start, tv_now, tv_delta; size_t skvcnt, idx; int touch, ms_remain; if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { skdebug(__func__, "sk_openv failed"); return NULL; } sk = NULL; if (skvcnt < 2) { if (skvcnt == 1) { /* single candidate */ sk = skv[0]; skv[0] = NULL; } goto out; } #ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS skdebug(__func__, "libfido2 version does not support a feature needed for multiple tokens. Please upgrade to >=1.5.0"); goto out; #endif if (sk_touch_begin(skv, skvcnt) == -1) { skdebug(__func__, "sk_touch_begin failed"); goto out; } monotime_tv(&tv_start); do { if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) { skdebug(__func__, "sk_touch_poll failed"); goto out; } if (touch) { sk = skv[idx]; skv[idx] = NULL; goto out; } monotime_tv(&tv_now); timersub(&tv_now, &tv_start, &tv_delta); ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 - tv_delta.tv_usec / 1000; } while (ms_remain >= FIDO_POLL_MS); skdebug(__func__, "timeout"); out: sk_closev(skv, skvcnt); return sk; } static struct sk_usbhid * sk_probe(const char *application, const uint8_t *key_handle, size_t key_handle_len, int probe_resident) { struct sk_usbhid *sk; fido_dev_info_t *devlist; size_t ndevs; int r; #ifdef HAVE_CYGWIN if (!probe_resident && (sk = sk_open("windows://hello")) != NULL) return sk; #endif /* HAVE_CYGWIN */ if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) { skdebug(__func__, "fido_dev_info_new failed"); return NULL; } if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES, &ndevs)) != FIDO_OK) { skdebug(__func__, "fido_dev_info_manifest failed: %s", fido_strerr(r)); fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); return NULL; } skdebug(__func__, "%zu device(s) detected", ndevs); if (ndevs == 0) { sk = NULL; } else if (application != NULL && key_handle != NULL) { skdebug(__func__, "selecting sk by cred"); sk = sk_select_by_cred(devlist, ndevs, application, key_handle, key_handle_len); } else { skdebug(__func__, "selecting sk by touch"); sk = sk_select_by_touch(devlist, ndevs); } fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); return sk; } #ifdef WITH_OPENSSL /* * The key returned via fido_cred_pubkey_ptr() is in affine coordinates, * but the API expects a SEC1 octet string. */ static int pack_public_key_ecdsa(const fido_cred_t *cred, struct sk_enroll_response *response) { const uint8_t *ptr; BIGNUM *x = NULL, *y = NULL; EC_POINT *q = NULL; EC_GROUP *g = NULL; int ret = -1; response->public_key = NULL; response->public_key_len = 0; if ((x = BN_new()) == NULL || (y = BN_new()) == NULL || (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL || (q = EC_POINT_new(g)) == NULL) { skdebug(__func__, "libcrypto setup failed"); goto out; } if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { skdebug(__func__, "fido_cred_pubkey_ptr failed"); goto out; } if (fido_cred_pubkey_len(cred) != 64) { skdebug(__func__, "bad fido_cred_pubkey_len %zu", fido_cred_pubkey_len(cred)); goto out; } if (BN_bin2bn(ptr, 32, x) == NULL || BN_bin2bn(ptr + 32, 32, y) == NULL) { skdebug(__func__, "BN_bin2bn failed"); goto out; } if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) { skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed"); goto out; } response->public_key_len = EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); if (response->public_key_len == 0 || response->public_key_len > 2048) { skdebug(__func__, "bad pubkey length %zu", response->public_key_len); goto out; } if ((response->public_key = malloc(response->public_key_len)) == NULL) { skdebug(__func__, "malloc pubkey failed"); goto out; } if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, response->public_key, response->public_key_len, NULL) == 0) { skdebug(__func__, "EC_POINT_point2oct failed"); goto out; } /* success */ ret = 0; out: if (ret != 0 && response->public_key != NULL) { memset(response->public_key, 0, response->public_key_len); free(response->public_key); response->public_key = NULL; } EC_POINT_free(q); EC_GROUP_free(g); BN_clear_free(x); BN_clear_free(y); return ret; } #endif /* WITH_OPENSSL */ static int pack_public_key_ed25519(const fido_cred_t *cred, struct sk_enroll_response *response) { const uint8_t *ptr; size_t len; int ret = -1; response->public_key = NULL; response->public_key_len = 0; if ((len = fido_cred_pubkey_len(cred)) != 32) { skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len); goto out; } if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { skdebug(__func__, "fido_cred_pubkey_ptr failed"); goto out; } response->public_key_len = len; if ((response->public_key = malloc(response->public_key_len)) == NULL) { skdebug(__func__, "malloc pubkey failed"); goto out; } memcpy(response->public_key, ptr, len); ret = 0; out: if (ret != 0) free(response->public_key); return ret; } static int pack_public_key(uint32_t alg, const fido_cred_t *cred, struct sk_enroll_response *response) { switch(alg) { #ifdef WITH_OPENSSL case SSH_SK_ECDSA: return pack_public_key_ecdsa(cred, response); #endif /* WITH_OPENSSL */ case SSH_SK_ED25519: return pack_public_key_ed25519(cred, response); default: return -1; } } static int fidoerr_to_skerr(int fidoerr) { switch (fidoerr) { case FIDO_ERR_UNSUPPORTED_OPTION: case FIDO_ERR_UNSUPPORTED_ALGORITHM: return SSH_SK_ERR_UNSUPPORTED; case FIDO_ERR_PIN_REQUIRED: case FIDO_ERR_PIN_INVALID: case FIDO_ERR_OPERATION_DENIED: 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; } static int key_lookup(fido_dev_t *dev, const char *application, const uint8_t *user_id, size_t user_id_len, const char *pin) { fido_assert_t *assert = NULL; uint8_t message[32]; int r = FIDO_ERR_INTERNAL; int sk_supports_uv, uv; size_t i; memset(message, '\0', sizeof(message)); if ((assert = fido_assert_new()) == NULL) { skdebug(__func__, "fido_assert_new failed"); goto out; } /* generate an invalid signature on FIDO2 tokens */ if ((r = fido_assert_set_clientdata(assert, message, sizeof(message))) != FIDO_OK) { skdebug(__func__, "fido_assert_set_clientdata: %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_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); goto out; } uv = FIDO_OPT_OMIT; if (pin == NULL && check_sk_options(dev, "uv", &sk_supports_uv) == 0 && sk_supports_uv != -1) uv = FIDO_OPT_TRUE; if ((r = fido_assert_set_uv(assert, uv)) != FIDO_OK) { skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); goto out; } if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) { skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); goto out; } r = FIDO_ERR_NO_CREDENTIALS; skdebug(__func__, "%zu signatures returned", fido_assert_count(assert)); for (i = 0; i < fido_assert_count(assert); i++) { if (fido_assert_user_id_len(assert, i) == user_id_len && memcmp(fido_assert_user_id_ptr(assert, i), user_id, user_id_len) == 0) { skdebug(__func__, "credential exists"); r = FIDO_OK; goto out; } } out: fido_assert_free(&assert); return r; } int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **options, struct sk_enroll_response **enroll_response) { fido_cred_t *cred = NULL; const uint8_t *ptr; uint8_t user_id[32]; struct sk_usbhid *sk = NULL; struct sk_enroll_response *response = NULL; size_t len; int credprot; int cose_alg; int ret = SSH_SK_ERR_GENERAL; int r; char *device = NULL; fido_init(SSH_FIDO_INIT_ARG); if (enroll_response == NULL) { skdebug(__func__, "enroll_response == NULL"); goto out; } *enroll_response = NULL; memset(user_id, 0, sizeof(user_id)); if (check_enroll_options(options, &device, user_id, sizeof(user_id)) != 0) goto out; /* error already logged */ switch(alg) { #ifdef WITH_OPENSSL case SSH_SK_ECDSA: cose_alg = COSE_ES256; break; #endif /* WITH_OPENSSL */ case SSH_SK_ED25519: cose_alg = COSE_EDDSA; break; default: skdebug(__func__, "unsupported key type %d", alg); goto out; } if (device != NULL) sk = sk_open(device); else sk = sk_probe(NULL, NULL, 0, 0); if (sk == NULL) { ret = SSH_SK_ERR_DEVICE_NOT_FOUND; skdebug(__func__, "failed to find sk"); goto out; } skdebug(__func__, "using device %s", sk->path); if ((flags & SSH_SK_RESIDENT_KEY) != 0 && (flags & SSH_SK_FORCE_OPERATION) == 0 && (r = key_lookup(sk->dev, application, user_id, sizeof(user_id), pin)) != FIDO_ERR_NO_CREDENTIALS) { if (r != FIDO_OK) { ret = fidoerr_to_skerr(r); skdebug(__func__, "key_lookup failed"); } else { ret = SSH_SK_ERR_CREDENTIAL_EXISTS; skdebug(__func__, "key exists"); } goto out; } 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(cred, challenge, challenge_len)) != FIDO_OK) { skdebug(__func__, "fido_cred_set_clientdata: %s", fido_strerr(r)); goto out; } if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ? FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) { skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r)); goto out; } if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id), "openssh", "openssh", NULL)) != FIDO_OK) { skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r)); goto out; } if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) { skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r)); goto out; } if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) { #if !defined(HAVE_FIDO_DEV_SUPPORTS_CRED_PROT) || \ !defined(HAVE_FIDO_CRED_SET_PROT) skdebug(__func__, "libfido2 version does not support a feature required for this operation. Please upgrade to >=1.5.0"); ret = SSH_SK_ERR_UNSUPPORTED; goto out; credprot = 0; (void)credprot; /* avoid warning */ #endif if (!fido_dev_supports_cred_prot(sk->dev)) { skdebug(__func__, "%s does not support credprot, " "refusing to create unprotected " "resident/verify-required key", sk->path); ret = SSH_SK_ERR_UNSUPPORTED; goto out; } if ((flags & SSH_SK_USER_VERIFICATION_REQD)) credprot = FIDO_CRED_PROT_UV_REQUIRED; else credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID; if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) { skdebug(__func__, "fido_cred_set_prot: %s", fido_strerr(r)); ret = fidoerr_to_skerr(r); goto out; } } if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) { skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r)); ret = fidoerr_to_skerr(r); goto out; } if (fido_cred_x5c_ptr(cred) != NULL) { if ((r = fido_cred_verify(cred)) != FIDO_OK) { skdebug(__func__, "fido_cred_verify: %s", fido_strerr(r)); goto out; } } else if (strcmp(fido_cred_fmt(cred), "none") != 0) { 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; } } else { skdebug(__func__, "no attestation data"); } if ((response = calloc(1, sizeof(*response))) == NULL) { skdebug(__func__, "calloc response failed"); goto out; } response->flags = flags; if (pack_public_key(alg, cred, response) != 0) { skdebug(__func__, "pack_public_key failed"); goto out; } if ((ptr = fido_cred_id_ptr(cred)) != NULL) { len = fido_cred_id_len(cred); if ((response->key_handle = calloc(1, len)) == NULL) { skdebug(__func__, "calloc key handle failed"); goto out; } memcpy(response->key_handle, ptr, len); response->key_handle_len = len; } if ((ptr = fido_cred_sig_ptr(cred)) != NULL) { len = fido_cred_sig_len(cred); if ((response->signature = calloc(1, len)) == NULL) { skdebug(__func__, "calloc signature failed"); goto out; } memcpy(response->signature, ptr, len); response->signature_len = len; } if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) { len = fido_cred_x5c_len(cred); skdebug(__func__, "attestation cert len=%zu", len); if ((response->attestation_cert = calloc(1, len)) == NULL) { skdebug(__func__, "calloc attestation cert failed"); goto out; } memcpy(response->attestation_cert, ptr, len); response->attestation_cert_len = len; } if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) { len = fido_cred_authdata_len(cred); skdebug(__func__, "authdata len=%zu", len); if ((response->authdata = calloc(1, len)) == NULL) { skdebug(__func__, "calloc authdata failed"); goto out; } memcpy(response->authdata, ptr, len); response->authdata_len = len; } *enroll_response = response; response = NULL; ret = 0; out: free(device); if (response != NULL) { free(response->public_key); free(response->key_handle); free(response->signature); free(response->attestation_cert); free(response->authdata); free(response); } sk_close(sk); fido_cred_free(&cred); return ret; } #ifdef WITH_OPENSSL static int pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response) { ECDSA_SIG *sig = NULL; const BIGNUM *sig_r, *sig_s; const unsigned char *cp; size_t sig_len; int ret = -1; cp = fido_assert_sig_ptr(assert, 0); sig_len = fido_assert_sig_len(assert, 0); if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) { skdebug(__func__, "d2i_ECDSA_SIG failed"); goto out; } ECDSA_SIG_get0(sig, &sig_r, &sig_s); response->sig_r_len = BN_num_bytes(sig_r); response->sig_s_len = BN_num_bytes(sig_s); if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL || (response->sig_s = calloc(1, response->sig_s_len)) == NULL) { skdebug(__func__, "calloc signature failed"); goto out; } BN_bn2bin(sig_r, response->sig_r); BN_bn2bin(sig_s, response->sig_s); ret = 0; out: ECDSA_SIG_free(sig); if (ret != 0) { free(response->sig_r); free(response->sig_s); response->sig_r = NULL; response->sig_s = NULL; } return ret; } #endif /* WITH_OPENSSL */ static int pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response) { const unsigned char *ptr; size_t len; int ret = -1; ptr = fido_assert_sig_ptr(assert, 0); len = fido_assert_sig_len(assert, 0); if (len != 64) { skdebug(__func__, "bad length %zu", len); goto out; } response->sig_r_len = len; if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) { skdebug(__func__, "calloc signature failed"); goto out; } memcpy(response->sig_r, ptr, len); ret = 0; out: if (ret != 0) { free(response->sig_r); response->sig_r = NULL; } return ret; } static int pack_sig(uint32_t alg, fido_assert_t *assert, struct sk_sign_response *response) { switch(alg) { #ifdef WITH_OPENSSL case SSH_SK_ECDSA: return pack_sig_ecdsa(assert, response); #endif /* WITH_OPENSSL */ case SSH_SK_ED25519: return pack_sig_ed25519(assert, response); default: return -1; } } /* Checks sk_options for sk_sign() and sk_load_resident_keys() */ static int check_sign_load_resident_options(struct sk_option **options, char **devicep) { size_t i; if (options == NULL) return 0; for (i = 0; options[i] != NULL; i++) { if (strcmp(options[i]->name, "device") == 0) { if ((*devicep = strdup(options[i]->value)) == NULL) { skdebug(__func__, "strdup device failed"); return -1; } skdebug(__func__, "requested device %s", *devicep); } else { skdebug(__func__, "requested unsupported option %s", options[i]->name); if (options[i]->required) { skdebug(__func__, "unknown required option"); return -1; } } } return 0; } int sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, const char *application, const uint8_t *key_handle, size_t key_handle_len, uint8_t flags, const char *pin, struct sk_option **options, struct sk_sign_response **sign_response) { fido_assert_t *assert = NULL; char *device = NULL; struct sk_usbhid *sk = NULL; struct sk_sign_response *response = NULL; int ret = SSH_SK_ERR_GENERAL, internal_uv; int r; fido_init(SSH_FIDO_INIT_ARG); if (sign_response == NULL) { skdebug(__func__, "sign_response == NULL"); goto out; } *sign_response = NULL; if (check_sign_load_resident_options(options, &device) != 0) goto out; /* error already logged */ if (device != NULL) sk = sk_open(device); else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD)) sk = sk_probe(NULL, NULL, 0, 0); else sk = sk_probe(application, key_handle, key_handle_len, 0); if (sk == NULL) { ret = SSH_SK_ERR_DEVICE_NOT_FOUND; skdebug(__func__, "failed to find sk"); goto out; } if ((assert = fido_assert_new()) == NULL) { skdebug(__func__, "fido_assert_new failed"); goto out; } if ((r = fido_assert_set_clientdata(assert, data, datalen)) != FIDO_OK) { skdebug(__func__, "fido_assert_set_clientdata: %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; } /* * WinHello requests the PIN by default. Make "uv" request explicit * to allow keys with and without -O verify-required to make sense. */ if (pin == NULL && fido_dev_is_winhello (sk->dev) && (r = fido_assert_set_uv(assert, FIDO_OPT_FALSE)) != FIDO_OK) { skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); } if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD)) { if (check_sk_options(sk->dev, "uv", &internal_uv) < 0 || internal_uv != 1) { skdebug(__func__, "check_sk_options uv"); ret = SSH_SK_ERR_PIN_REQUIRED; goto out; } if ((r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) { skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); ret = fidoerr_to_skerr(r); goto out; } } if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) { skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); ret = fidoerr_to_skerr(r); goto out; } if ((response = calloc(1, sizeof(*response))) == NULL) { skdebug(__func__, "calloc response failed"); goto out; } response->flags = fido_assert_flags(assert, 0); response->counter = fido_assert_sigcount(assert, 0); if (pack_sig(alg, assert, response) != 0) { skdebug(__func__, "pack_sig failed"); goto out; } *sign_response = response; response = NULL; ret = 0; out: free(device); if (response != NULL) { free(response->sig_r); free(response->sig_s); free(response); } sk_close(sk); fido_assert_free(&assert); return ret; } static int read_rks(struct sk_usbhid *sk, const char *pin, struct sk_resident_key ***rksp, size_t *nrksp) { int ret = SSH_SK_ERR_GENERAL, r = -1, internal_uv; fido_credman_metadata_t *metadata = NULL; fido_credman_rp_t *rp = NULL; fido_credman_rk_t *rk = NULL; size_t i, j, nrp, nrk, user_id_len; const fido_cred_t *cred; const char *rp_id, *rp_name, *user_name; struct sk_resident_key *srk = NULL, **tmp; const u_char *user_id; if (pin == NULL) { skdebug(__func__, "no PIN specified"); ret = SSH_SK_ERR_PIN_REQUIRED; goto out; } if ((metadata = fido_credman_metadata_new()) == NULL) { skdebug(__func__, "alloc failed"); goto out; } if (check_sk_options(sk->dev, "uv", &internal_uv) != 0) { skdebug(__func__, "check_sk_options failed"); goto out; } if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) { if (r == FIDO_ERR_INVALID_COMMAND) { skdebug(__func__, "device %s does not support " "resident keys", sk->path); ret = 0; goto out; } skdebug(__func__, "get metadata for %s failed: %s", sk->path, fido_strerr(r)); ret = fidoerr_to_skerr(r); goto out; } skdebug(__func__, "existing %llu, remaining %llu", (unsigned long long)fido_credman_rk_existing(metadata), (unsigned long long)fido_credman_rk_remaining(metadata)); if ((rp = fido_credman_rp_new()) == NULL) { skdebug(__func__, "alloc rp failed"); goto out; } if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) { skdebug(__func__, "get RPs for %s failed: %s", sk->path, fido_strerr(r)); goto out; } nrp = fido_credman_rp_count(rp); skdebug(__func__, "Device %s has resident keys for %zu RPs", sk->path, nrp); /* Iterate over RP IDs that have resident keys */ for (i = 0; i < nrp; i++) { rp_id = fido_credman_rp_id(rp, i); rp_name = fido_credman_rp_name(rp, i); skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu", i, rp_name == NULL ? "(none)" : rp_name, rp_id == NULL ? "(none)" : rp_id, fido_credman_rp_id_hash_len(rp, i)); /* Skip non-SSH RP IDs */ if (rp_id == NULL || strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0) continue; fido_credman_rk_free(&rk); if ((rk = fido_credman_rk_new()) == NULL) { skdebug(__func__, "alloc rk failed"); goto out; } if ((r = fido_credman_get_dev_rk(sk->dev, fido_credman_rp_id(rp, i), rk, pin)) != 0) { skdebug(__func__, "get RKs for %s slot %zu failed: %s", sk->path, i, fido_strerr(r)); goto out; } nrk = fido_credman_rk_count(rk); skdebug(__func__, "RP \"%s\" has %zu resident keys", fido_credman_rp_id(rp, i), nrk); /* Iterate over resident keys for this RP ID */ for (j = 0; j < nrk; j++) { if ((cred = fido_credman_rk(rk, j)) == NULL) { skdebug(__func__, "no RK in slot %zu", j); continue; } if ((user_name = fido_cred_user_name(cred)) == NULL) user_name = ""; user_id = fido_cred_user_id_ptr(cred); user_id_len = fido_cred_user_id_len(cred); skdebug(__func__, "Device %s RP \"%s\" user \"%s\" " "uidlen %zu slot %zu: type %d flags 0x%02x " "prot 0x%02x", sk->path, rp_id, user_name, user_id_len, j, fido_cred_type(cred), fido_cred_flags(cred), fido_cred_prot(cred)); /* build response entry */ if ((srk = calloc(1, sizeof(*srk))) == NULL || (srk->key.key_handle = calloc(1, fido_cred_id_len(cred))) == NULL || (srk->application = strdup(rp_id)) == NULL || (user_id_len > 0 && (srk->user_id = calloc(1, user_id_len)) == 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); srk->user_id_len = user_id_len; if (srk->user_id_len != 0) memcpy(srk->user_id, user_id, srk->user_id_len); switch (fido_cred_type(cred)) { case COSE_ES256: srk->alg = SSH_SK_ECDSA; break; case COSE_EDDSA: srk->alg = SSH_SK_ED25519; break; default: skdebug(__func__, "unsupported key type %d", fido_cred_type(cred)); goto out; /* XXX free rk and continue */ } if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED && internal_uv == -1) srk->flags |= SSH_SK_USER_VERIFICATION_REQD; if ((r = pack_public_key(srk->alg, cred, &srk->key)) != 0) { skdebug(__func__, "pack public key failed"); goto out; } /* append */ if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1, sizeof(**rksp))) == NULL) { skdebug(__func__, "alloc rksp"); goto out; } *rksp = tmp; (*rksp)[(*nrksp)++] = srk; srk = NULL; } } /* Success */ ret = 0; out: if (srk != NULL) { free(srk->application); freezero(srk->key.public_key, srk->key.public_key_len); freezero(srk->key.key_handle, srk->key.key_handle_len); freezero(srk->user_id, srk->user_id_len); freezero(srk, sizeof(*srk)); } fido_credman_rp_free(&rp); fido_credman_rk_free(&rk); fido_credman_metadata_free(&metadata); return ret; } int sk_load_resident_keys(const char *pin, struct sk_option **options, struct sk_resident_key ***rksp, size_t *nrksp) { int ret = SSH_SK_ERR_GENERAL, r = -1; size_t i, nrks = 0; struct sk_resident_key **rks = NULL; struct sk_usbhid *sk = NULL; char *device = NULL; *rksp = NULL; *nrksp = 0; fido_init(SSH_FIDO_INIT_ARG); if (check_sign_load_resident_options(options, &device) != 0) goto out; /* error already logged */ if (device != NULL) sk = sk_open(device); else sk = sk_probe(NULL, NULL, 0, 1); if (sk == NULL) { ret = SSH_SK_ERR_DEVICE_NOT_FOUND; skdebug(__func__, "failed to find sk"); goto out; } skdebug(__func__, "trying %s", sk->path); if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) { skdebug(__func__, "read_rks failed for %s", sk->path); ret = r; goto out; } /* success, unless we have no keys but a specific error */ if (nrks > 0 || ret == SSH_SK_ERR_GENERAL) ret = 0; *rksp = rks; *nrksp = nrks; rks = NULL; nrks = 0; out: sk_close(sk); for (i = 0; i < nrks; i++) { free(rks[i]->application); freezero(rks[i]->key.public_key, rks[i]->key.public_key_len); freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len); freezero(rks[i]->user_id, rks[i]->user_id_len); freezero(rks[i], sizeof(*rks[i])); } free(device); free(rks); return ret; } #endif /* ENABLE_SK_INTERNAL */ openssh-10.0p1/PaxHeaders.10889/smult_curve25519_ref.c100644 001750 001750 0000000003614775415623 0017132xustar0030 atime=1744182234.786938267 openssh-10.0p1/smult_curve25519_ref.c010064400017500001750000000153241477541562300155220ustar00djmdjm/* $OpenBSD: smult_curve25519_ref.c,v 1.2 2013/11/02 22:02:14 markus Exp $ */ /* version 20081011 Matthew Dempsky Public domain. Derived from public domain code by D. J. Bernstein. */ int crypto_scalarmult_curve25519(unsigned char *, const unsigned char *, const unsigned char *); static void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { unsigned int j; unsigned int u; u = 0; for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } u += a[31] + b[31]; out[31] = u; } static void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { unsigned int j; unsigned int u; u = 218; for (j = 0;j < 31;++j) { u += a[j] + 65280 - b[j]; out[j] = u & 255; u >>= 8; } u += a[31] - b[31]; out[31] = u; } static void squeeze(unsigned int a[32]) { unsigned int j; unsigned int u; u = 0; for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } u += a[31]; a[31] = u & 127; u = 19 * (u >> 7); for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } u += a[31]; a[31] = u; } static const unsigned int minusp[32] = { 19, 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, 128 } ; static void freeze(unsigned int a[32]) { unsigned int aorig[32]; unsigned int j; unsigned int negative; for (j = 0;j < 32;++j) aorig[j] = a[j]; add(a,a,minusp); negative = -((a[31] >> 7) & 1); for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); } static void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { unsigned int i; unsigned int j; unsigned int u; for (i = 0;i < 32;++i) { u = 0; for (j = 0;j <= i;++j) u += a[j] * b[i - j]; for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; out[i] = u; } squeeze(out); } static void mult121665(unsigned int out[32],const unsigned int a[32]) { unsigned int j; unsigned int u; u = 0; for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } u += 121665 * a[31]; out[31] = u & 127; u = 19 * (u >> 7); for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } u += out[j]; out[j] = u; } static void square(unsigned int out[32],const unsigned int a[32]) { unsigned int i; unsigned int j; unsigned int u; for (i = 0;i < 32;++i) { u = 0; for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; u *= 2; if ((i & 1) == 0) { u += a[i / 2] * a[i / 2]; u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; } out[i] = u; } squeeze(out); } static void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) { unsigned int j; unsigned int t; unsigned int bminus1; bminus1 = b - 1; for (j = 0;j < 64;++j) { t = bminus1 & (r[j] ^ s[j]); p[j] = s[j] ^ t; q[j] = r[j] ^ t; } } static void mainloop(unsigned int work[64],const unsigned char e[32]) { unsigned int xzm1[64]; unsigned int xzm[64]; unsigned int xzmb[64]; unsigned int xzm1b[64]; unsigned int xznb[64]; unsigned int xzn1b[64]; unsigned int a0[64]; unsigned int a1[64]; unsigned int b0[64]; unsigned int b1[64]; unsigned int c1[64]; unsigned int r[32]; unsigned int s[32]; unsigned int t[32]; unsigned int u[32]; unsigned int j; unsigned int b; int pos; for (j = 0;j < 32;++j) xzm1[j] = work[j]; xzm1[32] = 1; for (j = 33;j < 64;++j) xzm1[j] = 0; xzm[0] = 1; for (j = 1;j < 64;++j) xzm[j] = 0; for (pos = 254;pos >= 0;--pos) { b = e[pos / 8] >> (pos & 7); b &= 1; select(xzmb,xzm1b,xzm,xzm1,b); add(a0,xzmb,xzmb + 32); sub(a0 + 32,xzmb,xzmb + 32); add(a1,xzm1b,xzm1b + 32); sub(a1 + 32,xzm1b,xzm1b + 32); square(b0,a0); square(b0 + 32,a0 + 32); mult(b1,a1,a0 + 32); mult(b1 + 32,a1 + 32,a0); add(c1,b1,b1 + 32); sub(c1 + 32,b1,b1 + 32); square(r,c1 + 32); sub(s,b0,b0 + 32); mult121665(t,s); add(u,t,b0); mult(xznb,b0,b0 + 32); mult(xznb + 32,s,u); square(xzn1b,c1); mult(xzn1b + 32,r,work); select(xzm,xzm1,xznb,xzn1b,b); } for (j = 0;j < 64;++j) work[j] = xzm[j]; } static void recip(unsigned int out[32],const unsigned int z[32]) { unsigned int z2[32]; unsigned int z9[32]; unsigned int z11[32]; unsigned int z2_5_0[32]; unsigned int z2_10_0[32]; unsigned int z2_20_0[32]; unsigned int z2_50_0[32]; unsigned int z2_100_0[32]; unsigned int t0[32]; unsigned int t1[32]; int i; /* 2 */ square(z2,z); /* 4 */ square(t1,z2); /* 8 */ square(t0,t1); /* 9 */ mult(z9,t0,z); /* 11 */ mult(z11,z9,z2); /* 22 */ square(t0,z11); /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); /* 2^6 - 2^1 */ square(t0,z2_5_0); /* 2^7 - 2^2 */ square(t1,t0); /* 2^8 - 2^3 */ square(t0,t1); /* 2^9 - 2^4 */ square(t1,t0); /* 2^10 - 2^5 */ square(t0,t1); /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); /* 2^11 - 2^1 */ square(t0,z2_10_0); /* 2^12 - 2^2 */ square(t1,t0); /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); /* 2^21 - 2^1 */ square(t0,z2_20_0); /* 2^22 - 2^2 */ square(t1,t0); /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); /* 2^41 - 2^1 */ square(t1,t0); /* 2^42 - 2^2 */ square(t0,t1); /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); /* 2^51 - 2^1 */ square(t0,z2_50_0); /* 2^52 - 2^2 */ square(t1,t0); /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); /* 2^101 - 2^1 */ square(t1,z2_100_0); /* 2^102 - 2^2 */ square(t0,t1); /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); /* 2^201 - 2^1 */ square(t0,t1); /* 2^202 - 2^2 */ square(t1,t0); /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); /* 2^251 - 2^1 */ square(t1,t0); /* 2^252 - 2^2 */ square(t0,t1); /* 2^253 - 2^3 */ square(t1,t0); /* 2^254 - 2^4 */ square(t0,t1); /* 2^255 - 2^5 */ square(t1,t0); /* 2^255 - 21 */ mult(out,t1,z11); } int crypto_scalarmult_curve25519(unsigned char *q, const unsigned char *n, const unsigned char *p) { unsigned int work[96]; unsigned char e[32]; unsigned int i; for (i = 0;i < 32;++i) e[i] = n[i]; e[0] &= 248; e[31] &= 127; e[31] |= 64; for (i = 0;i < 32;++i) work[i] = p[i]; mainloop(work,e); recip(work + 32,work + 32); mult(work + 64,work,work + 32); freeze(work + 64); for (i = 0;i < 32;++i) q[i] = work[64 + i]; return 0; } openssh-10.0p1/PaxHeaders.10889/sntrup761.c100644 001750 001750 0000000003614775415623 0015111xustar0030 atime=1744182234.801586615 openssh-10.0p1/sntrup761.c010064400017500001750000002337731477541562300135130ustar00djmdjm /* $OpenBSD: sntrup761.c,v 1.8 2024/09/16 05:37:05 djm Exp $ */ /* * Public Domain, Authors: * - Daniel J. Bernstein * - Chitchanok Chuengsatiansup * - Tanja Lange * - Christine van Vredendaal */ #include "includes.h" #ifdef USE_SNTRUP761X25519 #include #include "crypto_api.h" #define crypto_declassify(x, y) do {} while (0) #define int8 crypto_int8 #define uint8 crypto_uint8 #define int16 crypto_int16 #define uint16 crypto_uint16 #define int32 crypto_int32 #define uint32 crypto_uint32 #define int64 crypto_int64 #define uint64 crypto_uint64 extern volatile crypto_int16 crypto_int16_optblocker; extern volatile crypto_int32 crypto_int32_optblocker; extern volatile crypto_int64 crypto_int64_optblocker; /* from supercop-20240808/cryptoint/crypto_int16.h */ /* auto-generated: cd cryptoint; ./autogen */ /* cryptoint 20240806 */ #ifndef crypto_int16_h #define crypto_int16_h #define crypto_int16 int16_t #define crypto_int16_unsigned uint16_t __attribute__((unused)) static inline crypto_int16 crypto_int16_load(const unsigned char *crypto_int16_s) { crypto_int16 crypto_int16_z = 0; crypto_int16_z |= ((crypto_int16) (*crypto_int16_s++)) << 0; crypto_int16_z |= ((crypto_int16) (*crypto_int16_s++)) << 8; return crypto_int16_z; } __attribute__((unused)) static inline void crypto_int16_store(unsigned char *crypto_int16_s,crypto_int16 crypto_int16_x) { *crypto_int16_s++ = crypto_int16_x >> 0; *crypto_int16_s++ = crypto_int16_x >> 8; } __attribute__((unused)) static inline crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarw $15,%0" : "+r"(crypto_int16_x) : : "cc"); return crypto_int16_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_y; __asm__ ("sbfx %w0,%w1,15,1" : "=r"(crypto_int16_y) : "r"(crypto_int16_x) : ); return crypto_int16_y; #else crypto_int16_x >>= 16-6; crypto_int16_x ^= crypto_int16_optblocker; crypto_int16_x >>= 5; return crypto_int16_x; #endif } __attribute__((unused)) static inline crypto_int16_unsigned crypto_int16_unsigned_topbit_01(crypto_int16_unsigned crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("shrw $15,%0" : "+r"(crypto_int16_x) : : "cc"); return crypto_int16_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_y; __asm__ ("ubfx %w0,%w1,15,1" : "=r"(crypto_int16_y) : "r"(crypto_int16_x) : ); return crypto_int16_y; #else crypto_int16_x >>= 16-6; crypto_int16_x ^= crypto_int16_optblocker; crypto_int16_x >>= 5; return crypto_int16_x; #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_negative_01(crypto_int16 crypto_int16_x) { return crypto_int16_unsigned_topbit_01(crypto_int16_x); } __attribute__((unused)) static inline crypto_int16 crypto_int16_topbit_mask(crypto_int16 crypto_int16_x) { return crypto_int16_negative_mask(crypto_int16_x); } __attribute__((unused)) static inline crypto_int16 crypto_int16_topbit_01(crypto_int16 crypto_int16_x) { return crypto_int16_unsigned_topbit_01(crypto_int16_x); } __attribute__((unused)) static inline crypto_int16 crypto_int16_bottombit_mask(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("andw $1,%0" : "+r"(crypto_int16_x) : : "cc"); return -crypto_int16_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_y; __asm__ ("sbfx %w0,%w1,0,1" : "=r"(crypto_int16_y) : "r"(crypto_int16_x) : ); return crypto_int16_y; #else crypto_int16_x &= 1 ^ crypto_int16_optblocker; return -crypto_int16_x; #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_bottombit_01(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("andw $1,%0" : "+r"(crypto_int16_x) : : "cc"); return crypto_int16_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_y; __asm__ ("ubfx %w0,%w1,0,1" : "=r"(crypto_int16_y) : "r"(crypto_int16_x) : ); return crypto_int16_y; #else crypto_int16_x &= 1 ^ crypto_int16_optblocker; return crypto_int16_x; #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_bitinrangepublicpos_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarw %%cl,%0" : "+r"(crypto_int16_x) : "c"(crypto_int16_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("sxth %w0,%w0\n asr %w0,%w0,%w1" : "+&r"(crypto_int16_x) : "r"(crypto_int16_s) : ); #else crypto_int16_x >>= crypto_int16_s ^ crypto_int16_optblocker; #endif return crypto_int16_bottombit_mask(crypto_int16_x); } __attribute__((unused)) static inline crypto_int16 crypto_int16_bitinrangepublicpos_01(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarw %%cl,%0" : "+r"(crypto_int16_x) : "c"(crypto_int16_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("sxth %w0,%w0\n asr %w0,%w0,%w1" : "+&r"(crypto_int16_x) : "r"(crypto_int16_s) : ); #else crypto_int16_x >>= crypto_int16_s ^ crypto_int16_optblocker; #endif return crypto_int16_bottombit_01(crypto_int16_x); } __attribute__((unused)) static inline crypto_int16 crypto_int16_shlmod(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_s) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16_s &= 15; __asm__ ("shlw %%cl,%0" : "+r"(crypto_int16_x) : "c"(crypto_int16_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("and %w0,%w0,15\n and %w1,%w1,65535\n lsl %w1,%w1,%w0" : "+&r"(crypto_int16_s), "+r"(crypto_int16_x) : : ); #else int crypto_int16_k, crypto_int16_l; for (crypto_int16_l = 0,crypto_int16_k = 1;crypto_int16_k < 16;++crypto_int16_l,crypto_int16_k *= 2) crypto_int16_x ^= (crypto_int16_x ^ (crypto_int16_x << crypto_int16_k)) & crypto_int16_bitinrangepublicpos_mask(crypto_int16_s,crypto_int16_l); #endif return crypto_int16_x; } __attribute__((unused)) static inline crypto_int16 crypto_int16_shrmod(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_s) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16_s &= 15; __asm__ ("sarw %%cl,%0" : "+r"(crypto_int16_x) : "c"(crypto_int16_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("and %w0,%w0,15\n sxth %w1,%w1\n asr %w1,%w1,%w0" : "+&r"(crypto_int16_s), "+r"(crypto_int16_x) : : ); #else int crypto_int16_k, crypto_int16_l; for (crypto_int16_l = 0,crypto_int16_k = 1;crypto_int16_k < 16;++crypto_int16_l,crypto_int16_k *= 2) crypto_int16_x ^= (crypto_int16_x ^ (crypto_int16_x >> crypto_int16_k)) & crypto_int16_bitinrangepublicpos_mask(crypto_int16_s,crypto_int16_l); #endif return crypto_int16_x; } __attribute__((unused)) static inline crypto_int16 crypto_int16_bitmod_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_s) { crypto_int16_x = crypto_int16_shrmod(crypto_int16_x,crypto_int16_s); return crypto_int16_bottombit_mask(crypto_int16_x); } __attribute__((unused)) static inline crypto_int16 crypto_int16_bitmod_01(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_s) { crypto_int16_x = crypto_int16_shrmod(crypto_int16_x,crypto_int16_s); return crypto_int16_bottombit_01(crypto_int16_x); } __attribute__((unused)) static inline crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $-1,%1\n testw %2,%2\n cmovnew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("tst %w1,65535\n csetm %w0,ne" : "=r"(crypto_int16_z) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #else crypto_int16_x |= -crypto_int16_x; return crypto_int16_negative_mask(crypto_int16_x); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_nonzero_01(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $1,%1\n testw %2,%2\n cmovnew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("tst %w1,65535\n cset %w0,ne" : "=r"(crypto_int16_z) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #else crypto_int16_x |= -crypto_int16_x; return crypto_int16_unsigned_topbit_01(crypto_int16_x); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $-1,%1\n testw %2,%2\n cmovgw %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("sxth %w0,%w1\n cmp %w0,0\n csetm %w0,gt" : "=r"(crypto_int16_z) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #else crypto_int16 crypto_int16_z = -crypto_int16_x; crypto_int16_z ^= crypto_int16_x & crypto_int16_z; return crypto_int16_negative_mask(crypto_int16_z); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_positive_01(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $1,%1\n testw %2,%2\n cmovgw %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("sxth %w0,%w1\n cmp %w0,0\n cset %w0,gt" : "=r"(crypto_int16_z) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #else crypto_int16 crypto_int16_z = -crypto_int16_x; crypto_int16_z ^= crypto_int16_x & crypto_int16_z; return crypto_int16_unsigned_topbit_01(crypto_int16_z); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $-1,%1\n testw %2,%2\n cmovew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("tst %w1,65535\n csetm %w0,eq" : "=r"(crypto_int16_z) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #else return ~crypto_int16_nonzero_mask(crypto_int16_x); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_zero_01(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $1,%1\n testw %2,%2\n cmovew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("tst %w1,65535\n cset %w0,eq" : "=r"(crypto_int16_z) : "r"(crypto_int16_x) : "cc"); return crypto_int16_z; #else return 1-crypto_int16_nonzero_01(crypto_int16_x); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $-1,%1\n cmpw %3,%2\n cmovnew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("and %w0,%w1,65535\n cmp %w0,%w2,uxth\n csetm %w0,ne" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else return crypto_int16_nonzero_mask(crypto_int16_x ^ crypto_int16_y); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_unequal_01(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $1,%1\n cmpw %3,%2\n cmovnew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("and %w0,%w1,65535\n cmp %w0,%w2,uxth\n cset %w0,ne" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else return crypto_int16_nonzero_01(crypto_int16_x ^ crypto_int16_y); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $-1,%1\n cmpw %3,%2\n cmovew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("and %w0,%w1,65535\n cmp %w0,%w2,uxth\n csetm %w0,eq" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_equal_01(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $1,%1\n cmpw %3,%2\n cmovew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("and %w0,%w1,65535\n cmp %w0,%w2,uxth\n cset %w0,eq" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else return 1-crypto_int16_unequal_01(crypto_int16_x,crypto_int16_y); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("cmpw %1,%0\n cmovgw %1,%0" : "+r"(crypto_int16_x) : "r"(crypto_int16_y) : "cc"); return crypto_int16_x; #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("sxth %w0,%w0\n cmp %w0,%w1,sxth\n csel %w0,%w0,%w1,lt" : "+&r"(crypto_int16_x) : "r"(crypto_int16_y) : "cc"); return crypto_int16_x; #else crypto_int16 crypto_int16_r = crypto_int16_y ^ crypto_int16_x; crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; crypto_int16_z ^= crypto_int16_r & (crypto_int16_z ^ crypto_int16_y); crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); crypto_int16_z &= crypto_int16_r; return crypto_int16_x ^ crypto_int16_z; #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("cmpw %1,%0\n cmovlw %1,%0" : "+r"(crypto_int16_x) : "r"(crypto_int16_y) : "cc"); return crypto_int16_x; #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("sxth %w0,%w0\n cmp %w0,%w1,sxth\n csel %w0,%w1,%w0,lt" : "+&r"(crypto_int16_x) : "r"(crypto_int16_y) : "cc"); return crypto_int16_x; #else crypto_int16 crypto_int16_r = crypto_int16_y ^ crypto_int16_x; crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; crypto_int16_z ^= crypto_int16_r & (crypto_int16_z ^ crypto_int16_y); crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); crypto_int16_z &= crypto_int16_r; return crypto_int16_y ^ crypto_int16_z; #endif } __attribute__((unused)) static inline void crypto_int16_minmax(crypto_int16 *crypto_int16_p,crypto_int16 *crypto_int16_q) { crypto_int16 crypto_int16_x = *crypto_int16_p; crypto_int16 crypto_int16_y = *crypto_int16_q; #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_z; __asm__ ("cmpw %2,%1\n movw %1,%0\n cmovgw %2,%1\n cmovgw %0,%2" : "=&r"(crypto_int16_z), "+&r"(crypto_int16_x), "+r"(crypto_int16_y) : : "cc"); *crypto_int16_p = crypto_int16_x; *crypto_int16_q = crypto_int16_y; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_r, crypto_int16_s; __asm__ ("sxth %w0,%w0\n cmp %w0,%w3,sxth\n csel %w1,%w0,%w3,lt\n csel %w2,%w3,%w0,lt" : "+&r"(crypto_int16_x), "=&r"(crypto_int16_r), "=r"(crypto_int16_s) : "r"(crypto_int16_y) : "cc"); *crypto_int16_p = crypto_int16_r; *crypto_int16_q = crypto_int16_s; #else crypto_int16 crypto_int16_r = crypto_int16_y ^ crypto_int16_x; crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; crypto_int16_z ^= crypto_int16_r & (crypto_int16_z ^ crypto_int16_y); crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); crypto_int16_z &= crypto_int16_r; crypto_int16_x ^= crypto_int16_z; crypto_int16_y ^= crypto_int16_z; *crypto_int16_p = crypto_int16_x; *crypto_int16_q = crypto_int16_y; #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $-1,%1\n cmpw %3,%2\n cmovlw %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("sxth %w0,%w1\n cmp %w0,%w2,sxth\n csetm %w0,lt" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else crypto_int16 crypto_int16_r = crypto_int16_x ^ crypto_int16_y; crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; crypto_int16_z ^= crypto_int16_r & (crypto_int16_z ^ crypto_int16_x); return crypto_int16_negative_mask(crypto_int16_z); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_smaller_01(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $1,%1\n cmpw %3,%2\n cmovlw %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("sxth %w0,%w1\n cmp %w0,%w2,sxth\n cset %w0,lt" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else crypto_int16 crypto_int16_r = crypto_int16_x ^ crypto_int16_y; crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; crypto_int16_z ^= crypto_int16_r & (crypto_int16_z ^ crypto_int16_x); return crypto_int16_unsigned_topbit_01(crypto_int16_z); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_leq_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $-1,%1\n cmpw %3,%2\n cmovlew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("sxth %w0,%w1\n cmp %w0,%w2,sxth\n csetm %w0,le" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else return ~crypto_int16_smaller_mask(crypto_int16_y,crypto_int16_x); #endif } __attribute__((unused)) static inline crypto_int16 crypto_int16_leq_01(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 crypto_int16_q,crypto_int16_z; __asm__ ("xorw %0,%0\n movw $1,%1\n cmpw %3,%2\n cmovlew %1,%0" : "=&r"(crypto_int16_z), "=&r"(crypto_int16_q) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int16 crypto_int16_z; __asm__ ("sxth %w0,%w1\n cmp %w0,%w2,sxth\n cset %w0,le" : "=&r"(crypto_int16_z) : "r"(crypto_int16_x), "r"(crypto_int16_y) : "cc"); return crypto_int16_z; #else return 1-crypto_int16_smaller_01(crypto_int16_y,crypto_int16_x); #endif } __attribute__((unused)) static inline int crypto_int16_ones_num(crypto_int16 crypto_int16_x) { crypto_int16_unsigned crypto_int16_y = crypto_int16_x; const crypto_int16 C0 = 0x5555; const crypto_int16 C1 = 0x3333; const crypto_int16 C2 = 0x0f0f; crypto_int16_y -= ((crypto_int16_y >> 1) & C0); crypto_int16_y = (crypto_int16_y & C1) + ((crypto_int16_y >> 2) & C1); crypto_int16_y = (crypto_int16_y + (crypto_int16_y >> 4)) & C2; crypto_int16_y = (crypto_int16_y + (crypto_int16_y >> 8)) & 0xff; return crypto_int16_y; } __attribute__((unused)) static inline int crypto_int16_bottomzeros_num(crypto_int16 crypto_int16_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int16 fallback = 16; __asm__ ("bsfw %0,%0\n cmovew %1,%0" : "+&r"(crypto_int16_x) : "r"(fallback) : "cc"); return crypto_int16_x; #elif defined(__GNUC__) && defined(__aarch64__) int64_t crypto_int16_y; __asm__ ("orr %w0,%w1,-65536\n rbit %w0,%w0\n clz %w0,%w0" : "=r"(crypto_int16_y) : "r"(crypto_int16_x) : ); return crypto_int16_y; #else crypto_int16 crypto_int16_y = crypto_int16_x ^ (crypto_int16_x-1); crypto_int16_y = ((crypto_int16) crypto_int16_y) >> 1; crypto_int16_y &= ~(crypto_int16_x & (((crypto_int16) 1) << (16-1))); return crypto_int16_ones_num(crypto_int16_y); #endif } #endif /* from supercop-20240808/cryptoint/crypto_int32.h */ /* auto-generated: cd cryptoint; ./autogen */ /* cryptoint 20240806 */ #ifndef crypto_int32_h #define crypto_int32_h #define crypto_int32 int32_t #define crypto_int32_unsigned uint32_t __attribute__((unused)) static inline crypto_int32 crypto_int32_load(const unsigned char *crypto_int32_s) { crypto_int32 crypto_int32_z = 0; crypto_int32_z |= ((crypto_int32) (*crypto_int32_s++)) << 0; crypto_int32_z |= ((crypto_int32) (*crypto_int32_s++)) << 8; crypto_int32_z |= ((crypto_int32) (*crypto_int32_s++)) << 16; crypto_int32_z |= ((crypto_int32) (*crypto_int32_s++)) << 24; return crypto_int32_z; } __attribute__((unused)) static inline void crypto_int32_store(unsigned char *crypto_int32_s,crypto_int32 crypto_int32_x) { *crypto_int32_s++ = crypto_int32_x >> 0; *crypto_int32_s++ = crypto_int32_x >> 8; *crypto_int32_s++ = crypto_int32_x >> 16; *crypto_int32_s++ = crypto_int32_x >> 24; } __attribute__((unused)) static inline crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarl $31,%0" : "+r"(crypto_int32_x) : : "cc"); return crypto_int32_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_y; __asm__ ("asr %w0,%w1,31" : "=r"(crypto_int32_y) : "r"(crypto_int32_x) : ); return crypto_int32_y; #else crypto_int32_x >>= 32-6; crypto_int32_x ^= crypto_int32_optblocker; crypto_int32_x >>= 5; return crypto_int32_x; #endif } __attribute__((unused)) static inline crypto_int32_unsigned crypto_int32_unsigned_topbit_01(crypto_int32_unsigned crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("shrl $31,%0" : "+r"(crypto_int32_x) : : "cc"); return crypto_int32_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_y; __asm__ ("lsr %w0,%w1,31" : "=r"(crypto_int32_y) : "r"(crypto_int32_x) : ); return crypto_int32_y; #else crypto_int32_x >>= 32-6; crypto_int32_x ^= crypto_int32_optblocker; crypto_int32_x >>= 5; return crypto_int32_x; #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_negative_01(crypto_int32 crypto_int32_x) { return crypto_int32_unsigned_topbit_01(crypto_int32_x); } __attribute__((unused)) static inline crypto_int32 crypto_int32_topbit_mask(crypto_int32 crypto_int32_x) { return crypto_int32_negative_mask(crypto_int32_x); } __attribute__((unused)) static inline crypto_int32 crypto_int32_topbit_01(crypto_int32 crypto_int32_x) { return crypto_int32_unsigned_topbit_01(crypto_int32_x); } __attribute__((unused)) static inline crypto_int32 crypto_int32_bottombit_mask(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("andl $1,%0" : "+r"(crypto_int32_x) : : "cc"); return -crypto_int32_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_y; __asm__ ("sbfx %w0,%w1,0,1" : "=r"(crypto_int32_y) : "r"(crypto_int32_x) : ); return crypto_int32_y; #else crypto_int32_x &= 1 ^ crypto_int32_optblocker; return -crypto_int32_x; #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_bottombit_01(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("andl $1,%0" : "+r"(crypto_int32_x) : : "cc"); return crypto_int32_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_y; __asm__ ("ubfx %w0,%w1,0,1" : "=r"(crypto_int32_y) : "r"(crypto_int32_x) : ); return crypto_int32_y; #else crypto_int32_x &= 1 ^ crypto_int32_optblocker; return crypto_int32_x; #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_bitinrangepublicpos_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarl %%cl,%0" : "+r"(crypto_int32_x) : "c"(crypto_int32_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("asr %w0,%w0,%w1" : "+r"(crypto_int32_x) : "r"(crypto_int32_s) : ); #else crypto_int32_x >>= crypto_int32_s ^ crypto_int32_optblocker; #endif return crypto_int32_bottombit_mask(crypto_int32_x); } __attribute__((unused)) static inline crypto_int32 crypto_int32_bitinrangepublicpos_01(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarl %%cl,%0" : "+r"(crypto_int32_x) : "c"(crypto_int32_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("asr %w0,%w0,%w1" : "+r"(crypto_int32_x) : "r"(crypto_int32_s) : ); #else crypto_int32_x >>= crypto_int32_s ^ crypto_int32_optblocker; #endif return crypto_int32_bottombit_01(crypto_int32_x); } __attribute__((unused)) static inline crypto_int32 crypto_int32_shlmod(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("shll %%cl,%0" : "+r"(crypto_int32_x) : "c"(crypto_int32_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("lsl %w0,%w0,%w1" : "+r"(crypto_int32_x) : "r"(crypto_int32_s) : ); #else int crypto_int32_k, crypto_int32_l; for (crypto_int32_l = 0,crypto_int32_k = 1;crypto_int32_k < 32;++crypto_int32_l,crypto_int32_k *= 2) crypto_int32_x ^= (crypto_int32_x ^ (crypto_int32_x << crypto_int32_k)) & crypto_int32_bitinrangepublicpos_mask(crypto_int32_s,crypto_int32_l); #endif return crypto_int32_x; } __attribute__((unused)) static inline crypto_int32 crypto_int32_shrmod(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarl %%cl,%0" : "+r"(crypto_int32_x) : "c"(crypto_int32_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("asr %w0,%w0,%w1" : "+r"(crypto_int32_x) : "r"(crypto_int32_s) : ); #else int crypto_int32_k, crypto_int32_l; for (crypto_int32_l = 0,crypto_int32_k = 1;crypto_int32_k < 32;++crypto_int32_l,crypto_int32_k *= 2) crypto_int32_x ^= (crypto_int32_x ^ (crypto_int32_x >> crypto_int32_k)) & crypto_int32_bitinrangepublicpos_mask(crypto_int32_s,crypto_int32_l); #endif return crypto_int32_x; } __attribute__((unused)) static inline crypto_int32 crypto_int32_bitmod_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_s) { crypto_int32_x = crypto_int32_shrmod(crypto_int32_x,crypto_int32_s); return crypto_int32_bottombit_mask(crypto_int32_x); } __attribute__((unused)) static inline crypto_int32 crypto_int32_bitmod_01(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_s) { crypto_int32_x = crypto_int32_shrmod(crypto_int32_x,crypto_int32_s); return crypto_int32_bottombit_01(crypto_int32_x); } __attribute__((unused)) static inline crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $-1,%1\n testl %2,%2\n cmovnel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,0\n csetm %w0,ne" : "=r"(crypto_int32_z) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #else crypto_int32_x |= -crypto_int32_x; return crypto_int32_negative_mask(crypto_int32_x); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_nonzero_01(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $1,%1\n testl %2,%2\n cmovnel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,0\n cset %w0,ne" : "=r"(crypto_int32_z) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #else crypto_int32_x |= -crypto_int32_x; return crypto_int32_unsigned_topbit_01(crypto_int32_x); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $-1,%1\n testl %2,%2\n cmovgl %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,0\n csetm %w0,gt" : "=r"(crypto_int32_z) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #else crypto_int32 crypto_int32_z = -crypto_int32_x; crypto_int32_z ^= crypto_int32_x & crypto_int32_z; return crypto_int32_negative_mask(crypto_int32_z); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_positive_01(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $1,%1\n testl %2,%2\n cmovgl %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,0\n cset %w0,gt" : "=r"(crypto_int32_z) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #else crypto_int32 crypto_int32_z = -crypto_int32_x; crypto_int32_z ^= crypto_int32_x & crypto_int32_z; return crypto_int32_unsigned_topbit_01(crypto_int32_z); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $-1,%1\n testl %2,%2\n cmovel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,0\n csetm %w0,eq" : "=r"(crypto_int32_z) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #else return ~crypto_int32_nonzero_mask(crypto_int32_x); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_zero_01(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $1,%1\n testl %2,%2\n cmovel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,0\n cset %w0,eq" : "=r"(crypto_int32_z) : "r"(crypto_int32_x) : "cc"); return crypto_int32_z; #else return 1-crypto_int32_nonzero_01(crypto_int32_x); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $-1,%1\n cmpl %3,%2\n cmovnel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n csetm %w0,ne" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else return crypto_int32_nonzero_mask(crypto_int32_x ^ crypto_int32_y); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_unequal_01(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $1,%1\n cmpl %3,%2\n cmovnel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n cset %w0,ne" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else return crypto_int32_nonzero_01(crypto_int32_x ^ crypto_int32_y); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $-1,%1\n cmpl %3,%2\n cmovel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n csetm %w0,eq" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_equal_01(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $1,%1\n cmpl %3,%2\n cmovel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n cset %w0,eq" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else return 1-crypto_int32_unequal_01(crypto_int32_x,crypto_int32_y); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("cmpl %1,%0\n cmovgl %1,%0" : "+r"(crypto_int32_x) : "r"(crypto_int32_y) : "cc"); return crypto_int32_x; #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("cmp %w0,%w1\n csel %w0,%w0,%w1,lt" : "+r"(crypto_int32_x) : "r"(crypto_int32_y) : "cc"); return crypto_int32_x; #else crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x; crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x; crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_y); crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); crypto_int32_z &= crypto_int32_r; return crypto_int32_x ^ crypto_int32_z; #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("cmpl %1,%0\n cmovll %1,%0" : "+r"(crypto_int32_x) : "r"(crypto_int32_y) : "cc"); return crypto_int32_x; #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("cmp %w0,%w1\n csel %w0,%w1,%w0,lt" : "+r"(crypto_int32_x) : "r"(crypto_int32_y) : "cc"); return crypto_int32_x; #else crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x; crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x; crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_y); crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); crypto_int32_z &= crypto_int32_r; return crypto_int32_y ^ crypto_int32_z; #endif } __attribute__((unused)) static inline void crypto_int32_minmax(crypto_int32 *crypto_int32_p,crypto_int32 *crypto_int32_q) { crypto_int32 crypto_int32_x = *crypto_int32_p; crypto_int32 crypto_int32_y = *crypto_int32_q; #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_z; __asm__ ("cmpl %2,%1\n movl %1,%0\n cmovgl %2,%1\n cmovgl %0,%2" : "=&r"(crypto_int32_z), "+&r"(crypto_int32_x), "+r"(crypto_int32_y) : : "cc"); *crypto_int32_p = crypto_int32_x; *crypto_int32_q = crypto_int32_y; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_r, crypto_int32_s; __asm__ ("cmp %w2,%w3\n csel %w0,%w2,%w3,lt\n csel %w1,%w3,%w2,lt" : "=&r"(crypto_int32_r), "=r"(crypto_int32_s) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); *crypto_int32_p = crypto_int32_r; *crypto_int32_q = crypto_int32_s; #else crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x; crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x; crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_y); crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); crypto_int32_z &= crypto_int32_r; crypto_int32_x ^= crypto_int32_z; crypto_int32_y ^= crypto_int32_z; *crypto_int32_p = crypto_int32_x; *crypto_int32_q = crypto_int32_y; #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $-1,%1\n cmpl %3,%2\n cmovll %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n csetm %w0,lt" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else crypto_int32 crypto_int32_r = crypto_int32_x ^ crypto_int32_y; crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_x); return crypto_int32_negative_mask(crypto_int32_z); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_smaller_01(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $1,%1\n cmpl %3,%2\n cmovll %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n cset %w0,lt" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else crypto_int32 crypto_int32_r = crypto_int32_x ^ crypto_int32_y; crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_x); return crypto_int32_unsigned_topbit_01(crypto_int32_z); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_leq_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $-1,%1\n cmpl %3,%2\n cmovlel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n csetm %w0,le" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else return ~crypto_int32_smaller_mask(crypto_int32_y,crypto_int32_x); #endif } __attribute__((unused)) static inline crypto_int32 crypto_int32_leq_01(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 crypto_int32_q,crypto_int32_z; __asm__ ("xorl %0,%0\n movl $1,%1\n cmpl %3,%2\n cmovlel %1,%0" : "=&r"(crypto_int32_z), "=&r"(crypto_int32_q) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int32 crypto_int32_z; __asm__ ("cmp %w1,%w2\n cset %w0,le" : "=r"(crypto_int32_z) : "r"(crypto_int32_x), "r"(crypto_int32_y) : "cc"); return crypto_int32_z; #else return 1-crypto_int32_smaller_01(crypto_int32_y,crypto_int32_x); #endif } __attribute__((unused)) static inline int crypto_int32_ones_num(crypto_int32 crypto_int32_x) { crypto_int32_unsigned crypto_int32_y = crypto_int32_x; const crypto_int32 C0 = 0x55555555; const crypto_int32 C1 = 0x33333333; const crypto_int32 C2 = 0x0f0f0f0f; crypto_int32_y -= ((crypto_int32_y >> 1) & C0); crypto_int32_y = (crypto_int32_y & C1) + ((crypto_int32_y >> 2) & C1); crypto_int32_y = (crypto_int32_y + (crypto_int32_y >> 4)) & C2; crypto_int32_y += crypto_int32_y >> 8; crypto_int32_y = (crypto_int32_y + (crypto_int32_y >> 16)) & 0xff; return crypto_int32_y; } __attribute__((unused)) static inline int crypto_int32_bottomzeros_num(crypto_int32 crypto_int32_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int32 fallback = 32; __asm__ ("bsfl %0,%0\n cmovel %1,%0" : "+&r"(crypto_int32_x) : "r"(fallback) : "cc"); return crypto_int32_x; #elif defined(__GNUC__) && defined(__aarch64__) int64_t crypto_int32_y; __asm__ ("rbit %w0,%w1\n clz %w0,%w0" : "=r"(crypto_int32_y) : "r"(crypto_int32_x) : ); return crypto_int32_y; #else crypto_int32 crypto_int32_y = crypto_int32_x ^ (crypto_int32_x-1); crypto_int32_y = ((crypto_int32) crypto_int32_y) >> 1; crypto_int32_y &= ~(crypto_int32_x & (((crypto_int32) 1) << (32-1))); return crypto_int32_ones_num(crypto_int32_y); #endif } #endif /* from supercop-20240808/cryptoint/crypto_int64.h */ /* auto-generated: cd cryptoint; ./autogen */ /* cryptoint 20240806 */ #ifndef crypto_int64_h #define crypto_int64_h #define crypto_int64 int64_t #define crypto_int64_unsigned uint64_t __attribute__((unused)) static inline crypto_int64 crypto_int64_load(const unsigned char *crypto_int64_s) { crypto_int64 crypto_int64_z = 0; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 0; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 8; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 16; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 24; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 32; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 40; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 48; crypto_int64_z |= ((crypto_int64) (*crypto_int64_s++)) << 56; return crypto_int64_z; } __attribute__((unused)) static inline void crypto_int64_store(unsigned char *crypto_int64_s,crypto_int64 crypto_int64_x) { *crypto_int64_s++ = crypto_int64_x >> 0; *crypto_int64_s++ = crypto_int64_x >> 8; *crypto_int64_s++ = crypto_int64_x >> 16; *crypto_int64_s++ = crypto_int64_x >> 24; *crypto_int64_s++ = crypto_int64_x >> 32; *crypto_int64_s++ = crypto_int64_x >> 40; *crypto_int64_s++ = crypto_int64_x >> 48; *crypto_int64_s++ = crypto_int64_x >> 56; } __attribute__((unused)) static inline crypto_int64 crypto_int64_negative_mask(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarq $63,%0" : "+r"(crypto_int64_x) : : "cc"); return crypto_int64_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_y; __asm__ ("asr %0,%1,63" : "=r"(crypto_int64_y) : "r"(crypto_int64_x) : ); return crypto_int64_y; #else crypto_int64_x >>= 64-6; crypto_int64_x ^= crypto_int64_optblocker; crypto_int64_x >>= 5; return crypto_int64_x; #endif } __attribute__((unused)) static inline crypto_int64_unsigned crypto_int64_unsigned_topbit_01(crypto_int64_unsigned crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("shrq $63,%0" : "+r"(crypto_int64_x) : : "cc"); return crypto_int64_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_y; __asm__ ("lsr %0,%1,63" : "=r"(crypto_int64_y) : "r"(crypto_int64_x) : ); return crypto_int64_y; #else crypto_int64_x >>= 64-6; crypto_int64_x ^= crypto_int64_optblocker; crypto_int64_x >>= 5; return crypto_int64_x; #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_negative_01(crypto_int64 crypto_int64_x) { return crypto_int64_unsigned_topbit_01(crypto_int64_x); } __attribute__((unused)) static inline crypto_int64 crypto_int64_topbit_mask(crypto_int64 crypto_int64_x) { return crypto_int64_negative_mask(crypto_int64_x); } __attribute__((unused)) static inline crypto_int64 crypto_int64_topbit_01(crypto_int64 crypto_int64_x) { return crypto_int64_unsigned_topbit_01(crypto_int64_x); } __attribute__((unused)) static inline crypto_int64 crypto_int64_bottombit_mask(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("andq $1,%0" : "+r"(crypto_int64_x) : : "cc"); return -crypto_int64_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_y; __asm__ ("sbfx %0,%1,0,1" : "=r"(crypto_int64_y) : "r"(crypto_int64_x) : ); return crypto_int64_y; #else crypto_int64_x &= 1 ^ crypto_int64_optblocker; return -crypto_int64_x; #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_bottombit_01(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("andq $1,%0" : "+r"(crypto_int64_x) : : "cc"); return crypto_int64_x; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_y; __asm__ ("ubfx %0,%1,0,1" : "=r"(crypto_int64_y) : "r"(crypto_int64_x) : ); return crypto_int64_y; #else crypto_int64_x &= 1 ^ crypto_int64_optblocker; return crypto_int64_x; #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_bitinrangepublicpos_mask(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarq %%cl,%0" : "+r"(crypto_int64_x) : "c"(crypto_int64_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("asr %0,%0,%1" : "+r"(crypto_int64_x) : "r"(crypto_int64_s) : ); #else crypto_int64_x >>= crypto_int64_s ^ crypto_int64_optblocker; #endif return crypto_int64_bottombit_mask(crypto_int64_x); } __attribute__((unused)) static inline crypto_int64 crypto_int64_bitinrangepublicpos_01(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarq %%cl,%0" : "+r"(crypto_int64_x) : "c"(crypto_int64_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("asr %0,%0,%1" : "+r"(crypto_int64_x) : "r"(crypto_int64_s) : ); #else crypto_int64_x >>= crypto_int64_s ^ crypto_int64_optblocker; #endif return crypto_int64_bottombit_01(crypto_int64_x); } __attribute__((unused)) static inline crypto_int64 crypto_int64_shlmod(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("shlq %%cl,%0" : "+r"(crypto_int64_x) : "c"(crypto_int64_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("lsl %0,%0,%1" : "+r"(crypto_int64_x) : "r"(crypto_int64_s) : ); #else int crypto_int64_k, crypto_int64_l; for (crypto_int64_l = 0,crypto_int64_k = 1;crypto_int64_k < 64;++crypto_int64_l,crypto_int64_k *= 2) crypto_int64_x ^= (crypto_int64_x ^ (crypto_int64_x << crypto_int64_k)) & crypto_int64_bitinrangepublicpos_mask(crypto_int64_s,crypto_int64_l); #endif return crypto_int64_x; } __attribute__((unused)) static inline crypto_int64 crypto_int64_shrmod(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_s) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("sarq %%cl,%0" : "+r"(crypto_int64_x) : "c"(crypto_int64_s) : "cc"); #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("asr %0,%0,%1" : "+r"(crypto_int64_x) : "r"(crypto_int64_s) : ); #else int crypto_int64_k, crypto_int64_l; for (crypto_int64_l = 0,crypto_int64_k = 1;crypto_int64_k < 64;++crypto_int64_l,crypto_int64_k *= 2) crypto_int64_x ^= (crypto_int64_x ^ (crypto_int64_x >> crypto_int64_k)) & crypto_int64_bitinrangepublicpos_mask(crypto_int64_s,crypto_int64_l); #endif return crypto_int64_x; } __attribute__((unused)) static inline crypto_int64 crypto_int64_bitmod_mask(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_s) { crypto_int64_x = crypto_int64_shrmod(crypto_int64_x,crypto_int64_s); return crypto_int64_bottombit_mask(crypto_int64_x); } __attribute__((unused)) static inline crypto_int64 crypto_int64_bitmod_01(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_s) { crypto_int64_x = crypto_int64_shrmod(crypto_int64_x,crypto_int64_s); return crypto_int64_bottombit_01(crypto_int64_x); } __attribute__((unused)) static inline crypto_int64 crypto_int64_nonzero_mask(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $-1,%1\n testq %2,%2\n cmovneq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,0\n csetm %0,ne" : "=r"(crypto_int64_z) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #else crypto_int64_x |= -crypto_int64_x; return crypto_int64_negative_mask(crypto_int64_x); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_nonzero_01(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $1,%1\n testq %2,%2\n cmovneq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,0\n cset %0,ne" : "=r"(crypto_int64_z) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #else crypto_int64_x |= -crypto_int64_x; return crypto_int64_unsigned_topbit_01(crypto_int64_x); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_positive_mask(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $-1,%1\n testq %2,%2\n cmovgq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,0\n csetm %0,gt" : "=r"(crypto_int64_z) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #else crypto_int64 crypto_int64_z = -crypto_int64_x; crypto_int64_z ^= crypto_int64_x & crypto_int64_z; return crypto_int64_negative_mask(crypto_int64_z); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_positive_01(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $1,%1\n testq %2,%2\n cmovgq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,0\n cset %0,gt" : "=r"(crypto_int64_z) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #else crypto_int64 crypto_int64_z = -crypto_int64_x; crypto_int64_z ^= crypto_int64_x & crypto_int64_z; return crypto_int64_unsigned_topbit_01(crypto_int64_z); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_zero_mask(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $-1,%1\n testq %2,%2\n cmoveq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,0\n csetm %0,eq" : "=r"(crypto_int64_z) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #else return ~crypto_int64_nonzero_mask(crypto_int64_x); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_zero_01(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $1,%1\n testq %2,%2\n cmoveq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,0\n cset %0,eq" : "=r"(crypto_int64_z) : "r"(crypto_int64_x) : "cc"); return crypto_int64_z; #else return 1-crypto_int64_nonzero_01(crypto_int64_x); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_unequal_mask(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $-1,%1\n cmpq %3,%2\n cmovneq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n csetm %0,ne" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else return crypto_int64_nonzero_mask(crypto_int64_x ^ crypto_int64_y); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_unequal_01(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $1,%1\n cmpq %3,%2\n cmovneq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n cset %0,ne" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else return crypto_int64_nonzero_01(crypto_int64_x ^ crypto_int64_y); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_equal_mask(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $-1,%1\n cmpq %3,%2\n cmoveq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n csetm %0,eq" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else return ~crypto_int64_unequal_mask(crypto_int64_x,crypto_int64_y); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_equal_01(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $1,%1\n cmpq %3,%2\n cmoveq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n cset %0,eq" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else return 1-crypto_int64_unequal_01(crypto_int64_x,crypto_int64_y); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_min(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("cmpq %1,%0\n cmovgq %1,%0" : "+r"(crypto_int64_x) : "r"(crypto_int64_y) : "cc"); return crypto_int64_x; #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("cmp %0,%1\n csel %0,%0,%1,lt" : "+r"(crypto_int64_x) : "r"(crypto_int64_y) : "cc"); return crypto_int64_x; #else crypto_int64 crypto_int64_r = crypto_int64_y ^ crypto_int64_x; crypto_int64 crypto_int64_z = crypto_int64_y - crypto_int64_x; crypto_int64_z ^= crypto_int64_r & (crypto_int64_z ^ crypto_int64_y); crypto_int64_z = crypto_int64_negative_mask(crypto_int64_z); crypto_int64_z &= crypto_int64_r; return crypto_int64_x ^ crypto_int64_z; #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_max(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) __asm__ ("cmpq %1,%0\n cmovlq %1,%0" : "+r"(crypto_int64_x) : "r"(crypto_int64_y) : "cc"); return crypto_int64_x; #elif defined(__GNUC__) && defined(__aarch64__) __asm__ ("cmp %0,%1\n csel %0,%1,%0,lt" : "+r"(crypto_int64_x) : "r"(crypto_int64_y) : "cc"); return crypto_int64_x; #else crypto_int64 crypto_int64_r = crypto_int64_y ^ crypto_int64_x; crypto_int64 crypto_int64_z = crypto_int64_y - crypto_int64_x; crypto_int64_z ^= crypto_int64_r & (crypto_int64_z ^ crypto_int64_y); crypto_int64_z = crypto_int64_negative_mask(crypto_int64_z); crypto_int64_z &= crypto_int64_r; return crypto_int64_y ^ crypto_int64_z; #endif } __attribute__((unused)) static inline void crypto_int64_minmax(crypto_int64 *crypto_int64_p,crypto_int64 *crypto_int64_q) { crypto_int64 crypto_int64_x = *crypto_int64_p; crypto_int64 crypto_int64_y = *crypto_int64_q; #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_z; __asm__ ("cmpq %2,%1\n movq %1,%0\n cmovgq %2,%1\n cmovgq %0,%2" : "=&r"(crypto_int64_z), "+&r"(crypto_int64_x), "+r"(crypto_int64_y) : : "cc"); *crypto_int64_p = crypto_int64_x; *crypto_int64_q = crypto_int64_y; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_r, crypto_int64_s; __asm__ ("cmp %2,%3\n csel %0,%2,%3,lt\n csel %1,%3,%2,lt" : "=&r"(crypto_int64_r), "=r"(crypto_int64_s) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); *crypto_int64_p = crypto_int64_r; *crypto_int64_q = crypto_int64_s; #else crypto_int64 crypto_int64_r = crypto_int64_y ^ crypto_int64_x; crypto_int64 crypto_int64_z = crypto_int64_y - crypto_int64_x; crypto_int64_z ^= crypto_int64_r & (crypto_int64_z ^ crypto_int64_y); crypto_int64_z = crypto_int64_negative_mask(crypto_int64_z); crypto_int64_z &= crypto_int64_r; crypto_int64_x ^= crypto_int64_z; crypto_int64_y ^= crypto_int64_z; *crypto_int64_p = crypto_int64_x; *crypto_int64_q = crypto_int64_y; #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_smaller_mask(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $-1,%1\n cmpq %3,%2\n cmovlq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n csetm %0,lt" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else crypto_int64 crypto_int64_r = crypto_int64_x ^ crypto_int64_y; crypto_int64 crypto_int64_z = crypto_int64_x - crypto_int64_y; crypto_int64_z ^= crypto_int64_r & (crypto_int64_z ^ crypto_int64_x); return crypto_int64_negative_mask(crypto_int64_z); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_smaller_01(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $1,%1\n cmpq %3,%2\n cmovlq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n cset %0,lt" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else crypto_int64 crypto_int64_r = crypto_int64_x ^ crypto_int64_y; crypto_int64 crypto_int64_z = crypto_int64_x - crypto_int64_y; crypto_int64_z ^= crypto_int64_r & (crypto_int64_z ^ crypto_int64_x); return crypto_int64_unsigned_topbit_01(crypto_int64_z); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_leq_mask(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $-1,%1\n cmpq %3,%2\n cmovleq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n csetm %0,le" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else return ~crypto_int64_smaller_mask(crypto_int64_y,crypto_int64_x); #endif } __attribute__((unused)) static inline crypto_int64 crypto_int64_leq_01(crypto_int64 crypto_int64_x,crypto_int64 crypto_int64_y) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 crypto_int64_q,crypto_int64_z; __asm__ ("xorq %0,%0\n movq $1,%1\n cmpq %3,%2\n cmovleq %1,%0" : "=&r"(crypto_int64_z), "=&r"(crypto_int64_q) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #elif defined(__GNUC__) && defined(__aarch64__) crypto_int64 crypto_int64_z; __asm__ ("cmp %1,%2\n cset %0,le" : "=r"(crypto_int64_z) : "r"(crypto_int64_x), "r"(crypto_int64_y) : "cc"); return crypto_int64_z; #else return 1-crypto_int64_smaller_01(crypto_int64_y,crypto_int64_x); #endif } __attribute__((unused)) static inline int crypto_int64_ones_num(crypto_int64 crypto_int64_x) { crypto_int64_unsigned crypto_int64_y = crypto_int64_x; const crypto_int64 C0 = 0x5555555555555555; const crypto_int64 C1 = 0x3333333333333333; const crypto_int64 C2 = 0x0f0f0f0f0f0f0f0f; crypto_int64_y -= ((crypto_int64_y >> 1) & C0); crypto_int64_y = (crypto_int64_y & C1) + ((crypto_int64_y >> 2) & C1); crypto_int64_y = (crypto_int64_y + (crypto_int64_y >> 4)) & C2; crypto_int64_y += crypto_int64_y >> 8; crypto_int64_y += crypto_int64_y >> 16; crypto_int64_y = (crypto_int64_y + (crypto_int64_y >> 32)) & 0xff; return crypto_int64_y; } __attribute__((unused)) static inline int crypto_int64_bottomzeros_num(crypto_int64 crypto_int64_x) { #if defined(__GNUC__) && defined(__x86_64__) crypto_int64 fallback = 64; __asm__ ("bsfq %0,%0\n cmoveq %1,%0" : "+&r"(crypto_int64_x) : "r"(fallback) : "cc"); return crypto_int64_x; #elif defined(__GNUC__) && defined(__aarch64__) int64_t crypto_int64_y; __asm__ ("rbit %0,%1\n clz %0,%0" : "=r"(crypto_int64_y) : "r"(crypto_int64_x) : ); return crypto_int64_y; #else crypto_int64 crypto_int64_y = crypto_int64_x ^ (crypto_int64_x-1); crypto_int64_y = ((crypto_int64) crypto_int64_y) >> 1; crypto_int64_y &= ~(crypto_int64_x & (((crypto_int64) 1) << (64-1))); return crypto_int64_ones_num(crypto_int64_y); #endif } #endif /* from supercop-20240808/crypto_sort/int32/portable4/sort.c */ #define int32_MINMAX(a,b) crypto_int32_minmax(&a,&b) static void crypto_sort_int32(void *array,long long n) { long long top,p,q,r,i,j; int32 *x = array; if (n < 2) return; top = 1; while (top < n - top) top += top; for (p = top;p >= 1;p >>= 1) { i = 0; while (i + 2 * p <= n) { for (j = i;j < i + p;++j) int32_MINMAX(x[j],x[j+p]); i += 2 * p; } for (j = i;j < n - p;++j) int32_MINMAX(x[j],x[j+p]); i = 0; j = 0; for (q = top;q > p;q >>= 1) { if (j != i) for (;;) { if (j == n - q) goto done; int32 a = x[j + p]; for (r = q;r > p;r >>= 1) int32_MINMAX(a,x[j + r]); x[j + p] = a; ++j; if (j == i + p) { i += 2 * p; break; } } while (i + p <= n - q) { for (j = i;j < i + p;++j) { int32 a = x[j + p]; for (r = q;r > p;r >>= 1) int32_MINMAX(a,x[j+r]); x[j + p] = a; } i += 2 * p; } /* now i + p > n - q */ j = i; while (j < n - q) { int32 a = x[j + p]; for (r = q;r > p;r >>= 1) int32_MINMAX(a,x[j+r]); x[j + p] = a; ++j; } done: ; } } } /* from supercop-20240808/crypto_sort/uint32/useint32/sort.c */ /* can save time by vectorizing xor loops */ /* can save time by integrating xor loops with int32_sort */ static void crypto_sort_uint32(void *array,long long n) { crypto_uint32 *x = array; long long j; for (j = 0;j < n;++j) x[j] ^= 0x80000000; crypto_sort_int32(array,n); for (j = 0;j < n;++j) x[j] ^= 0x80000000; } /* from supercop-20240808/crypto_kem/sntrup761/compact/kem.c */ // 20240806 djb: some automated conversion to cryptoint #define p 761 #define q 4591 #define w 286 #define q12 ((q - 1) / 2) typedef int8_t small; typedef int16_t Fq; #define Hash_bytes 32 #define Small_bytes ((p + 3) / 4) typedef small Inputs[p]; #define SecretKeys_bytes (2 * Small_bytes) #define Confirm_bytes 32 static small F3_freeze(int16_t x) { return x - 3 * ((10923 * x + 16384) >> 15); } static Fq Fq_freeze(int32_t x) { const int32_t q16 = (0x10000 + q / 2) / q; const int32_t q20 = (0x100000 + q / 2) / q; const int32_t q28 = (0x10000000 + q / 2) / q; x -= q * ((q16 * x) >> 16); x -= q * ((q20 * x) >> 20); return x - q * ((q28 * x + 0x8000000) >> 28); } static int Weightw_mask(small *r) { int i, weight = 0; for (i = 0; i < p; ++i) weight += crypto_int64_bottombit_01(r[i]); return crypto_int16_nonzero_mask(weight - w); } static void uint32_divmod_uint14(uint32_t *Q, uint16_t *r, uint32_t x, uint16_t m) { uint32_t qpart, mask, v = 0x80000000 / m; qpart = (x * (uint64_t)v) >> 31; x -= qpart * m; *Q = qpart; qpart = (x * (uint64_t)v) >> 31; x -= qpart * m; *Q += qpart; x -= m; *Q += 1; mask = crypto_int32_negative_mask(x); x += mask & (uint32_t)m; *Q += mask; *r = x; } static uint16_t uint32_mod_uint14(uint32_t x, uint16_t m) { uint32_t Q; uint16_t r; uint32_divmod_uint14(&Q, &r, x, m); return r; } static void Encode(unsigned char *out, const uint16_t *R, const uint16_t *M, long long len) { if (len == 1) { uint16_t r = R[0], m = M[0]; while (m > 1) { *out++ = r; r >>= 8; m = (m + 255) >> 8; } } if (len > 1) { uint16_t R2[(len + 1) / 2], M2[(len + 1) / 2]; long long i; for (i = 0; i < len - 1; i += 2) { uint32_t m0 = M[i]; uint32_t r = R[i] + R[i + 1] * m0; uint32_t m = M[i + 1] * m0; while (m >= 16384) { *out++ = r; r >>= 8; m = (m + 255) >> 8; } R2[i / 2] = r; M2[i / 2] = m; } if (i < len) { R2[i / 2] = R[i]; M2[i / 2] = M[i]; } Encode(out, R2, M2, (len + 1) / 2); } } static void Decode(uint16_t *out, const unsigned char *S, const uint16_t *M, long long len) { if (len == 1) { if (M[0] == 1) *out = 0; else if (M[0] <= 256) *out = uint32_mod_uint14(S[0], M[0]); else *out = uint32_mod_uint14(S[0] + (((uint16_t)S[1]) << 8), M[0]); } if (len > 1) { uint16_t R2[(len + 1) / 2], M2[(len + 1) / 2], bottomr[len / 2]; uint32_t bottomt[len / 2]; long long i; for (i = 0; i < len - 1; i += 2) { uint32_t m = M[i] * (uint32_t)M[i + 1]; if (m > 256 * 16383) { bottomt[i / 2] = 256 * 256; bottomr[i / 2] = S[0] + 256 * S[1]; S += 2; M2[i / 2] = (((m + 255) >> 8) + 255) >> 8; } else if (m >= 16384) { bottomt[i / 2] = 256; bottomr[i / 2] = S[0]; S += 1; M2[i / 2] = (m + 255) >> 8; } else { bottomt[i / 2] = 1; bottomr[i / 2] = 0; M2[i / 2] = m; } } if (i < len) M2[i / 2] = M[i]; Decode(R2, S, M2, (len + 1) / 2); for (i = 0; i < len - 1; i += 2) { uint32_t r1, r = bottomr[i / 2]; uint16_t r0; r += bottomt[i / 2] * R2[i / 2]; uint32_divmod_uint14(&r1, &r0, r, M[i]); r1 = uint32_mod_uint14(r1, M[i + 1]); *out++ = r0; *out++ = r1; } if (i < len) *out++ = R2[i / 2]; } } static void R3_fromRq(small *out, const Fq *r) { int i; for (i = 0; i < p; ++i) out[i] = F3_freeze(r[i]); } static void R3_mult(small *h, const small *f, const small *g) { int16_t fg[p + p - 1]; int i, j; for (i = 0; i < p + p - 1; ++i) fg[i] = 0; for (i = 0; i < p; ++i) for (j = 0; j < p; ++j) fg[i + j] += f[i] * (int16_t)g[j]; for (i = p; i < p + p - 1; ++i) fg[i - p] += fg[i]; for (i = p; i < p + p - 1; ++i) fg[i - p + 1] += fg[i]; for (i = 0; i < p; ++i) h[i] = F3_freeze(fg[i]); } static int R3_recip(small *out, const small *in) { small f[p + 1], g[p + 1], v[p + 1], r[p + 1]; int sign, swap, t, i, loop, delta = 1; for (i = 0; i < p + 1; ++i) v[i] = 0; for (i = 0; i < p + 1; ++i) r[i] = 0; r[0] = 1; for (i = 0; i < p; ++i) f[i] = 0; f[0] = 1; f[p - 1] = f[p] = -1; for (i = 0; i < p; ++i) g[p - 1 - i] = in[i]; g[p] = 0; for (loop = 0; loop < 2 * p - 1; ++loop) { for (i = p; i > 0; --i) v[i] = v[i - 1]; v[0] = 0; sign = -g[0] * f[0]; swap = crypto_int16_negative_mask(-delta) & crypto_int16_nonzero_mask(g[0]); delta ^= swap & (delta ^ -delta); delta += 1; for (i = 0; i < p + 1; ++i) { t = swap & (f[i] ^ g[i]); f[i] ^= t; g[i] ^= t; t = swap & (v[i] ^ r[i]); v[i] ^= t; r[i] ^= t; } for (i = 0; i < p + 1; ++i) g[i] = F3_freeze(g[i] + sign * f[i]); for (i = 0; i < p + 1; ++i) r[i] = F3_freeze(r[i] + sign * v[i]); for (i = 0; i < p; ++i) g[i] = g[i + 1]; g[p] = 0; } sign = f[0]; for (i = 0; i < p; ++i) out[i] = sign * v[p - 1 - i]; return crypto_int16_nonzero_mask(delta); } static void Rq_mult_small(Fq *h, const Fq *f, const small *g) { int32_t fg[p + p - 1]; int i, j; for (i = 0; i < p + p - 1; ++i) fg[i] = 0; for (i = 0; i < p; ++i) for (j = 0; j < p; ++j) fg[i + j] += f[i] * (int32_t)g[j]; for (i = p; i < p + p - 1; ++i) fg[i - p] += fg[i]; for (i = p; i < p + p - 1; ++i) fg[i - p + 1] += fg[i]; for (i = 0; i < p; ++i) h[i] = Fq_freeze(fg[i]); } static void Rq_mult3(Fq *h, const Fq *f) { int i; for (i = 0; i < p; ++i) h[i] = Fq_freeze(3 * f[i]); } static Fq Fq_recip(Fq a1) { int i = 1; Fq ai = a1; while (i < q - 2) { ai = Fq_freeze(a1 * (int32_t)ai); i += 1; } return ai; } static int Rq_recip3(Fq *out, const small *in) { Fq f[p + 1], g[p + 1], v[p + 1], r[p + 1], scale; int swap, t, i, loop, delta = 1; int32_t f0, g0; for (i = 0; i < p + 1; ++i) v[i] = 0; for (i = 0; i < p + 1; ++i) r[i] = 0; r[0] = Fq_recip(3); for (i = 0; i < p; ++i) f[i] = 0; f[0] = 1; f[p - 1] = f[p] = -1; for (i = 0; i < p; ++i) g[p - 1 - i] = in[i]; g[p] = 0; for (loop = 0; loop < 2 * p - 1; ++loop) { for (i = p; i > 0; --i) v[i] = v[i - 1]; v[0] = 0; swap = crypto_int16_negative_mask(-delta) & crypto_int16_nonzero_mask(g[0]); delta ^= swap & (delta ^ -delta); delta += 1; for (i = 0; i < p + 1; ++i) { t = swap & (f[i] ^ g[i]); f[i] ^= t; g[i] ^= t; t = swap & (v[i] ^ r[i]); v[i] ^= t; r[i] ^= t; } f0 = f[0]; g0 = g[0]; for (i = 0; i < p + 1; ++i) g[i] = Fq_freeze(f0 * g[i] - g0 * f[i]); for (i = 0; i < p + 1; ++i) r[i] = Fq_freeze(f0 * r[i] - g0 * v[i]); for (i = 0; i < p; ++i) g[i] = g[i + 1]; g[p] = 0; } scale = Fq_recip(f[0]); for (i = 0; i < p; ++i) out[i] = Fq_freeze(scale * (int32_t)v[p - 1 - i]); return crypto_int16_nonzero_mask(delta); } static void Round(Fq *out, const Fq *a) { int i; for (i = 0; i < p; ++i) out[i] = a[i] - F3_freeze(a[i]); } static void Short_fromlist(small *out, const uint32_t *in) { uint32_t L[p]; int i; for (i = 0; i < w; ++i) L[i] = in[i] & (uint32_t)-2; for (i = w; i < p; ++i) L[i] = (in[i] & (uint32_t)-3) | 1; crypto_sort_uint32(L, p); for (i = 0; i < p; ++i) out[i] = (L[i] & 3) - 1; } static void Hash_prefix(unsigned char *out, int b, const unsigned char *in, int inlen) { unsigned char x[inlen + 1], h[64]; int i; x[0] = b; for (i = 0; i < inlen; ++i) x[i + 1] = in[i]; crypto_hash_sha512(h, x, inlen + 1); for (i = 0; i < 32; ++i) out[i] = h[i]; } static uint32_t urandom32(void) { unsigned char c[4]; uint32_t result = 0; int i; randombytes(c, 4); for (i = 0; i < 4; ++i) result += ((uint32_t)c[i]) << (8 * i); return result; } static void Short_random(small *out) { uint32_t L[p]; int i; for (i = 0; i < p; ++i) L[i] = urandom32(); Short_fromlist(out, L); } static void Small_random(small *out) { int i; for (i = 0; i < p; ++i) out[i] = (((urandom32() & 0x3fffffff) * 3) >> 30) - 1; } static void KeyGen(Fq *h, small *f, small *ginv) { small g[p]; Fq finv[p]; for (;;) { int result; Small_random(g); result = R3_recip(ginv, g); crypto_declassify(&result, sizeof result); if (result == 0) break; } Short_random(f); Rq_recip3(finv, f); Rq_mult_small(h, finv, g); } static void Encrypt(Fq *c, const small *r, const Fq *h) { Fq hr[p]; Rq_mult_small(hr, h, r); Round(c, hr); } static void Decrypt(small *r, const Fq *c, const small *f, const small *ginv) { Fq cf[p], cf3[p]; small e[p], ev[p]; int mask, i; Rq_mult_small(cf, c, f); Rq_mult3(cf3, cf); R3_fromRq(e, cf3); R3_mult(ev, e, ginv); mask = Weightw_mask(ev); for (i = 0; i < w; ++i) r[i] = ((ev[i] ^ 1) & ~mask) ^ 1; for (i = w; i < p; ++i) r[i] = ev[i] & ~mask; } static void Small_encode(unsigned char *s, const small *f) { int i, j; for (i = 0; i < p / 4; ++i) { small x = 0; for (j = 0;j < 4;++j) x += (*f++ + 1) << (2 * j); *s++ = x; } *s = *f++ + 1; } static void Small_decode(small *f, const unsigned char *s) { int i, j; for (i = 0; i < p / 4; ++i) { unsigned char x = *s++; for (j = 0;j < 4;++j) *f++ = ((small)((x >> (2 * j)) & 3)) - 1; } *f++ = ((small)(*s & 3)) - 1; } static void Rq_encode(unsigned char *s, const Fq *r) { uint16_t R[p], M[p]; int i; for (i = 0; i < p; ++i) R[i] = r[i] + q12; for (i = 0; i < p; ++i) M[i] = q; Encode(s, R, M, p); } static void Rq_decode(Fq *r, const unsigned char *s) { uint16_t R[p], M[p]; int i; for (i = 0; i < p; ++i) M[i] = q; Decode(R, s, M, p); for (i = 0; i < p; ++i) r[i] = ((Fq)R[i]) - q12; } static void Rounded_encode(unsigned char *s, const Fq *r) { uint16_t R[p], M[p]; int i; for (i = 0; i < p; ++i) R[i] = ((r[i] + q12) * 10923) >> 15; for (i = 0; i < p; ++i) M[i] = (q + 2) / 3; Encode(s, R, M, p); } static void Rounded_decode(Fq *r, const unsigned char *s) { uint16_t R[p], M[p]; int i; for (i = 0; i < p; ++i) M[i] = (q + 2) / 3; Decode(R, s, M, p); for (i = 0; i < p; ++i) r[i] = R[i] * 3 - q12; } static void ZKeyGen(unsigned char *pk, unsigned char *sk) { Fq h[p]; small f[p], v[p]; KeyGen(h, f, v); Rq_encode(pk, h); Small_encode(sk, f); Small_encode(sk + Small_bytes, v); } static void ZEncrypt(unsigned char *C, const Inputs r, const unsigned char *pk) { Fq h[p], c[p]; Rq_decode(h, pk); Encrypt(c, r, h); Rounded_encode(C, c); } static void ZDecrypt(Inputs r, const unsigned char *C, const unsigned char *sk) { small f[p], v[p]; Fq c[p]; Small_decode(f, sk); Small_decode(v, sk + Small_bytes); Rounded_decode(c, C); Decrypt(r, c, f, v); } static void HashConfirm(unsigned char *h, const unsigned char *r, const unsigned char *cache) { unsigned char x[Hash_bytes * 2]; int i; Hash_prefix(x, 3, r, Small_bytes); for (i = 0; i < Hash_bytes; ++i) x[Hash_bytes + i] = cache[i]; Hash_prefix(h, 2, x, sizeof x); } static void HashSession(unsigned char *k, int b, const unsigned char *y, const unsigned char *z) { unsigned char x[Hash_bytes + crypto_kem_sntrup761_CIPHERTEXTBYTES]; int i; Hash_prefix(x, 3, y, Small_bytes); for (i = 0; i < crypto_kem_sntrup761_CIPHERTEXTBYTES; ++i) x[Hash_bytes + i] = z[i]; Hash_prefix(k, b, x, sizeof x); } int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk) { int i; ZKeyGen(pk, sk); sk += SecretKeys_bytes; for (i = 0; i < crypto_kem_sntrup761_PUBLICKEYBYTES; ++i) *sk++ = pk[i]; randombytes(sk, Small_bytes); Hash_prefix(sk + Small_bytes, 4, pk, crypto_kem_sntrup761_PUBLICKEYBYTES); return 0; } static void Hide(unsigned char *c, unsigned char *r_enc, const Inputs r, const unsigned char *pk, const unsigned char *cache) { Small_encode(r_enc, r); ZEncrypt(c, r, pk); HashConfirm(c + crypto_kem_sntrup761_CIPHERTEXTBYTES - Confirm_bytes, r_enc, cache); } int crypto_kem_sntrup761_enc(unsigned char *c, unsigned char *k, const unsigned char *pk) { Inputs r; unsigned char r_enc[Small_bytes], cache[Hash_bytes]; Hash_prefix(cache, 4, pk, crypto_kem_sntrup761_PUBLICKEYBYTES); Short_random(r); Hide(c, r_enc, r, pk, cache); HashSession(k, 1, r_enc, c); return 0; } static int Ciphertexts_diff_mask(const unsigned char *c, const unsigned char *c2) { uint16_t differentbits = 0; int len = crypto_kem_sntrup761_CIPHERTEXTBYTES; while (len-- > 0) differentbits |= (*c++) ^ (*c2++); return (crypto_int64_bitmod_01((differentbits - 1),8)) - 1; } int crypto_kem_sntrup761_dec(unsigned char *k, const unsigned char *c, const unsigned char *sk) { const unsigned char *pk = sk + SecretKeys_bytes; const unsigned char *rho = pk + crypto_kem_sntrup761_PUBLICKEYBYTES; const unsigned char *cache = rho + Small_bytes; Inputs r; unsigned char r_enc[Small_bytes], cnew[crypto_kem_sntrup761_CIPHERTEXTBYTES]; int mask, i; ZDecrypt(r, c, sk); Hide(cnew, r_enc, r, pk, cache); mask = Ciphertexts_diff_mask(c, cnew); for (i = 0; i < Small_bytes; ++i) r_enc[i] ^= mask & (r_enc[i] ^ rho[i]); HashSession(k, 1 + mask, r_enc, c); return 0; } #endif /* USE_SNTRUP761X25519 */ openssh-10.0p1/PaxHeaders.10889/sntrup761.sh100644 001750 001750 0000000003614775415623 0015301xustar0030 atime=1744182234.801586615 openssh-10.0p1/sntrup761.sh010064400017500001750000000072171477541562300136730ustar00djmdjm#!/bin/sh # $OpenBSD: sntrup761.sh,v 1.9 2024/09/16 05:37:05 djm Exp $ # Placed in the Public Domain. # AUTHOR="supercop-20240808/crypto_kem/sntrup761/ref/implementors" FILES=" supercop-20240808/cryptoint/crypto_int16.h supercop-20240808/cryptoint/crypto_int32.h supercop-20240808/cryptoint/crypto_int64.h supercop-20240808/crypto_sort/int32/portable4/sort.c supercop-20240808/crypto_sort/uint32/useint32/sort.c supercop-20240808/crypto_kem/sntrup761/compact/kem.c " ### set -euo pipefail cd $1 echo -n '/* $' echo 'OpenBSD: $ */' echo echo '/*' echo ' * Public Domain, Authors:' sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR echo ' */' echo echo '#include ' echo '#include "crypto_api.h"' echo echo '#define crypto_declassify(x, y) do {} while (0)' echo # Map the types used in this code to the ones in crypto_api.h. We use #define # instead of typedef since some systems have existing intXX types and do not # permit multiple typedefs even if they do not conflict. for t in int8 uint8 int16 uint16 int32 uint32 int64 uint64; do echo "#define $t crypto_${t}" done for x in 16 32 64 ; do echo "extern volatile crypto_int$x crypto_int${x}_optblocker;" done echo for i in $FILES; do echo "/* from $i */" # Changes to all files: # - remove all includes, we inline everything required. # - make functions not required elsewhere static. # - rename the functions we do use. # - remove unnecessary defines and externs. sed -e "/#include/d" \ -e "s/crypto_kem_/crypto_kem_sntrup761_/g" \ -e "s/^void /static void /g" \ -e "s/^int16 /static int16 /g" \ -e "s/^uint16 /static uint16 /g" \ -e "/^extern /d" \ -e '/CRYPTO_NAMESPACE/d' \ -e "/^#define int32 crypto_int32/d" \ -e 's/[ ]*$//' \ $i | \ case "$i" in */cryptoint/crypto_int16.h) sed -e "s/static void crypto_int16_store/void crypto_int16_store/" \ -e "s/^[#]define crypto_int16_optblocker.*//" \ -e "s/static void crypto_int16_minmax/void crypto_int16_minmax/" ;; */cryptoint/crypto_int32.h) # Use int64_t for intermediate values in crypto_int32_minmax to # prevent signed 32-bit integer overflow when called by # crypto_sort_int32. Original code depends on -fwrapv (we set -ftrapv) sed -e "s/static void crypto_int32_store/void crypto_int32_store/" \ -e "s/^[#]define crypto_int32_optblocker.*//" \ -e "s/crypto_int32 crypto_int32_r = crypto_int32_y ^ crypto_int32_x;/crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x;/" \ -e "s/crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x;/crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x;/" \ -e "s/static void crypto_int32_minmax/void crypto_int32_minmax/" ;; */cryptoint/crypto_int64.h) sed -e "s/static void crypto_int64_store/void crypto_int64_store/" \ -e "s/^[#]define crypto_int64_optblocker.*//" \ -e "s/static void crypto_int64_minmax/void crypto_int64_minmax/" ;; */int32/portable4/sort.c) sed -e "s/void crypto_sort[(]/void crypto_sort_int32(/g" ;; */int32/portable5/sort.c) sed -e "s/crypto_sort_smallindices/crypto_sort_int32_smallindices/"\ -e "s/void crypto_sort[(]/void crypto_sort_int32(/g" ;; */uint32/useint32/sort.c) sed -e "s/void crypto_sort/void crypto_sort_uint32/g" ;; # Remove unused function to prevent warning. */crypto_kem/sntrup761/ref/int32.c) sed -e '/ int32_div_uint14/,/^}$/d' ;; # Remove unused function to prevent warning. */crypto_kem/sntrup761/ref/uint32.c) sed -e '/ uint32_div_uint14/,/^}$/d' ;; # Default: pass through. *) cat ;; esac echo done openssh-10.0p1/PaxHeaders.10889/srclimit.c100644 001750 001750 0000000003614775415623 0015146xustar0030 atime=1744182234.822093514 openssh-10.0p1/srclimit.c010064400017500001750000000354201477541562300135350ustar00djmdjm/* * Copyright (c) 2020 Darren Tucker * Copyright (c) 2024 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include "addr.h" #include "canohost.h" #include "log.h" #include "misc.h" #include "srclimit.h" #include "xmalloc.h" #include "servconf.h" #include "match.h" static int max_children, max_persource, ipv4_masklen, ipv6_masklen; static struct per_source_penalty penalty_cfg; static char *penalty_exempt; /* Per connection state, used to enforce unauthenticated connection limit. */ static struct child_info { int id; struct xaddr addr; } *children; /* * Penalised addresses, active entries here prohibit connections until expired. * Entries become active when more than penalty_min seconds of penalty are * outstanding. */ struct penalty { struct xaddr addr; time_t expiry; int active; const char *reason; RB_ENTRY(penalty) by_addr; RB_ENTRY(penalty) by_expiry; }; static int penalty_addr_cmp(struct penalty *a, struct penalty *b); static int penalty_expiry_cmp(struct penalty *a, struct penalty *b); RB_HEAD(penalties_by_addr, penalty) penalties_by_addr4, penalties_by_addr6; RB_HEAD(penalties_by_expiry, penalty) penalties_by_expiry4, penalties_by_expiry6; RB_GENERATE_STATIC(penalties_by_addr, penalty, by_addr, penalty_addr_cmp) RB_GENERATE_STATIC(penalties_by_expiry, penalty, by_expiry, penalty_expiry_cmp) static size_t npenalties4, npenalties6; static int srclimit_mask_addr(const struct xaddr *addr, int bits, struct xaddr *masked) { struct xaddr xmask; /* Mask address off address to desired size. */ if (addr_netmask(addr->af, bits, &xmask) != 0 || addr_and(masked, addr, &xmask) != 0) { debug3_f("%s: invalid mask %d bits", __func__, bits); return -1; } return 0; } static int srclimit_peer_addr(int sock, struct xaddr *addr) { struct sockaddr_storage storage; socklen_t addrlen = sizeof(storage); struct sockaddr *sa = (struct sockaddr *)&storage; if (getpeername(sock, sa, &addrlen) != 0) return 1; /* not remote socket? */ if (addr_sa_to_xaddr(sa, addrlen, addr) != 0) return 1; /* unknown address family? */ return 0; } void srclimit_init(int max, int persource, int ipv4len, int ipv6len, struct per_source_penalty *penalty_conf, const char *penalty_exempt_conf) { int i; max_children = max; ipv4_masklen = ipv4len; ipv6_masklen = ipv6len; max_persource = persource; penalty_cfg = *penalty_conf; if (penalty_cfg.max_sources4 < 0 || penalty_cfg.max_sources6 < 0) fatal_f("invalid max_sources"); /* shouldn't happen */ penalty_exempt = penalty_exempt_conf == NULL ? NULL : xstrdup(penalty_exempt_conf); RB_INIT(&penalties_by_addr4); RB_INIT(&penalties_by_expiry4); RB_INIT(&penalties_by_addr6); RB_INIT(&penalties_by_expiry6); if (max_persource == INT_MAX) /* no limit */ return; debug("%s: max connections %d, per source %d, masks %d,%d", __func__, max, persource, ipv4len, ipv6len); if (max <= 0) fatal("%s: invalid number of sockets: %d", __func__, max); children = xcalloc(max_children, sizeof(*children)); for (i = 0; i < max_children; i++) children[i].id = -1; } /* returns 1 if connection allowed, 0 if not allowed. */ int srclimit_check_allow(int sock, int id) { struct xaddr xa, xb; int i, bits, first_unused, count = 0; char xas[NI_MAXHOST]; if (max_persource == INT_MAX) /* no limit */ return 1; debug("%s: sock %d id %d limit %d", __func__, sock, id, max_persource); if (srclimit_peer_addr(sock, &xa) != 0) return 1; bits = xa.af == AF_INET ? ipv4_masklen : ipv6_masklen; if (srclimit_mask_addr(&xa, bits, &xb) != 0) return 1; first_unused = max_children; /* Count matching entries and find first unused one. */ for (i = 0; i < max_children; i++) { if (children[i].id == -1) { if (i < first_unused) first_unused = i; } else if (addr_cmp(&children[i].addr, &xb) == 0) { count++; } } if (addr_ntop(&xa, xas, sizeof(xas)) != 0) { debug3("%s: addr ntop failed", __func__); return 1; } debug3("%s: new unauthenticated connection from %s/%d, at %d of %d", __func__, xas, bits, count, max_persource); if (first_unused == max_children) { /* no free slot found */ debug3("%s: no free slot", __func__); return 0; } if (first_unused < 0 || first_unused >= max_children) fatal("%s: internal error: first_unused out of range", __func__); if (count >= max_persource) return 0; /* Connection allowed, store masked address. */ children[first_unused].id = id; memcpy(&children[first_unused].addr, &xb, sizeof(xb)); return 1; } void srclimit_done(int id) { int i; if (max_persource == INT_MAX) /* no limit */ return; debug("%s: id %d", __func__, id); /* Clear corresponding state entry. */ for (i = 0; i < max_children; i++) { if (children[i].id == id) { children[i].id = -1; return; } } } static int penalty_addr_cmp(struct penalty *a, struct penalty *b) { return addr_cmp(&a->addr, &b->addr); /* Addresses must be unique in by_addr, so no need to tiebreak */ } static int penalty_expiry_cmp(struct penalty *a, struct penalty *b) { if (a->expiry != b->expiry) return a->expiry < b->expiry ? -1 : 1; /* Tiebreak on addresses */ return addr_cmp(&a->addr, &b->addr); } static void expire_penalties_from_tree(time_t now, const char *t, struct penalties_by_expiry *by_expiry, struct penalties_by_addr *by_addr, size_t *npenaltiesp) { struct penalty *penalty, *tmp; /* XXX avoid full scan of tree, e.g. min-heap */ RB_FOREACH_SAFE(penalty, penalties_by_expiry, by_expiry, tmp) { if (penalty->expiry >= now) break; if (RB_REMOVE(penalties_by_expiry, by_expiry, penalty) != penalty || RB_REMOVE(penalties_by_addr, by_addr, penalty) != penalty) fatal_f("internal error: %s penalty table corrupt", t); free(penalty); if ((*npenaltiesp)-- == 0) fatal_f("internal error: %s npenalties underflow", t); } } static void expire_penalties(time_t now) { expire_penalties_from_tree(now, "ipv4", &penalties_by_expiry4, &penalties_by_addr4, &npenalties4); expire_penalties_from_tree(now, "ipv6", &penalties_by_expiry6, &penalties_by_addr6, &npenalties6); } static void addr_masklen_ntop(struct xaddr *addr, int masklen, char *s, size_t slen) { size_t o; if (addr_ntop(addr, s, slen) != 0) { strlcpy(s, "UNKNOWN", slen); return; } if ((o = strlen(s)) < slen) snprintf(s + o, slen - o, "/%d", masklen); } int srclimit_penalty_check_allow(int sock, const char **reason) { struct xaddr addr; struct penalty find, *penalty; time_t now; int bits, max_sources, overflow_mode; char addr_s[NI_MAXHOST]; struct penalties_by_addr *by_addr; size_t npenalties; if (!penalty_cfg.enabled) return 1; if (srclimit_peer_addr(sock, &addr) != 0) return 1; if (penalty_exempt != NULL) { if (addr_ntop(&addr, addr_s, sizeof(addr_s)) != 0) return 1; /* shouldn't happen */ if (addr_match_list(addr_s, penalty_exempt) == 1) { return 1; } } now = monotime(); expire_penalties(now); by_addr = addr.af == AF_INET ? &penalties_by_addr4 : &penalties_by_addr6; max_sources = addr.af == AF_INET ? penalty_cfg.max_sources4 : penalty_cfg.max_sources6; overflow_mode = addr.af == AF_INET ? penalty_cfg.overflow_mode : penalty_cfg.overflow_mode6; npenalties = addr.af == AF_INET ? npenalties4 : npenalties6; if (npenalties >= (size_t)max_sources && overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) { *reason = "too many penalised addresses"; return 0; } bits = addr.af == AF_INET ? ipv4_masklen : ipv6_masklen; memset(&find, 0, sizeof(find)); if (srclimit_mask_addr(&addr, bits, &find.addr) != 0) return 1; if ((penalty = RB_FIND(penalties_by_addr, by_addr, &find)) == NULL) return 1; /* no penalty */ if (penalty->expiry < now) { expire_penalties(now); return 1; /* expired penalty */ } if (!penalty->active) return 1; /* Penalty hasn't hit activation threshold yet */ *reason = penalty->reason; return 0; } static void srclimit_early_expire_penalties_from_tree(const char *t, struct penalties_by_expiry *by_expiry, struct penalties_by_addr *by_addr, size_t *npenaltiesp, size_t max_sources) { struct penalty *p = NULL; int bits; char s[NI_MAXHOST + 4]; /* Delete the soonest-to-expire penalties. */ while (*npenaltiesp > max_sources) { if ((p = RB_MIN(penalties_by_expiry, by_expiry)) == NULL) fatal_f("internal error: %s table corrupt (find)", t); bits = p->addr.af == AF_INET ? ipv4_masklen : ipv6_masklen; addr_masklen_ntop(&p->addr, bits, s, sizeof(s)); debug3_f("%s overflow, remove %s", t, s); if (RB_REMOVE(penalties_by_expiry, by_expiry, p) != p || RB_REMOVE(penalties_by_addr, by_addr, p) != p) fatal_f("internal error: %s table corrupt (remove)", t); free(p); (*npenaltiesp)--; } } static void srclimit_early_expire_penalties(void) { srclimit_early_expire_penalties_from_tree("ipv4", &penalties_by_expiry4, &penalties_by_addr4, &npenalties4, (size_t)penalty_cfg.max_sources4); srclimit_early_expire_penalties_from_tree("ipv6", &penalties_by_expiry6, &penalties_by_addr6, &npenalties6, (size_t)penalty_cfg.max_sources6); } void srclimit_penalise(struct xaddr *addr, int penalty_type) { struct xaddr masked; struct penalty *penalty = NULL, *existing = NULL; time_t now; int bits, penalty_secs, max_sources = 0, overflow_mode; char addrnetmask[NI_MAXHOST + 4]; const char *reason = NULL, *t; size_t *npenaltiesp = NULL; struct penalties_by_addr *by_addr = NULL; struct penalties_by_expiry *by_expiry = NULL; if (!penalty_cfg.enabled) return; if (penalty_exempt != NULL) { if (addr_ntop(addr, addrnetmask, sizeof(addrnetmask)) != 0) return; /* shouldn't happen */ if (addr_match_list(addrnetmask, penalty_exempt) == 1) { debug3_f("address %s is exempt", addrnetmask); return; } } switch (penalty_type) { case SRCLIMIT_PENALTY_NONE: return; case SRCLIMIT_PENALTY_CRASH: penalty_secs = penalty_cfg.penalty_crash; reason = "penalty: caused crash"; break; case SRCLIMIT_PENALTY_AUTHFAIL: penalty_secs = penalty_cfg.penalty_authfail; reason = "penalty: failed authentication"; break; case SRCLIMIT_PENALTY_NOAUTH: penalty_secs = penalty_cfg.penalty_noauth; reason = "penalty: connections without attempting authentication"; break; case SRCLIMIT_PENALTY_REFUSECONNECTION: penalty_secs = penalty_cfg.penalty_refuseconnection; reason = "penalty: connection prohibited by RefuseConnection"; break; case SRCLIMIT_PENALTY_GRACE_EXCEEDED: penalty_secs = penalty_cfg.penalty_grace; reason = "penalty: exceeded LoginGraceTime"; break; default: fatal_f("internal error: unknown penalty %d", penalty_type); } bits = addr->af == AF_INET ? ipv4_masklen : ipv6_masklen; if (srclimit_mask_addr(addr, bits, &masked) != 0) return; addr_masklen_ntop(addr, bits, addrnetmask, sizeof(addrnetmask)); now = monotime(); expire_penalties(now); by_expiry = addr->af == AF_INET ? &penalties_by_expiry4 : &penalties_by_expiry6; by_addr = addr->af == AF_INET ? &penalties_by_addr4 : &penalties_by_addr6; max_sources = addr->af == AF_INET ? penalty_cfg.max_sources4 : penalty_cfg.max_sources6; overflow_mode = addr->af == AF_INET ? penalty_cfg.overflow_mode : penalty_cfg.overflow_mode6; npenaltiesp = addr->af == AF_INET ? &npenalties4 : &npenalties6; t = addr->af == AF_INET ? "ipv4" : "ipv6"; if (*npenaltiesp >= (size_t)max_sources && overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) { verbose_f("%s penalty table full, cannot penalise %s for %s", t, addrnetmask, reason); return; } penalty = xcalloc(1, sizeof(*penalty)); penalty->addr = masked; penalty->expiry = now + penalty_secs; penalty->reason = reason; if ((existing = RB_INSERT(penalties_by_addr, by_addr, penalty)) == NULL) { /* penalty didn't previously exist */ if (penalty_secs > penalty_cfg.penalty_min) penalty->active = 1; if (RB_INSERT(penalties_by_expiry, by_expiry, penalty) != NULL) fatal_f("internal error: %s penalty tables corrupt", t); verbose_f("%s: new %s %s penalty of %d seconds for %s", t, addrnetmask, penalty->active ? "active" : "deferred", penalty_secs, reason); if (++(*npenaltiesp) > (size_t)max_sources) srclimit_early_expire_penalties(); /* permissive */ return; } debug_f("%s penalty for %s %s already exists, %lld seconds remaining", existing->active ? "active" : "inactive", t, addrnetmask, (long long)(existing->expiry - now)); /* Expiry information is about to change, remove from tree */ if (RB_REMOVE(penalties_by_expiry, by_expiry, existing) != existing) fatal_f("internal error: %s penalty table corrupt (remove)", t); /* An entry already existed. Accumulate penalty up to maximum */ existing->expiry += penalty_secs; if (existing->expiry - now > penalty_cfg.penalty_max) existing->expiry = now + penalty_cfg.penalty_max; if (existing->expiry - now > penalty_cfg.penalty_min && !existing->active) { verbose_f("%s: activating %s penalty of %lld seconds for %s", addrnetmask, t, (long long)(existing->expiry - now), reason); existing->active = 1; } existing->reason = penalty->reason; free(penalty); penalty = NULL; /* Re-insert into expiry tree */ if (RB_INSERT(penalties_by_expiry, by_expiry, existing) != NULL) fatal_f("internal error: %s penalty table corrupt (insert)", t); } static void srclimit_penalty_info_for_tree(const char *t, struct penalties_by_expiry *by_expiry, size_t npenalties) { struct penalty *p = NULL; int bits; char s[NI_MAXHOST + 4]; time_t now; now = monotime(); logit("%zu active %s penalties", npenalties, t); RB_FOREACH(p, penalties_by_expiry, by_expiry) { bits = p->addr.af == AF_INET ? ipv4_masklen : ipv6_masklen; addr_masklen_ntop(&p->addr, bits, s, sizeof(s)); if (p->expiry < now) logit("client %s %s (expired)", s, p->reason); else { logit("client %s %s (%llu secs left)", s, p->reason, (long long)(p->expiry - now)); } } } void srclimit_penalty_info(void) { srclimit_penalty_info_for_tree("ipv4", &penalties_by_expiry4, npenalties4); srclimit_penalty_info_for_tree("ipv6", &penalties_by_expiry6, npenalties6); } openssh-10.0p1/PaxHeaders.10889/srclimit.h100644 001750 001750 0000000003614775415623 0015153xustar0030 atime=1744182234.822093514 openssh-10.0p1/srclimit.h010064400017500001750000000032001477541562300135310ustar00djmdjm/* * Copyright (c) 2020 Darren Tucker * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ struct xaddr; struct per_source_penalty; void srclimit_init(int, int, int, int, struct per_source_penalty *, const char *); int srclimit_check_allow(int, int); void srclimit_done(int); #define SRCLIMIT_PENALTY_NONE 0 #define SRCLIMIT_PENALTY_CRASH 1 #define SRCLIMIT_PENALTY_AUTHFAIL 2 #define SRCLIMIT_PENALTY_GRACE_EXCEEDED 3 #define SRCLIMIT_PENALTY_NOAUTH 4 #define SRCLIMIT_PENALTY_REFUSECONNECTION 5 /* meaningful exit values, used by sshd listener for penalties */ #define EXIT_LOGIN_GRACE 3 /* login grace period exceeded */ #define EXIT_CHILD_CRASH 4 /* preauth child crashed */ #define EXIT_AUTH_ATTEMPTED 5 /* at least one auth attempt made */ #define EXIT_CONFIG_REFUSED 6 /* sshd_config RefuseConnection */ void srclimit_penalise(struct xaddr *, int); int srclimit_penalty_check_allow(int, const char **); void srclimit_penalty_info(void); openssh-10.0p1/PaxHeaders.10889/ssh-add.0100644 001750 001750 0000000003614775415623 0014560xustar0030 atime=1744182234.823070893 openssh-10.0p1/ssh-add.0010064400017500001750000000240371477541562300131510ustar00djmdjmSSH-ADD(1) General Commands Manual SSH-ADD(1) NAME ssh-add M-bM-^@M-^S adds private key identities to the OpenSSH authentication agent SYNOPSIS ssh-add [-CcDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file] [-h destination_constraint] [-S provider] [-t life] [file ...] ssh-add -s pkcs11 [-Cv] [certificate ...] ssh-add -e pkcs11 ssh-add -T pubkey ... 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_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519_sk. 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 When loading keys into or deleting keys from the agent, process certificates only and skip plain keys. -c Indicates that added identities should be subject to confirmation before being used for authentication. Confirmation is performed by ssh-askpass(1). Successful confirmation is signaled by a zero exit status from ssh-askpass(1), 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. If the argument list consists of M-bM-^@M-^\-M-bM-^@M-^] then ssh-add will read public keys to be removed from standard input. -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. -H hostkey_file Specifies a known hosts file to look up hostkeys when using destination-constrained keys via the -h flag. This option may be specified multiple times to allow multiple files to be searched. If no files are specified, ssh-add will use the default ssh_config(5) known hosts files: ~/.ssh/known_hosts, ~/.ssh/known_hosts2, /etc/ssh/ssh_known_hosts, and /etc/ssh/ssh_known_hosts2. -h destination_constraint When adding keys, constrain them to be usable only through specific hosts or to specific destinations. Destination constraints of the form M-bM-^@M-^X[user@]dest-hostnameM-bM-^@M-^Y permit use of the key only from the origin host (the one running ssh-agent(1)) to the listed destination host, with optional user name. Constraints of the form M-bM-^@M-^Xsrc-hostname>[user@]dst-hostnameM-bM-^@M-^Y allow a key available on a forwarded ssh-agent(1) to be used through a particular host (as specified by M-bM-^@M-^Xsrc-hostnameM-bM-^@M-^Y) to authenticate to a further host, specified by M-bM-^@M-^Xdst-hostnameM-bM-^@M-^Y. Multiple destination constraints may be added when loading keys. When attempting authentication with a key that has destination constraints, the whole connection path, including ssh-agent(1) forwarding, is tested against those constraints and each hop must be permitted for the attempt to succeed. For example, if key is forwarded to a remote host, M-bM-^@M-^Xhost-bM-bM-^@M-^Y, and is attempting authentication to another host, M-bM-^@M-^Xhost-cM-bM-^@M-^Y, then the operation will be successful only if M-bM-^@M-^Xhost-bM-bM-^@M-^Y was permitted from the origin host and the subsequent M-bM-^@M-^Xhost-b>host-cM-bM-^@M-^Y hop is also permitted by destination constraints. Hosts are identified by their host keys, and are looked up from known hosts files by ssh-add. Wildcards patterns may be used for hostnames and certificate host keys are supported. By default, keys added by ssh-add are not destination constrained. Destination constraints were added in OpenSSH release 8.9. Support in both the remote SSH client and server is required when using destination-constrained keys over a forwarded ssh-agent(1) channel. It is also important to note that destination constraints can only be enforced by ssh-agent(1) when a key is used, or when it is forwarded by a cooperating ssh(1). Specifically, it does not prevent an attacker with access to a remote SSH_AUTH_SOCK from forwarding it again and using it on a different host (but only to a permitted destination). -K Load resident keys from a FIDO authenticator. -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. -q Be quiet after a successful operation. -S 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. -s pkcs11 Add keys provided by the PKCS#11 shared library pkcs11. Certificate files may optionally be listed as command-line arguments. If these are present, then they will be loaded into the agent using any corresponding private keys loaded from the PKCS#11 token. -T pubkey ... Tests whether the private keys that correspond to the specified pubkey files are usable by performing sign and verify operations on each. -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). -v Verbose mode. Causes ssh-add to print debugging messages about its progress. This is helpful in debugging problems. Multiple -v options increase the verbosity. The maximum is 3. -X Unlock the agent. -x Lock the agent with a password. ENVIRONMENT DISPLAY, SSH_ASKPASS and SSH_ASKPASS_REQUIRE 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 (by default M-bM-^@M-^\ssh-askpassM-bM-^@M-^]) and open an X11 window to read the passphrase. This is particularly useful when calling ssh-add from a .xsession or related script. SSH_ASKPASS_REQUIRE allows further control over the use of an askpass program. If this variable is set to M-bM-^@M-^\neverM-bM-^@M-^] then ssh-add will never attempt to use one. If it is set to M-bM-^@M-^\preferM-bM-^@M-^], then ssh-add will prefer to use the askpass program instead of the TTY when requesting passwords. Finally, if the variable is set to M-bM-^@M-^\forceM-bM-^@M-^], then the askpass program will be used for all passphrase input regardless of whether DISPLAY is set. SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to communicate with the agent. 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. FILES ~/.ssh/id_ecdsa ~/.ssh/id_ecdsa_sk ~/.ssh/id_ed25519 ~/.ssh/id_ed25519_sk ~/.ssh/id_rsa Contains the ECDSA, authenticator-hosted ECDSA, Ed25519, authenticator-hosted Ed25519 or 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-askpass(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 7.6 June 17, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh-add.1100644 001750 001750 0000000003614775415623 0014561xustar0030 atime=1744182234.823070893 openssh-10.0p1/ssh-add.1010064400017500001750000000247461477541562300131610ustar00djmdjm.\" $OpenBSD: ssh-add.1,v 1.87 2024/06/17 08:30:29 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .Dd $Mdocdate: June 17 2024 $ .Dt SSH-ADD 1 .Os .Sh NAME .Nm ssh-add .Nd adds private key identities to the OpenSSH authentication agent .Sh SYNOPSIS .Nm ssh-add .Op Fl CcDdKkLlqvXx .Op Fl E Ar fingerprint_hash .Op Fl H Ar hostkey_file .Op Fl h Ar destination_constraint .Op Fl S Ar provider .Op Fl t Ar life .Op Ar .Nm ssh-add .Fl s Ar pkcs11 .Op Fl Cv .Op Ar certificate ... .Nm ssh-add .Fl e Ar pkcs11 .Nm ssh-add .Fl T .Ar pubkey ... .Sh DESCRIPTION .Nm adds private key identities to the authentication agent, .Xr ssh-agent 1 . When run without arguments, it adds the files .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ecdsa_sk , .Pa ~/.ssh/id_ed25519 and .Pa ~/.ssh/id_ed25519_sk . After loading a private key, .Nm will try to load corresponding certificate information from the filename obtained by appending .Pa -cert.pub to the name of the private key file. Alternative file names can be given on the command line. .Pp If any file requires a passphrase, .Nm asks for the passphrase from the user. The passphrase is read from the user's tty. .Nm retries the last passphrase if multiple identity files are given. .Pp The authentication agent must be running and the .Ev SSH_AUTH_SOCK environment variable must contain the name of its socket for .Nm to work. .Pp The options are as follows: .Bl -tag -width Ds .It Fl C When loading keys into or deleting keys from the agent, process certificates only and skip plain keys. .It Fl c Indicates that added identities should be subject to confirmation before being used for authentication. Confirmation is performed by .Xr ssh-askpass 1 . Successful confirmation is signaled by a zero exit status from .Xr ssh-askpass 1 , rather than text entered into the requester. .It Fl D Deletes all identities from the agent. .It Fl d Instead of adding identities, removes identities from the agent. If .Nm has been run without arguments, the keys for the default identities and their corresponding certificates will be removed. Otherwise, the argument list will be interpreted as a list of paths to public key files to specify keys and certificates to be removed from the agent. If no public key is found at a given path, .Nm will append .Pa .pub and retry. If the argument list consists of .Dq - then .Nm will read public keys to be removed from standard input. .It Fl E Ar fingerprint_hash Specifies the hash algorithm used when displaying key fingerprints. Valid options are: .Dq md5 and .Dq sha256 . The default is .Dq sha256 . .It Fl e Ar pkcs11 Remove keys provided by the PKCS#11 shared library .Ar pkcs11 . .It Fl H Ar hostkey_file Specifies a known hosts file to look up hostkeys when using destination-constrained keys via the .Fl h flag. This option may be specified multiple times to allow multiple files to be searched. If no files are specified, .Nm will use the default .Xr ssh_config 5 known hosts files: .Pa ~/.ssh/known_hosts , .Pa ~/.ssh/known_hosts2 , .Pa /etc/ssh/ssh_known_hosts , and .Pa /etc/ssh/ssh_known_hosts2 . .It Fl h Ar destination_constraint When adding keys, constrain them to be usable only through specific hosts or to specific destinations. .Pp Destination constraints of the form .Sq [user@]dest-hostname permit use of the key only from the origin host (the one running .Xr ssh-agent 1 ) to the listed destination host, with optional user name. .Pp Constraints of the form .Sq src-hostname>[user@]dst-hostname allow a key available on a forwarded .Xr ssh-agent 1 to be used through a particular host (as specified by .Sq src-hostname ) to authenticate to a further host, specified by .Sq dst-hostname . .Pp Multiple destination constraints may be added when loading keys. When attempting authentication with a key that has destination constraints, the whole connection path, including .Xr ssh-agent 1 forwarding, is tested against those constraints and each hop must be permitted for the attempt to succeed. For example, if key is forwarded to a remote host, .Sq host-b , and is attempting authentication to another host, .Sq host-c , then the operation will be successful only if .Sq host-b was permitted from the origin host and the subsequent .Sq host-b>host-c hop is also permitted by destination constraints. .Pp Hosts are identified by their host keys, and are looked up from known hosts files by .Nm . Wildcards patterns may be used for hostnames and certificate host keys are supported. By default, keys added by .Nm are not destination constrained. .Pp Destination constraints were added in OpenSSH release 8.9. Support in both the remote SSH client and server is required when using destination-constrained keys over a forwarded .Xr ssh-agent 1 channel. .Pp It is also important to note that destination constraints can only be enforced by .Xr ssh-agent 1 when a key is used, or when it is forwarded by a .Sy cooperating .Xr ssh 1 . Specifically, it does not prevent an attacker with access to a remote .Ev SSH_AUTH_SOCK from forwarding it again and using it on a different host (but only to a permitted destination). .It Fl K Load resident keys from a FIDO authenticator. .It Fl k When loading keys into or deleting keys from the agent, process plain private keys only and skip certificates. .It Fl L Lists public key parameters of all identities currently represented by the agent. .It Fl l Lists fingerprints of all identities currently represented by the agent. .It Fl q Be quiet after a successful operation. .It Fl S Ar provider Specifies a path to a library that will be used when adding FIDO authenticator-hosted keys, overriding the default of using the internal USB HID support. .It Fl s Ar pkcs11 Add keys provided by the PKCS#11 shared library .Ar pkcs11 . Certificate files may optionally be listed as command-line arguments. If these are present, then they will be loaded into the agent using any corresponding private keys loaded from the PKCS#11 token. .It Fl T Ar pubkey ... Tests whether the private keys that correspond to the specified .Ar pubkey files are usable by performing sign and verify operations on each. .It Fl t Ar life Set a maximum lifetime when adding identities to an agent. The lifetime may be specified in seconds or in a time format specified in .Xr sshd_config 5 . .It Fl v Verbose mode. Causes .Nm to print debugging messages about its progress. This is helpful in debugging problems. Multiple .Fl v options increase the verbosity. The maximum is 3. .It Fl X Unlock the agent. .It Fl x Lock the agent with a password. .El .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev "DISPLAY", "SSH_ASKPASS" and "SSH_ASKPASS_REQUIRE" If .Nm needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If .Nm does not have a terminal associated with it but .Ev DISPLAY and .Ev SSH_ASKPASS are set, it will execute the program specified by .Ev SSH_ASKPASS (by default .Dq ssh-askpass ) and open an X11 window to read the passphrase. This is particularly useful when calling .Nm from a .Pa .xsession or related script. .Pp .Ev SSH_ASKPASS_REQUIRE allows further control over the use of an askpass program. If this variable is set to .Dq never then .Nm will never attempt to use one. If it is set to .Dq prefer , then .Nm will prefer to use the askpass program instead of the TTY when requesting passwords. Finally, if the variable is set to .Dq force , then the askpass program will be used for all passphrase input regardless of whether .Ev DISPLAY is set. .It Ev SSH_AUTH_SOCK Identifies the path of a .Ux Ns -domain socket used to communicate with the agent. .It Ev SSH_SK_PROVIDER Specifies a path to a library that will be used when loading any FIDO authenticator-hosted keys, overriding the default of using the built-in USB HID support. .El .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.ssh/id_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 ECDSA, authenticator-hosted ECDSA, Ed25519, authenticator-hosted Ed25519 or RSA authentication identity of the user. .El .Pp Identity files should not be readable by anyone but the user. Note that .Nm ignores identity files if they are accessible by others. .Sh EXIT STATUS Exit status is 0 on success, 1 if the specified command fails, and 2 if .Nm is unable to contact the authentication agent. .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-agent 1 , .Xr ssh-askpass 1 , .Xr ssh-keygen 1 , .Xr sshd 8 .Sh AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song removed many bugs, re-added newer features and created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. openssh-10.0p1/PaxHeaders.10889/ssh-add.c100644 001750 001750 0000000003414775415623 0014641xustar0028 atime=1744182234.8240475 openssh-10.0p1/ssh-add.c010064400017500001750000000657441477541562300132460ustar00djmdjm/* $OpenBSD: ssh-add.c,v 1.173 2024/09/06 02:30:44 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Adds an identity to the authentication server, or removes an identity. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation, * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef WITH_OPENSSL # include # include "openbsd-compat/openssl-compat.h" #endif #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "ssh.h" #include "log.h" #include "sshkey.h" #include "sshbuf.h" #include "authfd.h" #include "authfile.h" #include "pathnames.h" #include "misc.h" #include "ssherr.h" #include "digest.h" #include "ssh-sk.h" #include "sk-api.h" #include "hostfile.h" /* argv0 */ extern char *__progname; /* Default files to add */ static char *default_files[] = { #ifdef WITH_OPENSSL _PATH_SSH_CLIENT_ID_RSA, #ifdef OPENSSL_HAS_ECC _PATH_SSH_CLIENT_ID_ECDSA, _PATH_SSH_CLIENT_ID_ECDSA_SK, #endif #endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, _PATH_SSH_CLIENT_ID_ED25519_SK, _PATH_SSH_CLIENT_ID_XMSS, #ifdef WITH_DSA _PATH_SSH_CLIENT_ID_DSA, #endif NULL }; static int fingerprint_hash = SSH_FP_HASH_DEFAULT; /* Default lifetime (0 == forever) */ static int lifetime = 0; /* User has to confirm key use */ static int confirm = 0; /* Maximum number of signatures (XMSS) */ static u_int maxsign = 0; static u_int minleft = 0; /* we keep a cache of one passphrase */ static char *pass = NULL; static void clear_pass(void) { if (pass) { freezero(pass, strlen(pass)); pass = NULL; } } static int delete_one(int agent_fd, const struct sshkey *key, const char *comment, const char *path, int qflag) { int r; if ((r = ssh_remove_identity(agent_fd, key)) != 0) { fprintf(stderr, "Could not remove identity \"%s\": %s\n", path, ssh_err(r)); return r; } if (!qflag) { fprintf(stderr, "Identity removed: %s %s (%s)\n", path, sshkey_type(key), comment ? comment : "no comment"); } return 0; } static int delete_stdin(int agent_fd, int qflag, int key_only, int cert_only) { char *line = NULL, *cp; size_t linesize = 0; struct sshkey *key = NULL; int lnum = 0, r, ret = -1; while (getline(&line, &linesize, stdin) != -1) { lnum++; sshkey_free(key); key = NULL; line[strcspn(line, "\n")] = '\0'; cp = line + strspn(line, " \t"); if (*cp == '#' || *cp == '\0') continue; if ((key = sshkey_new(KEY_UNSPEC)) == NULL) fatal_f("sshkey_new"); if ((r = sshkey_read(key, &cp)) != 0) { error_r(r, "(stdin):%d: invalid key", lnum); continue; } if ((!key_only && !cert_only) || (key_only && !sshkey_is_cert(key)) || (cert_only && sshkey_is_cert(key))) { if (delete_one(agent_fd, key, cp, "(stdin)", qflag) == 0) ret = 0; } } sshkey_free(key); free(line); return ret; } static int delete_file(int agent_fd, const char *filename, int key_only, int cert_only, int qflag) { struct sshkey *public, *cert = NULL; char *certpath = NULL, *comment = NULL; int r, ret = -1; if (strcmp(filename, "-") == 0) return delete_stdin(agent_fd, qflag, key_only, cert_only); if ((r = sshkey_load_public(filename, &public, &comment)) != 0) { printf("Bad key file %s: %s\n", filename, ssh_err(r)); return -1; } if ((!key_only && !cert_only) || (key_only && !sshkey_is_cert(public)) || (cert_only && sshkey_is_cert(public))) { if (delete_one(agent_fd, public, comment, filename, qflag) == 0) ret = 0; } if (key_only) goto out; /* Now try to delete the corresponding certificate too */ free(comment); comment = NULL; xasprintf(&certpath, "%s-cert.pub", filename); if ((r = sshkey_load_public(certpath, &cert, &comment)) != 0) { if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT) error_r(r, "Failed to load certificate \"%s\"", certpath); goto out; } if (!sshkey_equal_public(cert, public)) fatal("Certificate %s does not match private key %s", certpath, filename); if (delete_one(agent_fd, cert, comment, certpath, qflag) == 0) ret = 0; out: sshkey_free(cert); sshkey_free(public); free(certpath); free(comment); return ret; } /* Send a request to remove all identities. */ static int delete_all(int agent_fd, int qflag) { int ret = -1; /* * Since the agent might be forwarded, old or non-OpenSSH, when asked * to remove all keys, attempt to remove both protocol v.1 and v.2 * keys. */ if (ssh_remove_all_identities(agent_fd, 2) == 0) ret = 0; /* ignore error-code for ssh1 */ ssh_remove_all_identities(agent_fd, 1); if (ret != 0) fprintf(stderr, "Failed to remove all identities.\n"); else if (!qflag) fprintf(stderr, "All identities removed.\n"); return ret; } static int add_file(int agent_fd, const char *filename, int key_only, int cert_only, int qflag, const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { struct sshkey *private, *cert; char *comment = NULL; char msg[1024], *certpath = NULL; int r, fd, ret = -1; size_t i; u_int32_t left; struct sshbuf *keyblob; struct ssh_identitylist *idlist; if (strcmp(filename, "-") == 0) { fd = STDIN_FILENO; filename = "(stdin)"; } else if ((fd = open(filename, O_RDONLY)) == -1) { perror(filename); return -1; } /* * Since we'll try to load a keyfile multiple times, permission errors * will occur multiple times, so check perms first and bail if wrong. */ if (fd != STDIN_FILENO) { if (sshkey_perm_ok(fd, filename) != 0) { close(fd); return -1; } } if ((r = sshbuf_load_fd(fd, &keyblob)) != 0) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); sshbuf_free(keyblob); close(fd); return -1; } close(fd); /* At first, try empty passphrase */ if ((r = sshkey_parse_private_fileblob(keyblob, "", &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); goto fail_load; } /* try last */ if (private == NULL && pass != NULL) { if ((r = sshkey_parse_private_fileblob(keyblob, pass, &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); goto fail_load; } } if (private == NULL) { /* clear passphrase since it did not work */ clear_pass(); snprintf(msg, sizeof msg, "Enter passphrase for %s%s: ", filename, confirm ? " (will confirm each use)" : ""); for (;;) { pass = read_passphrase(msg, RP_ALLOW_STDIN); if (strcmp(pass, "") == 0) goto fail_load; if ((r = sshkey_parse_private_fileblob(keyblob, pass, &private, &comment)) == 0) break; else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); fail_load: clear_pass(); sshbuf_free(keyblob); return -1; } clear_pass(); snprintf(msg, sizeof msg, "Bad passphrase, try again for %s%s: ", filename, confirm ? " (will confirm each use)" : ""); } } if (comment == NULL || *comment == '\0') comment = xstrdup(filename); sshbuf_free(keyblob); /* For XMSS */ if ((r = sshkey_set_filename(private, filename)) != 0) { fprintf(stderr, "Could not add filename to private key: %s (%s)\n", filename, comment); goto out; } if (maxsign && minleft && (r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) { for (i = 0; i < idlist->nkeys; i++) { if (!sshkey_equal_public(idlist->keys[i], private)) continue; left = sshkey_signatures_left(idlist->keys[i]); if (left < minleft) { fprintf(stderr, "Only %d signatures left.\n", left); break; } fprintf(stderr, "Skipping update: "); if (left == minleft) { fprintf(stderr, "required signatures left (%d).\n", left); } else { fprintf(stderr, "more signatures left (%d) than" " required (%d).\n", left, minleft); } ssh_free_identitylist(idlist); goto out; } ssh_free_identitylist(idlist); } if (sshkey_is_sk(private)) { if (skprovider == NULL) { fprintf(stderr, "Cannot load FIDO key %s " "without provider\n", filename); goto out; } } else { /* Don't send provider constraint for other keys */ skprovider = NULL; } if (!cert_only && (r = ssh_add_identity_constrained(agent_fd, private, comment, lifetime, confirm, maxsign, skprovider, dest_constraints, ndest_constraints)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); if (lifetime != 0) { fprintf(stderr, "Lifetime set to %d seconds\n", lifetime); } if (confirm != 0) { fprintf(stderr, "The user must confirm " "each use of the key\n"); } } } else { fprintf(stderr, "Could not add identity \"%s\": %s\n", filename, ssh_err(r)); } /* Skip trying to load the cert if requested */ if (key_only) goto out; /* Now try to add the certificate flavour too */ xasprintf(&certpath, "%s-cert.pub", filename); if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) { if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT) error_r(r, "Failed to load certificate \"%s\"", certpath); goto out; } if (!sshkey_equal_public(cert, private)) { error("Certificate %s does not match private key %s", certpath, filename); sshkey_free(cert); goto out; } /* Graft with private bits */ if ((r = sshkey_to_certified(private)) != 0) { error_fr(r, "sshkey_to_certified"); sshkey_free(cert); goto out; } if ((r = sshkey_cert_copy(cert, private)) != 0) { error_fr(r, "sshkey_cert_copy"); sshkey_free(cert); goto out; } sshkey_free(cert); if ((r = ssh_add_identity_constrained(agent_fd, private, comment, lifetime, confirm, maxsign, skprovider, dest_constraints, ndest_constraints)) != 0) { error_r(r, "Certificate %s (%s) add failed", certpath, private->cert->key_id); goto out; } /* success */ if (!qflag) { fprintf(stderr, "Certificate added: %s (%s)\n", certpath, private->cert->key_id); if (lifetime != 0) { fprintf(stderr, "Lifetime set to %d seconds\n", lifetime); } if (confirm != 0) { fprintf(stderr, "The user must confirm each use " "of the key\n"); } } out: free(certpath); free(comment); sshkey_free(private); return ret; } static int update_card(int agent_fd, int add, const char *id, int qflag, int key_only, int cert_only, struct dest_constraint **dest_constraints, size_t ndest_constraints, struct sshkey **certs, size_t ncerts) { char *pin = NULL; int r, ret = -1; if (key_only) ncerts = 0; if (add) { if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; } if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin, lifetime, confirm, dest_constraints, ndest_constraints, cert_only, certs, ncerts)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Card %s: %s\n", add ? "added" : "removed", id); } } else { fprintf(stderr, "Could not %s card \"%s\": %s\n", add ? "add" : "remove", id, ssh_err(r)); ret = -1; } free(pin); return ret; } static int test_key(int agent_fd, const char *filename) { struct sshkey *key = NULL; u_char *sig = NULL; const char *alg = NULL; size_t slen = 0; int r, ret = -1; char data[1024]; if ((r = sshkey_load_public(filename, &key, NULL)) != 0) { error_r(r, "Couldn't read public key %s", filename); return -1; } if (sshkey_type_plain(key->type) == KEY_RSA) alg = "rsa-sha2-256"; arc4random_buf(data, sizeof(data)); if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data), alg, 0)) != 0) { error_r(r, "Agent signature failed for %s", filename); goto done; } if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), alg, 0, NULL)) != 0) { error_r(r, "Signature verification failed for %s", filename); goto done; } /* success */ ret = 0; done: free(sig); sshkey_free(key); return ret; } static int list_identities(int agent_fd, int do_fp) { char *fp; int r; struct ssh_identitylist *idlist; u_int32_t left; size_t i; if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { if (r != SSH_ERR_AGENT_NO_IDENTITIES) fprintf(stderr, "error fetching identities: %s\n", ssh_err(r)); else printf("The agent has no identities.\n"); return -1; } for (i = 0; i < idlist->nkeys; i++) { if (do_fp) { fp = sshkey_fingerprint(idlist->keys[i], fingerprint_hash, SSH_FP_DEFAULT); printf("%u %s %s (%s)\n", sshkey_size(idlist->keys[i]), fp == NULL ? "(null)" : fp, idlist->comments[i], sshkey_type(idlist->keys[i])); free(fp); } else { if ((r = sshkey_write(idlist->keys[i], stdout)) != 0) { fprintf(stderr, "sshkey_write: %s\n", ssh_err(r)); continue; } fprintf(stdout, " %s", idlist->comments[i]); left = sshkey_signatures_left(idlist->keys[i]); if (left > 0) fprintf(stdout, " [signatures left %d]", left); fprintf(stdout, "\n"); } } ssh_free_identitylist(idlist); return 0; } static int lock_agent(int agent_fd, int lock) { char prompt[100], *p1, *p2; int r, passok = 1, ret = -1; strlcpy(prompt, "Enter lock password: ", sizeof(prompt)); p1 = read_passphrase(prompt, RP_ALLOW_STDIN); if (lock) { strlcpy(prompt, "Again: ", sizeof prompt); p2 = read_passphrase(prompt, RP_ALLOW_STDIN); if (strcmp(p1, p2) != 0) { fprintf(stderr, "Passwords do not match.\n"); passok = 0; } freezero(p2, strlen(p2)); } if (passok) { if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) { fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un"); ret = 0; } else { fprintf(stderr, "Failed to %slock agent: %s\n", lock ? "" : "un", ssh_err(r)); } } freezero(p1, strlen(p1)); return (ret); } static int load_resident_keys(int agent_fd, const char *skprovider, int qflag, struct dest_constraint **dest_constraints, size_t ndest_constraints) { struct sshsk_resident_key **srks; size_t nsrks, i; struct sshkey *key; int r, ok = 0; char *fp; pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); if ((r = sshsk_load_resident(skprovider, NULL, pass, 0, &srks, &nsrks)) != 0) { error_r(r, "Unable to load resident keys"); return r; } for (i = 0; i < nsrks; i++) { key = srks[i]->key; if ((fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); if ((r = ssh_add_identity_constrained(agent_fd, key, "", lifetime, confirm, maxsign, skprovider, dest_constraints, ndest_constraints)) != 0) { error("Unable to add key %s %s", sshkey_type(key), fp); free(fp); ok = r; continue; } if (ok == 0) ok = 1; if (!qflag) { fprintf(stderr, "Resident identity added: %s %s\n", sshkey_type(key), fp); if (lifetime != 0) { fprintf(stderr, "Lifetime set to %d seconds\n", lifetime); } if (confirm != 0) { fprintf(stderr, "The user must confirm " "each use of the key\n"); } } free(fp); } sshsk_free_resident_keys(srks, nsrks); if (nsrks == 0) return SSH_ERR_KEY_NOT_FOUND; return ok == 1 ? 0 : ok; } static int do_file(int agent_fd, int deleting, int key_only, int cert_only, char *file, int qflag, const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { if (deleting) { if (delete_file(agent_fd, file, key_only, cert_only, qflag) == -1) return -1; } else { if (add_file(agent_fd, file, key_only, cert_only, qflag, skprovider, dest_constraints, ndest_constraints) == -1) return -1; } return 0; } /* Append string 's' to a NULL-terminated array of strings */ static void stringlist_append(char ***listp, const char *s) { size_t i = 0; if (*listp == NULL) *listp = xcalloc(2, sizeof(**listp)); else { for (i = 0; (*listp)[i] != NULL; i++) ; /* count */ *listp = xrecallocarray(*listp, i + 1, i + 2, sizeof(**listp)); } (*listp)[i] = xstrdup(s); } static void parse_dest_constraint_hop(const char *s, struct dest_constraint_hop *dch, char **hostkey_files) { char *user = NULL, *host, *os, *path; size_t i; struct hostkeys *hostkeys; const struct hostkey_entry *hke; int r, want_ca; memset(dch, '\0', sizeof(*dch)); os = xstrdup(s); if ((host = strrchr(os, '@')) == NULL) host = os; else { *host++ = '\0'; user = os; } cleanhostname(host); /* Trivial case: username@ (all hosts) */ if (*host == '\0') { if (user == NULL) { fatal("Invalid key destination constraint \"%s\": " "does not specify user or host", s); } dch->user = xstrdup(user); /* other fields left blank */ free(os); return; } if (hostkey_files == NULL) fatal_f("no hostkey files"); /* Otherwise we need to look up the keys for this hostname */ hostkeys = init_hostkeys(); for (i = 0; hostkey_files[i]; i++) { path = tilde_expand_filename(hostkey_files[i], getuid()); debug2_f("looking up host keys for \"%s\" in %s", host, path); load_hostkeys(hostkeys, host, path, 0); free(path); } dch->user = user == NULL ? NULL : xstrdup(user); dch->hostname = xstrdup(host); for (i = 0; i < hostkeys->num_entries; i++) { hke = hostkeys->entries + i; want_ca = hke->marker == MRK_CA; if (hke->marker != MRK_NONE && !want_ca) continue; debug3_f("%s%s%s: adding %s %skey from %s:%lu as key %u", user == NULL ? "": user, user == NULL ? "" : "@", host, sshkey_type(hke->key), want_ca ? "CA " : "", hke->file, hke->line, dch->nkeys); dch->keys = xrecallocarray(dch->keys, dch->nkeys, dch->nkeys + 1, sizeof(*dch->keys)); dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys, dch->nkeys + 1, sizeof(*dch->key_is_ca)); if ((r = sshkey_from_private(hke->key, &(dch->keys[dch->nkeys]))) != 0) fatal_fr(r, "sshkey_from_private"); dch->key_is_ca[dch->nkeys] = want_ca; dch->nkeys++; } if (dch->nkeys == 0) fatal("No host keys found for destination \"%s\"", host); free_hostkeys(hostkeys); free(os); return; } static void parse_dest_constraint(const char *s, struct dest_constraint ***dcp, size_t *ndcp, char **hostkey_files) { struct dest_constraint *dc; char *os, *cp; dc = xcalloc(1, sizeof(*dc)); os = xstrdup(s); if ((cp = strchr(os, '>')) == NULL) { /* initial hop; no 'from' hop specified */ parse_dest_constraint_hop(os, &dc->to, hostkey_files); } else { /* two hops specified */ *(cp++) = '\0'; parse_dest_constraint_hop(os, &dc->from, hostkey_files); parse_dest_constraint_hop(cp, &dc->to, hostkey_files); if (dc->from.user != NULL) { fatal("Invalid key constraint %s: cannot specify " "user on 'from' host", os); } } /* XXX eliminate or error on duplicates */ debug2_f("constraint %zu: %s%s%s (%u keys) > %s%s%s (%u keys)", *ndcp, dc->from.user ? dc->from.user : "", dc->from.user ? "@" : "", dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys, dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "", dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys); *dcp = xrecallocarray(*dcp, *ndcp, *ndcp + 1, sizeof(**dcp)); (*dcp)[(*ndcp)++] = dc; free(os); } static void usage(void) { fprintf(stderr, "usage: ssh-add [-CcDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file]\n" " [-h destination_constraint] [-S provider] [-t life]\n" #ifdef WITH_XMSS " [-M maxsign] [-m minleft]\n" #endif " [file ...]\n" " ssh-add -s pkcs11 [-Cv] [certificate ...]\n" " ssh-add -e pkcs11\n" " ssh-add -T pubkey ...\n" ); } int main(int argc, char **argv) { extern char *optarg; extern int optind; int agent_fd; char *pkcs11provider = NULL, *skprovider = NULL; char **dest_constraint_strings = NULL, **hostkey_files = NULL; int r, i, ch, deleting = 0, ret = 0, key_only = 0, cert_only = 0; int do_download = 0, xflag = 0, lflag = 0, Dflag = 0; int qflag = 0, Tflag = 0; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; LogLevel log_level = SYSLOG_LEVEL_INFO; struct sshkey *k, **certs = NULL; struct dest_constraint **dest_constraints = NULL; size_t ndest_constraints = 0, ncerts = 0; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); __progname = ssh_get_progname(argv[0]); seed_rng(); log_init(__progname, log_level, log_facility, 1); setvbuf(stdout, NULL, _IOLBF, 0); /* First, get a connection to the authentication agent. */ switch (r = ssh_get_authentication_socket(&agent_fd)) { case 0: break; case SSH_ERR_AGENT_NOT_PRESENT: fprintf(stderr, "Could not open a connection to your " "authentication agent.\n"); exit(2); default: fprintf(stderr, "Error connecting to agent: %s\n", ssh_err(r)); exit(2); } skprovider = getenv("SSH_SK_PROVIDER"); while ((ch = getopt(argc, argv, "vkKlLCcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) { switch (ch) { case 'v': if (log_level == SYSLOG_LEVEL_INFO) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; break; case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); if (fingerprint_hash == -1) fatal("Invalid hash algorithm \"%s\"", optarg); break; case 'H': stringlist_append(&hostkey_files, optarg); break; case 'h': stringlist_append(&dest_constraint_strings, optarg); break; case 'k': key_only = 1; break; case 'C': cert_only = 1; break; case 'K': do_download = 1; break; case 'l': case 'L': if (lflag != 0) fatal("-%c flag already specified", lflag); lflag = ch; break; case 'x': case 'X': if (xflag != 0) fatal("-%c flag already specified", xflag); xflag = ch; break; case 'c': confirm = 1; break; case 'm': minleft = (u_int)strtonum(optarg, 1, UINT_MAX, NULL); if (minleft == 0) { usage(); ret = 1; goto done; } break; case 'M': maxsign = (u_int)strtonum(optarg, 1, UINT_MAX, NULL); if (maxsign == 0) { usage(); ret = 1; goto done; } break; case 'd': deleting = 1; break; case 'D': Dflag = 1; break; case 's': pkcs11provider = optarg; break; case 'S': skprovider = optarg; break; case 'e': deleting = 1; pkcs11provider = optarg; break; case 't': if ((lifetime = convtime(optarg)) == -1 || lifetime < 0 || (u_long)lifetime > UINT32_MAX) { fprintf(stderr, "Invalid lifetime\n"); ret = 1; goto done; } break; case 'q': qflag = 1; break; case 'T': Tflag = 1; break; default: usage(); ret = 1; goto done; } } log_init(__progname, log_level, log_facility, 1); if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1) fatal("Invalid combination of actions"); else if (xflag) { if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1) ret = 1; goto done; } else if (lflag) { if (list_identities(agent_fd, lflag == 'l' ? 1 : 0) == -1) ret = 1; goto done; } else if (Dflag) { if (delete_all(agent_fd, qflag) == -1) ret = 1; goto done; } #ifdef ENABLE_SK_INTERNAL if (skprovider == NULL) skprovider = "internal"; #endif if (hostkey_files == NULL) { /* use defaults from readconf.c */ stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE); stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE2); stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE); stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE2); } if (dest_constraint_strings != NULL) { for (i = 0; dest_constraint_strings[i] != NULL; i++) { parse_dest_constraint(dest_constraint_strings[i], &dest_constraints, &ndest_constraints, hostkey_files); } } argc -= optind; argv += optind; if (Tflag) { if (argc <= 0) fatal("no keys to test"); for (r = i = 0; i < argc; i++) r |= test_key(agent_fd, argv[i]); ret = r == 0 ? 0 : 1; goto done; } if (pkcs11provider != NULL) { for (i = 0; i < argc; i++) { if ((r = sshkey_load_public(argv[i], &k, NULL)) != 0) fatal_fr(r, "load certificate %s", argv[i]); certs = xrecallocarray(certs, ncerts, ncerts + 1, sizeof(*certs)); debug2("%s: %s", argv[i], sshkey_ssh_name(k)); certs[ncerts++] = k; } debug2_f("loaded %zu certificates", ncerts); if (update_card(agent_fd, !deleting, pkcs11provider, qflag, key_only, cert_only, dest_constraints, ndest_constraints, certs, ncerts) == -1) ret = 1; goto done; } if (do_download) { if (skprovider == NULL) fatal("Cannot download keys without provider"); if (load_resident_keys(agent_fd, skprovider, qflag, dest_constraints, ndest_constraints) != 0) ret = 1; goto done; } if (argc == 0) { char buf[PATH_MAX]; struct passwd *pw; struct stat st; int count = 0; if ((pw = getpwuid(getuid())) == NULL) { fprintf(stderr, "No user found with uid %u\n", (u_int)getuid()); ret = 1; goto done; } for (i = 0; default_files[i]; i++) { snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, default_files[i]); if (stat(buf, &st) == -1) continue; if (do_file(agent_fd, deleting, key_only, cert_only, buf, qflag, skprovider, dest_constraints, ndest_constraints) == -1) ret = 1; else count++; } if (count == 0) ret = 1; } else { for (i = 0; i < argc; i++) { if (do_file(agent_fd, deleting, key_only, cert_only, argv[i], qflag, skprovider, dest_constraints, ndest_constraints) == -1) ret = 1; } } done: clear_pass(); ssh_close_authentication_socket(agent_fd); return ret; } openssh-10.0p1/PaxHeaders.10889/ssh-agent.0100644 001750 001750 0000000003614775415623 0015126xustar0030 atime=1744182234.825024979 openssh-10.0p1/ssh-agent.0010064400017500001750000000177211477541562300135210ustar00djmdjmSSH-AGENT(1) General Commands Manual SSH-AGENT(1) NAME ssh-agent M-bM-^@M-^S OpenSSH authentication agent SYNOPSIS ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash] [-O option] [-P allowed_providers] [-t life] ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option] [-P allowed_providers] [-t life] command [arg ...] ssh-agent [-c | -s] -k DESCRIPTION ssh-agent 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 ssh(1). 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.. -c Generate C-shell commands on standard output. This is the default if SHELL looks like it's a csh style of shell. -D Foreground mode. When this option is specified, ssh-agent will not fork. -d Debug mode. When this option is specified, ssh-agent will not fork and will write debug information to standard error. -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). -O option Specify an option when starting ssh-agent. The supported options are: allow-remote-pkcs11, no-restrict-websafe and websafe-allow. The allow-remote-pkcs11 option allows clients of a forwarded ssh-agent to load PKCS#11 or FIDO provider libraries. By default only local clients may perform this operation. Note that signalling that an ssh-agent client is remote is performed by ssh(1), and use of other tools to forward access to the agent socket may circumvent this restriction. The no-restrict-websafe option instructs ssh-agent to permit signatures using FIDO keys that might be web authentication requests. By default, ssh-agent refuses signature requests for FIDO keys where the key application string does not start with M-bM-^@M-^\ssh:M-bM-^@M-^] and when the data to be signed does not appear to be a ssh(1) user authentication request or a ssh-keygen(1) signature. The default behaviour prevents forwarded access to a FIDO key from also implicitly forwarding the ability to authenticate to websites. Alternately the websafe-allow option allows specifying a pattern- list of key application strings to replace the default application allow-list, for example: M-bM-^@M-^\websafe-allow=ssh:*,example.org,*.example.comM-bM-^@M-^] See PATTERNS in ssh_config(5) for a description of pattern-list syntax. -P allowed_providers Specify a pattern-list of acceptable paths for PKCS#11 provider and FIDO authenticator middleware shared libraries that may be used with the -S or -s options to ssh-add(1). Libraries that do not match the pattern list will be refused. The default list is M-bM-^@M-^\usr/lib*/*,/usr/local/lib*/*M-bM-^@M-^]. See PATTERNS in ssh_config(5) for a description of pattern-list syntax. -s Generate Bourne shell commands on standard output. This is the default if SHELL does not look like it's a csh style of shell. -t 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. command [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. There are three 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 ssh-agent program. The agent starts a command under which its environment variables are exported, for example ssh-agent xterm &. When the command terminates, so does the agent. The second method is used for a login session. When ssh-agent 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 eval `ssh-agent -s`. In both of these cases, ssh(1) looks at these environment variables and uses them to establish a connection to the agent. The third way to run ssh-agent is via socket activation from a supervising process, such as systemd. In this mode, the supervising process creates the listening socket and is responsible for starting ssh-agent as needed, and also for communicating the location of the socket listener to other programs in the user's session. Socket activation is used when ssh-agent is started with either of the -d or -D flags, no socket listening address specified by the -a flag, and both the LISTEN_FDS and LISTEN_PID environment variables correctly supplied by the supervising process. The agent initially does not have any private keys. Keys are added using ssh-add(1) or by ssh(1) when AddKeysToAgent is set in ssh_config(5). 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. Connections to ssh-agent may be forwarded from further remote hosts using the -A option to 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. ssh-agent will delete all keys it has loaded upon receiving SIGUSR1. ENVIRONMENT SSH_AGENT_PID When ssh-agent starts, it stores the name of the agent's process ID (PID) in this variable. SSH_AUTH_SOCK When ssh-agent starts, it creates a UNIX-domain socket and stores its pathname in this variable. It is accessible only to the current user, but is easily abused by root or another instance of the same user. FILES $TMPDIR/ssh-XXXXXXXXXX/agent. 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), ssh_config(5), 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 7.6 February 9, 2025 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh-agent.1100644 001750 001750 0000000003614775415623 0015127xustar0030 atime=1744182234.825024979 openssh-10.0p1/ssh-agent.1010064400017500001750000000220501477541562300135110ustar00djmdjm.\" $OpenBSD: ssh-agent.1,v 1.82 2025/02/09 18:24:08 schwarze Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .Dd $Mdocdate: February 9 2025 $ .Dt SSH-AGENT 1 .Os .Sh NAME .Nm ssh-agent .Nd OpenSSH authentication agent .Sh SYNOPSIS .Nm ssh-agent .Op Fl c | s .Op Fl \&Dd .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash .Op Fl O Ar option .Op Fl P Ar allowed_providers .Op Fl t Ar life .Nm ssh-agent .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash .Op Fl O Ar option .Op Fl P Ar allowed_providers .Op Fl t Ar life .Ar command Op Ar arg ... .Nm ssh-agent .Op Fl c | s .Fl k .Sh DESCRIPTION .Nm is a program to hold private keys used for public key authentication. 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 options are as follows: .Bl -tag -width Ds .It Fl a Ar bind_address Bind the agent to the .Ux Ns -domain socket .Ar bind_address . The default is .Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt . .It Fl c Generate C-shell commands on standard output. 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 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: .Dq md5 and .Dq sha256 . The default is .Dq sha256 . .It Fl k Kill the current agent (given by the .Ev SSH_AGENT_PID environment variable). .It Fl O Ar option Specify an option when starting .Nm . The supported options are: .Cm allow-remote-pkcs11 , .Cm no-restrict-websafe and .Cm websafe-allow . .Pp The .Cm allow-remote-pkcs11 option allows clients of a forwarded .Nm to load PKCS#11 or FIDO provider libraries. By default only local clients may perform this operation. Note that signalling that an .Nm client is remote is performed by .Xr ssh 1 , and use of other tools to forward access to the agent socket may circumvent this restriction. .Pp The .Cm no-restrict-websafe option instructs .Nm to permit signatures using FIDO keys that might be web authentication requests. By default, .Nm refuses signature requests for FIDO keys where the key application string does not start with .Dq ssh: and when the data to be signed does not appear to be a .Xr ssh 1 user authentication request or a .Xr ssh-keygen 1 signature. The default behaviour prevents forwarded access to a FIDO key from also implicitly forwarding the ability to authenticate to websites. .Pp Alternately the .Cm websafe-allow option allows specifying a pattern-list of key application strings to replace the default application allow-list, for example: .Dq websafe-allow=ssh:*,example.org,*.example.com .Pp See PATTERNS in .Xr ssh_config 5 for a description of pattern-list syntax. .It Fl P Ar allowed_providers Specify a pattern-list of acceptable paths for PKCS#11 provider and FIDO authenticator middleware shared libraries that may be used with the .Fl S or .Fl s options to .Xr ssh-add 1 . Libraries that do not match the pattern list will be refused. The default list is .Dq usr/lib*/*,/usr/local/lib*/* . .Pp See PATTERNS in .Xr ssh_config 5 for a description of pattern-list syntax. .It Fl s Generate Bourne shell commands on standard output. This is the default if .Ev SHELL does not look like it's a csh style of shell. .It Fl t Ar life Set a default value for the maximum lifetime of identities added to the agent. The lifetime may be specified in seconds or in a time format specified in .Xr sshd_config 5 . 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 There are three main ways to get an agent set up. The first is at the start of an X session, where all other windows or programs are started as children of the .Nm program. The agent starts a command under which its environment variables are exported, for example .Cm ssh-agent xterm & . When the command terminates, so does the agent. .Pp The second method is used for a login session. When .Nm is started, it prints the shell commands required to set its environment variables, which in turn can be evaluated in the calling shell, for example .Cm eval `ssh-agent -s` . .Pp In both of these cases, .Xr ssh 1 looks at these environment variables and uses them to establish a connection to the agent. .Pp The third way to run .Nm is via socket activation from a supervising process, such as systemd. In this mode, the supervising process creates the listening socket and is responsible for starting .Nm as needed, and also for communicating the location of the socket listener to other programs in the user's session. Socket activation is used when .Nm is started with either of the .Fl d or .Fl D flags, no socket listening address specified by the .Fl a flag, and both the .Ev LISTEN_FDS and .Ev LISTEN_PID environment variables correctly supplied by the supervising process. .Pp The agent initially does not have any private keys. Keys are added using .Xr ssh-add 1 or by .Xr ssh 1 when .Cm AddKeysToAgent is set in .Xr ssh_config 5 . Multiple identities may be stored in .Nm concurrently and .Xr ssh 1 will automatically use them if present. .Xr ssh-add 1 is also used to remove keys from .Nm and to query the keys that are held in one. .Pp Connections to .Nm may be forwarded from further remote hosts using the .Fl A option to .Xr ssh 1 (but see the caveats documented therein), avoiding the need for authentication data to be stored on other machines. Authentication passphrases and private keys never go over the network: the connection to the agent is forwarded over SSH remote connections and the result is returned to the requester, allowing the user access to their identities anywhere in the network in a secure fashion. .Pp .Nm will delete all keys it has loaded upon receiving .Dv SIGUSR1 . .Sh ENVIRONMENT .Bl -tag -width "SSH_AGENT_PID" .It Ev SSH_AGENT_PID When .Nm starts, it stores the name of the agent's process ID (PID) in this variable. .It Ev SSH_AUTH_SOCK When .Nm starts, it creates a .Ux Ns -domain socket and stores its pathname in this variable. It is accessible only to the current user, but is easily abused by root or another instance of the same user. .El .Sh FILES .Bl -tag -width Ds .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent. .Ux Ns -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. .El .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-keygen 1 , .Xr ssh_config 5 , .Xr sshd 8 .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos , 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. openssh-10.0p1/PaxHeaders.10889/ssh-agent.c100644 001750 001750 0000000003614775415623 0015211xustar0030 atime=1744182234.829907675 openssh-10.0p1/ssh-agent.c010064400017500001750000002054261477541562300136050ustar00djmdjm/* $OpenBSD: ssh-agent.c,v 1.310 2025/02/18 08:02:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * The authentication agent program. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_UN_H # include #endif #include "openbsd-compat/sys-queue.h" #ifdef WITH_OPENSSL #include #include "openbsd-compat/openssl-compat.h" #endif #include #include #include #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_POLL_H # include #endif #include #include #include #include #include #include #include #ifdef HAVE_UTIL_H # include #endif #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshbuf.h" #include "sshkey.h" #include "authfd.h" #include "log.h" #include "misc.h" #include "digest.h" #include "ssherr.h" #include "match.h" #include "msg.h" #include "pathnames.h" #include "ssh-pkcs11.h" #include "sk-api.h" #include "myproposal.h" #ifndef DEFAULT_ALLOWED_PROVIDERS # define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*" #endif #ifndef DEFAULT_WEBSAFE_ALLOWLIST # define DEFAULT_WEBSAFE_ALLOWLIST "ssh:*" #endif /* Maximum accepted message length */ #define AGENT_MAX_LEN (256*1024) /* Maximum bytes to read from client socket */ #define AGENT_RBUF_LEN (4096) /* Maximum number of recorded session IDs/hostkeys per connection */ #define AGENT_MAX_SESSION_IDS 16 /* Maximum size of session ID */ #define AGENT_MAX_SID_LEN 128 /* Maximum number of destination constraints to accept on a key */ #define AGENT_MAX_DEST_CONSTRAINTS 1024 /* Maximum number of associated certificate constraints to accept on a key */ #define AGENT_MAX_EXT_CERTS 1024 /* XXX store hostkey_sid in a refcounted tree */ typedef enum { AUTH_UNUSED = 0, AUTH_SOCKET = 1, AUTH_CONNECTION = 2, } sock_type; struct hostkey_sid { struct sshkey *key; struct sshbuf *sid; int forwarded; }; typedef struct socket_entry { int fd; sock_type type; struct sshbuf *input; struct sshbuf *output; struct sshbuf *request; size_t nsession_ids; struct hostkey_sid *session_ids; int session_bind_attempted; } SocketEntry; u_int sockets_alloc = 0; SocketEntry *sockets = NULL; typedef struct identity { TAILQ_ENTRY(identity) next; struct sshkey *key; char *comment; char *provider; time_t death; u_int confirm; char *sk_provider; struct dest_constraint *dest_constraints; size_t ndest_constraints; } Identity; struct idtable { int nentries; TAILQ_HEAD(idqueue, identity) idlist; }; /* private key table */ struct idtable *idtab; int max_fd = 0; /* pid of shell == parent of agent */ pid_t parent_pid = -1; time_t parent_alive_interval = 0; static sig_atomic_t signalled_exit; static sig_atomic_t signalled_keydrop; /* pid of process for which cleanup_socket is applicable */ pid_t cleanup_pid = 0; /* pathname and directory for AUTH_SOCKET */ char socket_name[PATH_MAX]; char socket_dir[PATH_MAX]; /* Pattern-list of allowed PKCS#11/Security key paths */ static char *allowed_providers; /* * Allows PKCS11 providers or SK keys that use non-internal providers to * be added over a remote connection (identified by session-bind@openssh.com). */ static int remote_add_provider; /* locking */ #define LOCK_SIZE 32 #define LOCK_SALT_SIZE 16 #define LOCK_ROUNDS 1 int locked = 0; u_char lock_pwhash[LOCK_SIZE]; u_char lock_salt[LOCK_SALT_SIZE]; extern char *__progname; /* Default lifetime in seconds (0 == forever) */ static int lifetime = 0; static int fingerprint_hash = SSH_FP_HASH_DEFAULT; /* Refuse signing of non-SSH messages for web-origin FIDO keys */ static int restrict_websafe = 1; static char *websafe_allowlist; static void close_socket(SocketEntry *e) { size_t i; close(e->fd); sshbuf_free(e->input); sshbuf_free(e->output); sshbuf_free(e->request); for (i = 0; i < e->nsession_ids; i++) { sshkey_free(e->session_ids[i].key); sshbuf_free(e->session_ids[i].sid); } free(e->session_ids); memset(e, '\0', sizeof(*e)); e->fd = -1; e->type = AUTH_UNUSED; } static void idtab_init(void) { idtab = xcalloc(1, sizeof(*idtab)); TAILQ_INIT(&idtab->idlist); idtab->nentries = 0; } static void free_dest_constraint_hop(struct dest_constraint_hop *dch) { u_int i; if (dch == NULL) return; free(dch->user); free(dch->hostname); for (i = 0; i < dch->nkeys; i++) sshkey_free(dch->keys[i]); free(dch->keys); free(dch->key_is_ca); } static void free_dest_constraints(struct dest_constraint *dcs, size_t ndcs) { size_t i; for (i = 0; i < ndcs; i++) { free_dest_constraint_hop(&dcs[i].from); free_dest_constraint_hop(&dcs[i].to); } free(dcs); } #ifdef ENABLE_PKCS11 static void dup_dest_constraint_hop(const struct dest_constraint_hop *dch, struct dest_constraint_hop *out) { u_int i; int r; out->user = dch->user == NULL ? NULL : xstrdup(dch->user); out->hostname = dch->hostname == NULL ? NULL : xstrdup(dch->hostname); out->is_ca = dch->is_ca; out->nkeys = dch->nkeys; out->keys = out->nkeys == 0 ? NULL : xcalloc(out->nkeys, sizeof(*out->keys)); out->key_is_ca = out->nkeys == 0 ? NULL : xcalloc(out->nkeys, sizeof(*out->key_is_ca)); for (i = 0; i < dch->nkeys; i++) { if (dch->keys[i] != NULL && (r = sshkey_from_private(dch->keys[i], &(out->keys[i]))) != 0) fatal_fr(r, "copy key"); out->key_is_ca[i] = dch->key_is_ca[i]; } } static struct dest_constraint * dup_dest_constraints(const struct dest_constraint *dcs, size_t ndcs) { size_t i; struct dest_constraint *ret; if (ndcs == 0) return NULL; ret = xcalloc(ndcs, sizeof(*ret)); for (i = 0; i < ndcs; i++) { dup_dest_constraint_hop(&dcs[i].from, &ret[i].from); dup_dest_constraint_hop(&dcs[i].to, &ret[i].to); } return ret; } #endif /* ENABLE_PKCS11 */ #ifdef DEBUG_CONSTRAINTS static void dump_dest_constraint_hop(const struct dest_constraint_hop *dch) { u_int i; char *fp; debug_f("user %s hostname %s is_ca %d nkeys %u", dch->user == NULL ? "(null)" : dch->user, dch->hostname == NULL ? "(null)" : dch->hostname, dch->is_ca, dch->nkeys); for (i = 0; i < dch->nkeys; i++) { fp = NULL; if (dch->keys[i] != NULL && (fp = sshkey_fingerprint(dch->keys[i], SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug_f("key %u/%u: %s%s%s key_is_ca %d", i, dch->nkeys, dch->keys[i] == NULL ? "" : sshkey_ssh_name(dch->keys[i]), dch->keys[i] == NULL ? "" : " ", dch->keys[i] == NULL ? "none" : fp, dch->key_is_ca[i]); free(fp); } } #endif /* DEBUG_CONSTRAINTS */ static void dump_dest_constraints(const char *context, const struct dest_constraint *dcs, size_t ndcs) { #ifdef DEBUG_CONSTRAINTS size_t i; debug_f("%s: %zu constraints", context, ndcs); for (i = 0; i < ndcs; i++) { debug_f("constraint %zu / %zu: from: ", i, ndcs); dump_dest_constraint_hop(&dcs[i].from); debug_f("constraint %zu / %zu: to: ", i, ndcs); dump_dest_constraint_hop(&dcs[i].to); } debug_f("done for %s", context); #endif /* DEBUG_CONSTRAINTS */ } static void free_identity(Identity *id) { sshkey_free(id->key); free(id->provider); free(id->comment); free(id->sk_provider); free_dest_constraints(id->dest_constraints, id->ndest_constraints); free(id); } /* * Match 'key' against the key/CA list in a destination constraint hop * Returns 0 on success or -1 otherwise. */ static int match_key_hop(const char *tag, const struct sshkey *key, const struct dest_constraint_hop *dch) { const char *reason = NULL; const char *hostname = dch->hostname ? dch->hostname : "(ORIGIN)"; u_int i; char *fp; if (key == NULL) return -1; /* XXX logspam */ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail", tag, hostname, sshkey_type(key), fp, dch->nkeys); free(fp); for (i = 0; i < dch->nkeys; i++) { if (dch->keys[i] == NULL) return -1; /* XXX logspam */ if ((fp = sshkey_fingerprint(dch->keys[i], SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("%s: key %u: %s%s %s", tag, i, dch->key_is_ca[i] ? "CA " : "", sshkey_type(dch->keys[i]), fp); free(fp); if (!sshkey_is_cert(key)) { /* plain key */ if (dch->key_is_ca[i] || !sshkey_equal(key, dch->keys[i])) continue; return 0; } /* certificate */ if (!dch->key_is_ca[i]) continue; if (key->cert == NULL || key->cert->signature_key == NULL) return -1; /* shouldn't happen */ if (!sshkey_equal(key->cert->signature_key, dch->keys[i])) continue; if (sshkey_cert_check_host(key, hostname, 1, SSH_ALLOWED_CA_SIGALGS, &reason) != 0) { debug_f("cert %s / hostname %s rejected: %s", key->cert->key_id, hostname, reason); continue; } return 0; } return -1; } /* Check destination constraints on an identity against the hostkey/user */ static int permitted_by_dest_constraints(const struct sshkey *fromkey, const struct sshkey *tokey, Identity *id, const char *user, const char **hostnamep) { size_t i; struct dest_constraint *d; if (hostnamep != NULL) *hostnamep = NULL; for (i = 0; i < id->ndest_constraints; i++) { d = id->dest_constraints + i; /* XXX remove logspam */ debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)", i, d->from.user ? d->from.user : "", d->from.user ? "@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)", d->from.nkeys, d->to.user ? d->to.user : "", d->to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)", d->to.nkeys); /* Match 'from' key */ if (fromkey == NULL) { /* We are matching the first hop */ if (d->from.hostname != NULL || d->from.nkeys != 0) continue; } else if (match_key_hop("from", fromkey, &d->from) != 0) continue; /* Match 'to' key */ if (tokey != NULL && match_key_hop("to", tokey, &d->to) != 0) continue; /* Match user if specified */ if (d->to.user != NULL && user != NULL && !match_pattern(user, d->to.user)) continue; /* successfully matched this constraint */ if (hostnamep != NULL) *hostnamep = d->to.hostname; debug2_f("allowed for hostname %s", d->to.hostname == NULL ? "*" : d->to.hostname); return 0; } /* no match */ debug2_f("%s identity \"%s\" not permitted for this destination", sshkey_type(id->key), id->comment); return -1; } /* * Check whether hostkeys on a SocketEntry and the optionally specified user * are permitted by the destination constraints on the Identity. * Returns 0 on success or -1 otherwise. */ static int identity_permitted(Identity *id, SocketEntry *e, char *user, const char **forward_hostnamep, const char **last_hostnamep) { size_t i; const char **hp; struct hostkey_sid *hks; const struct sshkey *fromkey = NULL; const char *test_user; char *fp1, *fp2; /* XXX remove logspam */ debug3_f("entering: key %s comment \"%s\", %zu socket bindings, " "%zu constraints", sshkey_type(id->key), id->comment, e->nsession_ids, id->ndest_constraints); if (id->ndest_constraints == 0) return 0; /* unconstrained */ if (e->session_bind_attempted && e->nsession_ids == 0) { error_f("previous session bind failed on socket"); return -1; } if (e->nsession_ids == 0) return 0; /* local use */ /* * Walk through the hops recorded by session_id and try to find a * constraint that satisfies each. */ for (i = 0; i < e->nsession_ids; i++) { hks = e->session_ids + i; if (hks->key == NULL) fatal_f("internal error: no bound key"); /* XXX remove logspam */ fp1 = fp2 = NULL; if (fromkey != NULL && (fp1 = sshkey_fingerprint(fromkey, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); if ((fp2 = sshkey_fingerprint(hks->key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("socketentry fd=%d, entry %zu %s, " "from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type(hks->key), fp2); free(fp1); free(fp2); /* * Record the hostnames for the initial forwarding and * the final destination. */ hp = NULL; if (i == e->nsession_ids - 1) hp = last_hostnamep; else if (i == 0) hp = forward_hostnamep; /* Special handling for final recorded binding */ test_user = NULL; if (i == e->nsession_ids - 1) { /* Can only check user at final hop */ test_user = user; /* * user is only presented for signature requests. * If this is the case, make sure last binding is not * for a forwarding. */ if (hks->forwarded && user != NULL) { error_f("tried to sign on forwarding hop"); return -1; } } else if (!hks->forwarded) { error_f("tried to forward though signing bind"); return -1; } if (permitted_by_dest_constraints(fromkey, hks->key, id, test_user, hp) != 0) return -1; fromkey = hks->key; } /* * Another special case: if the last bound session ID was for a * forwarding, and this function is not being called to check a sign * request (i.e. no 'user' supplied), then only permit the key if * there is a permission that would allow it to be used at another * destination. This hides keys that are allowed to be used to * authenticate *to* a host but not permitted for *use* beyond it. */ hks = &e->session_ids[e->nsession_ids - 1]; if (hks->forwarded && user == NULL && permitted_by_dest_constraints(hks->key, NULL, id, NULL, NULL) != 0) { debug3_f("key permitted at host but not after"); return -1; } /* success */ return 0; } static int socket_is_remote(SocketEntry *e) { return e->session_bind_attempted || (e->nsession_ids != 0); } /* return matching private key for given public key */ static Identity * lookup_identity(struct sshkey *key) { Identity *id; TAILQ_FOREACH(id, &idtab->idlist, next) { if (sshkey_equal(key, id->key)) return (id); } return (NULL); } /* Check confirmation of keysign request */ static int confirm_key(Identity *id, const char *extra) { char *p; int ret = -1; p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); if (p != NULL && ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s", id->comment, p, extra == NULL ? "" : "\n", extra == NULL ? "" : extra)) ret = 0; free(p); return (ret); } static void send_status(SocketEntry *e, int success) { int r; if ((r = sshbuf_put_u32(e->output, 1)) != 0 || (r = sshbuf_put_u8(e->output, success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) fatal_fr(r, "compose"); } /* send list of supported public keys to 'client' */ static void process_request_identities(SocketEntry *e) { Identity *id; struct sshbuf *msg, *keys; int r; u_int i = 0, nentries = 0; char *fp; debug2_f("entering"); if ((msg = sshbuf_new()) == NULL || (keys = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); TAILQ_FOREACH(id, &idtab->idlist, next) { if ((fp = sshkey_fingerprint(id->key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug_f("key %u / %u: %s %s", i++, idtab->nentries, sshkey_ssh_name(id->key), fp); dump_dest_constraints(__func__, id->dest_constraints, id->ndest_constraints); free(fp); /* identity not visible, don't include in response */ if (identity_permitted(id, e, NULL, NULL, NULL) != 0) continue; if ((r = sshkey_puts_opts(id->key, keys, SSHKEY_SERIALIZE_INFO)) != 0 || (r = sshbuf_put_cstring(keys, id->comment)) != 0) { error_fr(r, "compose key/comment"); continue; } nentries++; } debug2_f("replying with %u allowed of %u available keys", nentries, idtab->nentries); if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || (r = sshbuf_put_u32(msg, nentries)) != 0 || (r = sshbuf_putb(msg, keys)) != 0) fatal_fr(r, "compose"); if ((r = sshbuf_put_stringb(e->output, msg)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(msg); sshbuf_free(keys); } static char * agent_decode_alg(struct sshkey *key, u_int flags) { if (key->type == KEY_RSA) { if (flags & SSH_AGENT_RSA_SHA2_256) return "rsa-sha2-256"; else if (flags & SSH_AGENT_RSA_SHA2_512) return "rsa-sha2-512"; } else if (key->type == KEY_RSA_CERT) { if (flags & SSH_AGENT_RSA_SHA2_256) return "rsa-sha2-256-cert-v01@openssh.com"; else if (flags & SSH_AGENT_RSA_SHA2_512) return "rsa-sha2-512-cert-v01@openssh.com"; } return NULL; } /* * Attempt to parse the contents of a buffer as a SSH publickey userauth * request, checking its contents for consistency and matching the embedded * key against the one that is being used for signing. * Note: does not modify msg buffer. * Optionally extract the username, session ID and/or hostkey from the request. */ static int parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key, char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp) { struct sshbuf *b = NULL, *sess_id = NULL; char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL; int r; u_char t, sig_follows; struct sshkey *mkey = NULL, *hostkey = NULL; if (userp != NULL) *userp = NULL; if (sess_idp != NULL) *sess_idp = NULL; if (hostkeyp != NULL) *hostkeyp = NULL; if ((b = sshbuf_fromb(msg)) == NULL) fatal_f("sshbuf_fromb"); /* SSH userauth request */ if ((r = sshbuf_froms(b, &sess_id)) != 0) goto out; if (sshbuf_len(sess_id) == 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */ (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */ (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */ (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */ (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */ (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */ (r = sshkey_froms(b, &mkey)) != 0) /* key */ goto out; if (t != SSH2_MSG_USERAUTH_REQUEST || sig_follows != 1 || strcmp(service, "ssh-connection") != 0 || !sshkey_equal(expected_key, mkey) || sshkey_type_from_name(pkalg) != expected_key->type) { r = SSH_ERR_INVALID_FORMAT; goto out; } if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) { if ((r = sshkey_froms(b, &hostkey)) != 0) goto out; } else if (strcmp(method, "publickey") != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(b) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ r = 0; debug3_f("well formed userauth"); if (userp != NULL) { *userp = user; user = NULL; } if (sess_idp != NULL) { *sess_idp = sess_id; sess_id = NULL; } if (hostkeyp != NULL) { *hostkeyp = hostkey; hostkey = NULL; } out: sshbuf_free(b); sshbuf_free(sess_id); free(user); free(service); free(method); free(pkalg); sshkey_free(mkey); sshkey_free(hostkey); return r; } /* * Attempt to parse the contents of a buffer as a SSHSIG signature request. * Note: does not modify buffer. */ static int parse_sshsig_request(struct sshbuf *msg) { int r; struct sshbuf *b; if ((b = sshbuf_fromb(msg)) == NULL) fatal_f("sshbuf_fromb"); if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 || (r = sshbuf_consume(b, 6)) != 0 || (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */ (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */ goto out; if (sshbuf_len(b) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ r = 0; out: sshbuf_free(b); return r; } /* * This function inspects a message to be signed by a FIDO key that has a * web-like application string (i.e. one that does not begin with "ssh:". * It checks that the message is one of those expected for SSH operations * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges * for the web. */ static int check_websafe_message_contents(struct sshkey *key, struct sshbuf *data) { if (parse_userauth_request(data, key, NULL, NULL, NULL) == 0) { debug_f("signed data matches public key userauth request"); return 1; } if (parse_sshsig_request(data) == 0) { debug_f("signed data matches SSHSIG signature request"); return 1; } /* XXX check CA signature operation */ error("web-origin key attempting to sign non-SSH message"); return 0; } static int buf_equal(const struct sshbuf *a, const struct sshbuf *b) { if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL) return SSH_ERR_INVALID_ARGUMENT; if (sshbuf_len(a) != sshbuf_len(b)) return SSH_ERR_INVALID_FORMAT; if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0) return SSH_ERR_INVALID_FORMAT; return 0; } /* ssh2 only */ static void process_sign_request2(SocketEntry *e) { u_char *signature = NULL; size_t slen = 0; u_int compat = 0, flags; int r, ok = -1, retried = 0; char *fp = NULL, *pin = NULL, *prompt = NULL; char *user = NULL, *sig_dest = NULL; const char *fwd_host = NULL, *dest_host = NULL; struct sshbuf *msg = NULL, *data = NULL, *sid = NULL; struct sshkey *key = NULL, *hostkey = NULL; struct identity *id; struct notifier_ctx *notifier = NULL; debug_f("entering"); if ((msg = sshbuf_new()) == NULL || (data = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshkey_froms(e->request, &key)) != 0 || (r = sshbuf_get_stringb(e->request, data)) != 0 || (r = sshbuf_get_u32(e->request, &flags)) != 0) { error_fr(r, "parse"); goto send; } if ((id = lookup_identity(key)) == NULL) { verbose_f("%s key not found", sshkey_type(key)); goto send; } if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); if (id->ndest_constraints != 0) { if (e->nsession_ids == 0) { logit_f("refusing use of destination-constrained key " "to sign on unbound connection"); goto send; } if (parse_userauth_request(data, key, &user, &sid, &hostkey) != 0) { logit_f("refusing use of destination-constrained key " "to sign an unidentified signature"); goto send; } /* XXX logspam */ debug_f("user=%s", user); if (identity_permitted(id, e, user, &fwd_host, &dest_host) != 0) goto send; /* XXX display fwd_host/dest_host in askpass UI */ /* * Ensure that the session ID is the most recent one * registered on the socket - it should have been bound by * ssh immediately before userauth. */ if (buf_equal(sid, e->session_ids[e->nsession_ids - 1].sid) != 0) { error_f("unexpected session ID (%zu listed) on " "signature request for target user %s with " "key %s %s", e->nsession_ids, user, sshkey_type(id->key), fp); goto send; } /* * Ensure that the hostkey embedded in the signature matches * the one most recently bound to the socket. An exception is * made for the initial forwarding hop. */ if (e->nsession_ids > 1 && hostkey == NULL) { error_f("refusing use of destination-constrained key: " "no hostkey recorded in signature for forwarded " "connection"); goto send; } if (hostkey != NULL && !sshkey_equal(hostkey, e->session_ids[e->nsession_ids - 1].key)) { error_f("refusing use of destination-constrained key: " "mismatch between hostkey in request and most " "recently bound session"); goto send; } xasprintf(&sig_dest, "public key authentication request for " "user \"%s\" to listed host", user); } if (id->confirm && confirm_key(id, sig_dest) != 0) { verbose_f("user refused key"); goto send; } if (sshkey_is_sk(id->key)) { if (restrict_websafe && match_pattern_list(id->key->sk_application, websafe_allowlist, 0) != 1 && !check_websafe_message_contents(key, data)) { /* error already logged */ goto send; } if (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { notifier = notify_start(0, "Confirm user presence for key %s %s%s%s", sshkey_type(id->key), fp, sig_dest == NULL ? "" : "\n", sig_dest == NULL ? "" : sig_dest); } } retry_pin: if ((r = sshkey_sign(id->key, &signature, &slen, sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags), id->sk_provider, pin, compat)) != 0) { debug_fr(r, "sshkey_sign"); if (pin == NULL && !retried && sshkey_is_sk(id->key) && r == SSH_ERR_KEY_WRONG_PASSPHRASE) { notify_complete(notifier, NULL); notifier = NULL; /* XXX include sig_dest */ xasprintf(&prompt, "Enter PIN%sfor %s key %s: ", (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) ? " and confirm user presence " : " ", sshkey_type(id->key), fp); pin = read_passphrase(prompt, RP_USE_ASKPASS); retried = 1; goto retry_pin; } error_fr(r, "sshkey_sign"); goto send; } /* Success */ ok = 0; debug_f("good signature"); send: notify_complete(notifier, "User presence confirmed"); if (ok == 0) { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || (r = sshbuf_put_string(msg, signature, slen)) != 0) fatal_fr(r, "compose"); } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) fatal_fr(r, "compose failure"); if ((r = sshbuf_put_stringb(e->output, msg)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(sid); sshbuf_free(data); sshbuf_free(msg); sshkey_free(key); sshkey_free(hostkey); free(fp); free(signature); free(sig_dest); free(user); free(prompt); if (pin != NULL) freezero(pin, strlen(pin)); } /* shared */ static void process_remove_identity(SocketEntry *e) { int r, success = 0; struct sshkey *key = NULL; Identity *id; debug2_f("entering"); if ((r = sshkey_froms(e->request, &key)) != 0) { error_fr(r, "parse key"); goto done; } if ((id = lookup_identity(key)) == NULL) { debug_f("key not found"); goto done; } /* identity not visible, cannot be removed */ if (identity_permitted(id, e, NULL, NULL, NULL) != 0) goto done; /* error already logged */ /* We have this key, free it. */ if (idtab->nentries < 1) fatal_f("internal error: nentries %d", idtab->nentries); TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); idtab->nentries--; success = 1; done: sshkey_free(key); send_status(e, success); } static void remove_all_identities(void) { Identity *id; debug2_f("entering"); /* Loop over all identities and clear the keys. */ for (id = TAILQ_FIRST(&idtab->idlist); id; id = TAILQ_FIRST(&idtab->idlist)) { TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); } /* Mark that there are no identities. */ idtab->nentries = 0; } static void process_remove_all_identities(SocketEntry *e) { remove_all_identities(); /* Send success. */ send_status(e, 1); } /* removes expired keys and returns number of seconds until the next expiry */ static time_t reaper(void) { time_t deadline = 0, now = monotime(); Identity *id, *nxt; for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { nxt = TAILQ_NEXT(id, next); if (id->death == 0) continue; if (now >= id->death) { debug("expiring key '%s'", id->comment); TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); idtab->nentries--; } else deadline = (deadline == 0) ? id->death : MINIMUM(deadline, id->death); } if (deadline == 0 || deadline <= now) return 0; else return (deadline - now); } static int parse_dest_constraint_hop(struct sshbuf *b, struct dest_constraint_hop *dch) { u_char key_is_ca; size_t elen = 0; int r; struct sshkey *k = NULL; char *fp; memset(dch, '\0', sizeof(*dch)); if ((r = sshbuf_get_cstring(b, &dch->user, NULL)) != 0 || (r = sshbuf_get_cstring(b, &dch->hostname, NULL)) != 0 || (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { error_fr(r, "parse"); goto out; } if (elen != 0) { error_f("unsupported extensions (len %zu)", elen); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } if (*dch->hostname == '\0') { free(dch->hostname); dch->hostname = NULL; } if (*dch->user == '\0') { free(dch->user); dch->user = NULL; } while (sshbuf_len(b) != 0) { dch->keys = xrecallocarray(dch->keys, dch->nkeys, dch->nkeys + 1, sizeof(*dch->keys)); dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys, dch->nkeys + 1, sizeof(*dch->key_is_ca)); if ((r = sshkey_froms(b, &k)) != 0 || (r = sshbuf_get_u8(b, &key_is_ca)) != 0) goto out; if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("%s%s%s: adding %skey %s %s", dch->user == NULL ? "" : dch->user, dch->user == NULL ? "" : "@", dch->hostname, key_is_ca ? "CA " : "", sshkey_type(k), fp); free(fp); dch->keys[dch->nkeys] = k; dch->key_is_ca[dch->nkeys] = key_is_ca != 0; dch->nkeys++; k = NULL; /* transferred */ } /* success */ r = 0; out: sshkey_free(k); return r; } static int parse_dest_constraint(struct sshbuf *m, struct dest_constraint *dc) { struct sshbuf *b = NULL, *frombuf = NULL, *tobuf = NULL; int r; size_t elen = 0; debug3_f("entering"); memset(dc, '\0', sizeof(*dc)); if ((r = sshbuf_froms(m, &b)) != 0 || (r = sshbuf_froms(b, &frombuf)) != 0 || (r = sshbuf_froms(b, &tobuf)) != 0 || (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { error_fr(r, "parse"); goto out; } if ((r = parse_dest_constraint_hop(frombuf, &dc->from)) != 0 || (r = parse_dest_constraint_hop(tobuf, &dc->to)) != 0) goto out; /* already logged */ if (elen != 0) { error_f("unsupported extensions (len %zu)", elen); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)", dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys, dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "", dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys); /* check consistency */ if ((dc->from.hostname == NULL) != (dc->from.nkeys == 0) || dc->from.user != NULL) { error_f("inconsistent \"from\" specification"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (dc->to.hostname == NULL || dc->to.nkeys == 0) { error_f("incomplete \"to\" specification"); r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ r = 0; out: sshbuf_free(b); sshbuf_free(frombuf); sshbuf_free(tobuf); return r; } static int parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, struct dest_constraint **dcsp, size_t *ndcsp, int *cert_onlyp, struct sshkey ***certs, size_t *ncerts) { char *ext_name = NULL; int r; struct sshbuf *b = NULL; u_char v; struct sshkey *k; if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) { error_fr(r, "parse constraint extension"); goto out; } debug_f("constraint ext %s", ext_name); if (strcmp(ext_name, "sk-provider@openssh.com") == 0) { if (sk_providerp == NULL) { error_f("%s not valid here", ext_name); r = SSH_ERR_INVALID_FORMAT; goto out; } if (*sk_providerp != NULL) { error_f("%s already set", ext_name); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_cstring(m, sk_providerp, NULL)) != 0) { error_fr(r, "parse %s", ext_name); goto out; } } else if (strcmp(ext_name, "restrict-destination-v00@openssh.com") == 0) { if (*dcsp != NULL) { error_f("%s already set", ext_name); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_froms(m, &b)) != 0) { error_fr(r, "parse %s outer", ext_name); goto out; } while (sshbuf_len(b) != 0) { if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) { error_f("too many %s constraints", ext_name); r = SSH_ERR_INVALID_FORMAT; goto out; } *dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1, sizeof(**dcsp)); if ((r = parse_dest_constraint(b, *dcsp + (*ndcsp)++)) != 0) goto out; /* error already logged */ } } else if (strcmp(ext_name, "associated-certs-v00@openssh.com") == 0) { if (certs == NULL || ncerts == NULL || cert_onlyp == NULL) { error_f("%s not valid here", ext_name); r = SSH_ERR_INVALID_FORMAT; goto out; } if (*certs != NULL) { error_f("%s already set", ext_name); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_u8(m, &v)) != 0 || (r = sshbuf_froms(m, &b)) != 0) { error_fr(r, "parse %s", ext_name); goto out; } *cert_onlyp = v != 0; while (sshbuf_len(b) != 0) { if (*ncerts >= AGENT_MAX_EXT_CERTS) { error_f("too many %s constraints", ext_name); r = SSH_ERR_INVALID_FORMAT; goto out; } *certs = xrecallocarray(*certs, *ncerts, *ncerts + 1, sizeof(**certs)); if ((r = sshkey_froms(b, &k)) != 0) { error_fr(r, "parse key"); goto out; } (*certs)[(*ncerts)++] = k; } } else { error_f("unsupported constraint \"%s\"", ext_name); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } /* success */ r = 0; out: free(ext_name); sshbuf_free(b); return r; } static int parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, u_int *secondsp, int *confirmp, char **sk_providerp, struct dest_constraint **dcsp, size_t *ndcsp, int *cert_onlyp, size_t *ncerts, struct sshkey ***certs) { u_char ctype; int r; u_int seconds, maxsign = 0; while (sshbuf_len(m)) { if ((r = sshbuf_get_u8(m, &ctype)) != 0) { error_fr(r, "parse constraint type"); goto out; } switch (ctype) { case SSH_AGENT_CONSTRAIN_LIFETIME: if (*deathp != 0) { error_f("lifetime already set"); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_u32(m, &seconds)) != 0) { error_fr(r, "parse lifetime constraint"); goto out; } *deathp = monotime() + seconds; *secondsp = seconds; break; case SSH_AGENT_CONSTRAIN_CONFIRM: if (*confirmp != 0) { error_f("confirm already set"); r = SSH_ERR_INVALID_FORMAT; goto out; } *confirmp = 1; break; case SSH_AGENT_CONSTRAIN_MAXSIGN: if (k == NULL) { error_f("maxsign not valid here"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (maxsign != 0) { error_f("maxsign already set"); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_u32(m, &maxsign)) != 0) { error_fr(r, "parse maxsign constraint"); goto out; } if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) { error_fr(r, "enable maxsign"); goto out; } break; case SSH_AGENT_CONSTRAIN_EXTENSION: if ((r = parse_key_constraint_extension(m, sk_providerp, dcsp, ndcsp, cert_onlyp, certs, ncerts)) != 0) goto out; /* error already logged */ break; default: error_f("Unknown constraint %d", ctype); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } } /* success */ r = 0; out: return r; } static void process_add_identity(SocketEntry *e) { Identity *id; int success = 0, confirm = 0; char *fp, *comment = NULL, *sk_provider = NULL; char canonical_provider[PATH_MAX]; time_t death = 0; u_int seconds = 0; struct dest_constraint *dest_constraints = NULL; size_t ndest_constraints = 0; struct sshkey *k = NULL; int r = SSH_ERR_INTERNAL_ERROR; debug2_f("entering"); if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || k == NULL || (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { error_fr(r, "parse"); goto out; } if (parse_key_constraints(e->request, k, &death, &seconds, &confirm, &sk_provider, &dest_constraints, &ndest_constraints, NULL, NULL, NULL) != 0) { error_f("failed to parse constraints"); sshbuf_reset(e->request); goto out; } dump_dest_constraints(__func__, dest_constraints, ndest_constraints); if (sk_provider != NULL) { if (!sshkey_is_sk(k)) { error("Cannot add provider: %s is not an " "authenticator-hosted key", sshkey_type(k)); goto out; } if (strcasecmp(sk_provider, "internal") == 0) { debug_f("internal provider"); } else { if (socket_is_remote(e) && !remote_add_provider) { verbose("failed add of SK provider \"%.100s\": " "remote addition of providers is disabled", sk_provider); goto out; } if (realpath(sk_provider, canonical_provider) == NULL) { verbose("failed provider \"%.100s\": " "realpath: %s", sk_provider, strerror(errno)); goto out; } free(sk_provider); sk_provider = xstrdup(canonical_provider); if (match_pattern_list(sk_provider, allowed_providers, 0) != 1) { error("Refusing add key: " "provider %s not allowed", sk_provider); goto out; } } } if ((r = sshkey_shield_private(k)) != 0) { error_fr(r, "shield private"); goto out; } if (lifetime && !death) death = monotime() + lifetime; if ((id = lookup_identity(k)) == NULL) { id = xcalloc(1, sizeof(Identity)); TAILQ_INSERT_TAIL(&idtab->idlist, id, next); /* Increment the number of identities. */ idtab->nentries++; } else { /* identity not visible, do not update */ if (identity_permitted(id, e, NULL, NULL, NULL) != 0) goto out; /* error already logged */ /* key state might have been updated */ sshkey_free(id->key); free(id->comment); free(id->sk_provider); free_dest_constraints(id->dest_constraints, id->ndest_constraints); } /* success */ id->key = k; id->comment = comment; id->death = death; id->confirm = confirm; id->sk_provider = sk_provider; id->dest_constraints = dest_constraints; id->ndest_constraints = ndest_constraints; if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) " "(provider: %s) (destination constraints: %zu)", sshkey_ssh_name(k), fp, comment, seconds, confirm, sk_provider == NULL ? "none" : sk_provider, ndest_constraints); free(fp); /* transferred */ k = NULL; comment = NULL; sk_provider = NULL; dest_constraints = NULL; ndest_constraints = 0; success = 1; out: free(sk_provider); free(comment); sshkey_free(k); free_dest_constraints(dest_constraints, ndest_constraints); send_status(e, success); } /* XXX todo: encrypt sensitive data with passphrase */ static void process_lock_agent(SocketEntry *e, int lock) { int r, success = 0, delay; char *passwd; u_char passwdhash[LOCK_SIZE]; static u_int fail_count = 0; size_t pwlen; debug2_f("entering"); /* * This is deliberately fatal: the user has requested that we lock, * but we can't parse their request properly. The only safe thing to * do is abort. */ if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0) fatal_fr(r, "parse"); if (pwlen == 0) { debug("empty password not supported"); } else if (locked && !lock) { if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0) fatal("bcrypt_pbkdf"); if (timingsafe_bcmp(passwdhash, lock_pwhash, LOCK_SIZE) == 0) { debug("agent unlocked"); locked = 0; fail_count = 0; explicit_bzero(lock_pwhash, sizeof(lock_pwhash)); success = 1; } else { /* delay in 0.1s increments up to 10s */ if (fail_count < 100) fail_count++; delay = 100000 * fail_count; debug("unlock failed, delaying %0.1lf seconds", (double)delay/1000000); usleep(delay); } explicit_bzero(passwdhash, sizeof(passwdhash)); } else if (!locked && lock) { debug("agent locked"); locked = 1; arc4random_buf(lock_salt, sizeof(lock_salt)); if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), lock_pwhash, sizeof(lock_pwhash), LOCK_ROUNDS) < 0) fatal("bcrypt_pbkdf"); success = 1; } freezero(passwd, pwlen); send_status(e, success); } static void no_identities(SocketEntry *e) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || (r = sshbuf_put_u32(msg, 0)) != 0 || (r = sshbuf_put_stringb(e->output, msg)) != 0) fatal_fr(r, "compose"); sshbuf_free(msg); } #ifdef ENABLE_PKCS11 /* Add an identity to idlist; takes ownership of 'key' and 'comment' */ static void add_p11_identity(struct sshkey *key, char *comment, const char *provider, time_t death, u_int confirm, struct dest_constraint *dest_constraints, size_t ndest_constraints) { Identity *id; if (lookup_identity(key) != NULL) { sshkey_free(key); free(comment); return; } id = xcalloc(1, sizeof(Identity)); id->key = key; id->comment = comment; id->provider = xstrdup(provider); id->death = death; id->confirm = confirm; id->dest_constraints = dup_dest_constraints(dest_constraints, ndest_constraints); id->ndest_constraints = ndest_constraints; TAILQ_INSERT_TAIL(&idtab->idlist, id, next); idtab->nentries++; } static void process_add_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; time_t death = 0; struct sshkey **keys = NULL, *k; struct dest_constraint *dest_constraints = NULL; size_t j, ndest_constraints = 0, ncerts = 0; struct sshkey **certs = NULL; int cert_only = 0; debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { error_fr(r, "parse"); goto send; } if (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm, NULL, &dest_constraints, &ndest_constraints, &cert_only, &ncerts, &certs) != 0) { error_f("failed to parse constraints"); goto send; } dump_dest_constraints(__func__, dest_constraints, ndest_constraints); if (socket_is_remote(e) && !remote_add_provider) { verbose("failed PKCS#11 add of \"%.100s\": remote addition of " "providers is disabled", provider); goto send; } if (realpath(provider, canonical_provider) == NULL) { verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", provider, strerror(errno)); goto send; } if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { verbose("refusing PKCS#11 add of \"%.100s\": " "provider not allowed", canonical_provider); goto send; } debug_f("add %.100s", canonical_provider); if (lifetime && !death) death = monotime() + lifetime; count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments); for (i = 0; i < count; i++) { if (comments[i] == NULL || comments[i][0] == '\0') { free(comments[i]); comments[i] = xstrdup(canonical_provider); } for (j = 0; j < ncerts; j++) { if (!sshkey_is_cert(certs[j])) continue; if (!sshkey_equal_public(keys[i], certs[j])) continue; if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) continue; add_p11_identity(k, xstrdup(comments[i]), canonical_provider, death, confirm, dest_constraints, ndest_constraints); success = 1; } if (!cert_only && lookup_identity(keys[i]) == NULL) { add_p11_identity(keys[i], comments[i], canonical_provider, death, confirm, dest_constraints, ndest_constraints); keys[i] = NULL; /* transferred */ comments[i] = NULL; /* transferred */ success = 1; } /* XXX update constraints for existing keys */ sshkey_free(keys[i]); free(comments[i]); } send: free(pin); free(provider); free(keys); free(comments); free_dest_constraints(dest_constraints, ndest_constraints); for (j = 0; j < ncerts; j++) sshkey_free(certs[j]); free(certs); send_status(e, success); } static void process_remove_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; int r, success = 0; Identity *id, *nxt; debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { error_fr(r, "parse"); goto send; } free(pin); if (realpath(provider, canonical_provider) == NULL) { verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", provider, strerror(errno)); goto send; } debug_f("remove %.100s", canonical_provider); for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { nxt = TAILQ_NEXT(id, next); /* Skip file--based keys */ if (id->provider == NULL) continue; if (!strcmp(canonical_provider, id->provider)) { TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); idtab->nentries--; } } if (pkcs11_del_provider(canonical_provider) == 0) success = 1; else error_f("pkcs11_del_provider failed"); send: free(provider); send_status(e, success); } #endif /* ENABLE_PKCS11 */ static int process_ext_session_bind(SocketEntry *e) { int r, sid_match, key_match; struct sshkey *key = NULL; struct sshbuf *sid = NULL, *sig = NULL; char *fp = NULL; size_t i; u_char fwd = 0; debug2_f("entering"); e->session_bind_attempted = 1; if ((r = sshkey_froms(e->request, &key)) != 0 || (r = sshbuf_froms(e->request, &sid)) != 0 || (r = sshbuf_froms(e->request, &sig)) != 0 || (r = sshbuf_get_u8(e->request, &fwd)) != 0) { error_fr(r, "parse"); goto out; } if (sshbuf_len(sid) > AGENT_MAX_SID_LEN) { error_f("session ID too long"); goto out; } if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); /* check signature with hostkey on session ID */ if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig), sshbuf_ptr(sid), sshbuf_len(sid), NULL, 0, NULL)) != 0) { error_fr(r, "sshkey_verify for %s %s", sshkey_type(key), fp); goto out; } /* check whether sid/key already recorded */ for (i = 0; i < e->nsession_ids; i++) { if (!e->session_ids[i].forwarded) { error_f("attempt to bind session ID to socket " "previously bound for authentication attempt"); r = -1; goto out; } sid_match = buf_equal(sid, e->session_ids[i].sid) == 0; key_match = sshkey_equal(key, e->session_ids[i].key); if (sid_match && key_match) { debug_f("session ID already recorded for %s %s", sshkey_type(key), fp); r = 0; goto out; } else if (sid_match) { error_f("session ID recorded against different key " "for %s %s", sshkey_type(key), fp); r = -1; goto out; } /* * new sid with previously-seen key can happen, e.g. multiple * connections to the same host. */ } /* record new key/sid */ if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) { error_f("too many session IDs recorded"); r = -1; goto out; } e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids, e->nsession_ids + 1, sizeof(*e->session_ids)); i = e->nsession_ids++; debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key), fp, i, AGENT_MAX_SESSION_IDS); e->session_ids[i].key = key; e->session_ids[i].forwarded = fwd != 0; key = NULL; /* transferred */ /* can't transfer sid; it's refcounted and scoped to request's life */ if ((e->session_ids[i].sid = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0) fatal_fr(r, "sshbuf_putb session ID"); /* success */ r = 0; out: free(fp); sshkey_free(key); sshbuf_free(sid); sshbuf_free(sig); return r == 0 ? 1 : 0; } static void process_extension(SocketEntry *e) { int r, success = 0; char *name; debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) { error_fr(r, "parse"); goto send; } if (strcmp(name, "session-bind@openssh.com") == 0) success = process_ext_session_bind(e); else debug_f("unsupported extension \"%s\"", name); free(name); send: send_status(e, success); } /* * dispatch incoming message. * returns 1 on success, 0 for incomplete messages or -1 on error. */ static int process_message(u_int socknum) { u_int msg_len; u_char type; const u_char *cp; int r; SocketEntry *e; if (socknum >= sockets_alloc) fatal_f("sock %u >= allocated %u", socknum, sockets_alloc); e = &sockets[socknum]; if (sshbuf_len(e->input) < 5) return 0; /* Incomplete message header. */ cp = sshbuf_ptr(e->input); msg_len = PEEK_U32(cp); if (msg_len > AGENT_MAX_LEN) { debug_f("socket %u (fd=%d) message too long %u > %u", socknum, e->fd, msg_len, AGENT_MAX_LEN); return -1; } if (sshbuf_len(e->input) < msg_len + 4) return 0; /* Incomplete message body. */ /* move the current input to e->request */ sshbuf_reset(e->request); if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 || (r = sshbuf_get_u8(e->request, &type)) != 0) { if (r == SSH_ERR_MESSAGE_INCOMPLETE || r == SSH_ERR_STRING_TOO_LARGE) { error_fr(r, "parse"); return -1; } fatal_fr(r, "parse"); } debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type); /* check whether agent is locked */ if (locked && type != SSH_AGENTC_UNLOCK) { sshbuf_reset(e->request); switch (type) { case SSH2_AGENTC_REQUEST_IDENTITIES: /* send empty lists */ no_identities(e); break; default: /* send a fail message for all other request types */ send_status(e, 0); } return 1; } switch (type) { case SSH_AGENTC_LOCK: case SSH_AGENTC_UNLOCK: process_lock_agent(e, type == SSH_AGENTC_LOCK); break; case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: process_remove_all_identities(e); /* safe for !WITH_SSH1 */ break; /* ssh2 */ case SSH2_AGENTC_SIGN_REQUEST: process_sign_request2(e); break; case SSH2_AGENTC_REQUEST_IDENTITIES: process_request_identities(e); break; case SSH2_AGENTC_ADD_IDENTITY: case SSH2_AGENTC_ADD_ID_CONSTRAINED: process_add_identity(e); break; case SSH2_AGENTC_REMOVE_IDENTITY: process_remove_identity(e); break; case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: process_remove_all_identities(e); break; #ifdef ENABLE_PKCS11 case SSH_AGENTC_ADD_SMARTCARD_KEY: case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: process_add_smartcard_key(e); break; case SSH_AGENTC_REMOVE_SMARTCARD_KEY: process_remove_smartcard_key(e); break; #endif /* ENABLE_PKCS11 */ case SSH_AGENTC_EXTENSION: process_extension(e); break; default: /* Unknown message. Respond with failure. */ error("Unknown message %d", type); sshbuf_reset(e->request); send_status(e, 0); break; } return 1; } static void new_socket(sock_type type, int fd) { u_int i, old_alloc, new_alloc; debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" : (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN")); set_nonblock(fd); if (fd > max_fd) max_fd = fd; for (i = 0; i < sockets_alloc; i++) if (sockets[i].type == AUTH_UNUSED) { sockets[i].fd = fd; if ((sockets[i].input = sshbuf_new()) == NULL || (sockets[i].output = sshbuf_new()) == NULL || (sockets[i].request = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); sockets[i].type = type; return; } old_alloc = sockets_alloc; new_alloc = sockets_alloc + 10; sockets = xrecallocarray(sockets, old_alloc, new_alloc, sizeof(sockets[0])); for (i = old_alloc; i < new_alloc; i++) sockets[i].type = AUTH_UNUSED; sockets_alloc = new_alloc; sockets[old_alloc].fd = fd; if ((sockets[old_alloc].input = sshbuf_new()) == NULL || (sockets[old_alloc].output = sshbuf_new()) == NULL || (sockets[old_alloc].request = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); sockets[old_alloc].type = type; } static int handle_socket_read(u_int socknum) { struct sockaddr_un sunaddr; socklen_t slen; uid_t euid; gid_t egid; int fd; slen = sizeof(sunaddr); fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen); if (fd == -1) { error("accept from AUTH_SOCKET: %s", strerror(errno)); return -1; } if (getpeereid(fd, &euid, &egid) == -1) { error("getpeereid %d failed: %s", fd, strerror(errno)); close(fd); return -1; } if ((euid != 0) && (getuid() != euid)) { error("uid mismatch: peer euid %u != uid %u", (u_int) euid, (u_int) getuid()); close(fd); return -1; } new_socket(AUTH_CONNECTION, fd); return 0; } static int handle_conn_read(u_int socknum) { char buf[AGENT_RBUF_LEN]; ssize_t len; int r; if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) { if (len == -1) { if (errno == EAGAIN || errno == EINTR) return 0; error_f("read error on socket %u (fd %d): %s", socknum, sockets[socknum].fd, strerror(errno)); } return -1; } if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0) fatal_fr(r, "compose"); explicit_bzero(buf, sizeof(buf)); for (;;) { if ((r = process_message(socknum)) == -1) return -1; else if (r == 0) break; } return 0; } static int handle_conn_write(u_int socknum) { ssize_t len; int r; if (sshbuf_len(sockets[socknum].output) == 0) return 0; /* shouldn't happen */ if ((len = write(sockets[socknum].fd, sshbuf_ptr(sockets[socknum].output), sshbuf_len(sockets[socknum].output))) <= 0) { if (len == -1) { if (errno == EAGAIN || errno == EINTR) return 0; error_f("read error on socket %u (fd %d): %s", socknum, sockets[socknum].fd, strerror(errno)); } return -1; } if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0) fatal_fr(r, "consume"); return 0; } static void after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds) { size_t i; u_int socknum, activefds = npfd; for (i = 0; i < npfd; i++) { if (pfd[i].revents == 0) continue; /* Find sockets entry */ for (socknum = 0; socknum < sockets_alloc; socknum++) { if (sockets[socknum].type != AUTH_SOCKET && sockets[socknum].type != AUTH_CONNECTION) continue; if (pfd[i].fd == sockets[socknum].fd) break; } if (socknum >= sockets_alloc) { error_f("no socket for fd %d", pfd[i].fd); continue; } /* Process events */ switch (sockets[socknum].type) { case AUTH_SOCKET: if ((pfd[i].revents & (POLLIN|POLLERR)) == 0) break; if (npfd > maxfds) { debug3("out of fds (active %u >= limit %u); " "skipping accept", activefds, maxfds); break; } if (handle_socket_read(socknum) == 0) activefds++; break; case AUTH_CONNECTION: if ((pfd[i].revents & (POLLIN|POLLHUP|POLLERR)) != 0 && handle_conn_read(socknum) != 0) goto close_sock; if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 && handle_conn_write(socknum) != 0) { close_sock: if (activefds == 0) fatal("activefds == 0 at close_sock"); close_socket(&sockets[socknum]); activefds--; break; } break; default: break; } } } static int prepare_poll(struct pollfd **pfdp, size_t *npfdp, struct timespec *timeoutp, u_int maxfds) { struct pollfd *pfd = *pfdp; size_t i, j, npfd = 0; time_t deadline; int r; /* Count active sockets */ for (i = 0; i < sockets_alloc; i++) { switch (sockets[i].type) { case AUTH_SOCKET: case AUTH_CONNECTION: npfd++; break; case AUTH_UNUSED: break; default: fatal("Unknown socket type %d", sockets[i].type); break; } } if (npfd != *npfdp && (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL) fatal_f("recallocarray failed"); *pfdp = pfd; *npfdp = npfd; for (i = j = 0; i < sockets_alloc; i++) { switch (sockets[i].type) { case AUTH_SOCKET: if (npfd > maxfds) { debug3("out of fds (active %zu >= limit %u); " "skipping arming listener", npfd, maxfds); break; } pfd[j].fd = sockets[i].fd; pfd[j].revents = 0; pfd[j].events = POLLIN; j++; break; case AUTH_CONNECTION: pfd[j].fd = sockets[i].fd; pfd[j].revents = 0; /* * Only prepare to read if we can handle a full-size * input read buffer and enqueue a max size reply.. */ if ((r = sshbuf_check_reserve(sockets[i].input, AGENT_RBUF_LEN)) == 0 && (r = sshbuf_check_reserve(sockets[i].output, AGENT_MAX_LEN)) == 0) pfd[j].events = POLLIN; else if (r != SSH_ERR_NO_BUFFER_SPACE) fatal_fr(r, "reserve"); if (sshbuf_len(sockets[i].output) > 0) pfd[j].events |= POLLOUT; j++; break; default: break; } } deadline = reaper(); if (parent_alive_interval != 0) deadline = (deadline == 0) ? parent_alive_interval : MINIMUM(deadline, parent_alive_interval); if (deadline != 0) ptimeout_deadline_sec(timeoutp, deadline); return (1); } static void cleanup_socket(void) { if (cleanup_pid != 0 && getpid() != cleanup_pid) return; debug_f("cleanup"); if (socket_name[0]) unlink(socket_name); if (socket_dir[0]) rmdir(socket_dir); } void cleanup_exit(int i) { cleanup_socket(); #ifdef ENABLE_PKCS11 pkcs11_terminate(); #endif _exit(i); } static void cleanup_handler(int sig) { signalled_exit = sig; } static void keydrop_handler(int sig) { signalled_keydrop = sig; } static void check_parent_exists(void) { /* * If our parent has exited then getppid() will return (pid_t)1, * so testing for that should be safe. */ if (parent_pid != -1 && getppid() != parent_pid) { /* printf("Parent has died - Authentication agent exiting.\n"); */ cleanup_socket(); _exit(2); } } static void usage(void) { fprintf(stderr, "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n" " [-O option] [-P allowed_providers] [-t life]\n" " ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option]\n" " [-P allowed_providers] [-t life] command [arg ...]\n" " ssh-agent [-c | -s] -k\n"); exit(1); } int main(int ac, char **av) { int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0; int sock = -1, ch, result, saved_errno; char *shell, *format, *fdstr, *pidstr, *agentsocket = NULL; const char *errstr = NULL; const char *ccp; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif extern int optind; extern char *optarg; pid_t pid; char pidstrbuf[1 + 3 * sizeof pid]; size_t len; mode_t prev_mask; struct timespec timeout; struct pollfd *pfd = NULL; size_t npfd = 0; u_int maxfds; sigset_t nsigset, osigset; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* drop */ (void)setegid(getgid()); (void)setgid(getgid()); platform_disable_tracing(0); /* strict=no */ #ifdef RLIMIT_NOFILE if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) fatal("%s: getrlimit: %s", __progname, strerror(errno)); #endif __progname = ssh_get_progname(av[0]); seed_rng(); while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); if (fingerprint_hash == -1) fatal("Invalid hash algorithm \"%s\"", optarg); break; case 'c': if (s_flag) usage(); c_flag++; break; case 'k': k_flag++; break; case 'O': if (strcmp(optarg, "no-restrict-websafe") == 0) restrict_websafe = 0; else if (strcmp(optarg, "allow-remote-pkcs11") == 0) remote_add_provider = 1; else if ((ccp = strprefix(optarg, "websafe-allow=", 0)) != NULL) { if (websafe_allowlist != NULL) fatal("websafe-allow already set"); websafe_allowlist = xstrdup(ccp); } else fatal("Unknown -O option"); break; case 'P': if (allowed_providers != NULL) fatal("-P option already specified"); allowed_providers = xstrdup(optarg); break; case 's': if (c_flag) usage(); s_flag++; break; case 'd': if (d_flag || D_flag) usage(); d_flag++; break; case 'D': if (d_flag || D_flag) usage(); D_flag++; break; case 'a': agentsocket = optarg; break; case 't': if ((lifetime = convtime(optarg)) == -1) { fprintf(stderr, "Invalid lifetime\n"); usage(); } break; default: usage(); } } ac -= optind; av += optind; if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag)) usage(); if (allowed_providers == NULL) allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS); if (websafe_allowlist == NULL) websafe_allowlist = xstrdup(DEFAULT_WEBSAFE_ALLOWLIST); if (ac == 0 && !c_flag && !s_flag) { shell = getenv("SHELL"); if (shell != NULL && (len = strlen(shell)) > 2 && strncmp(shell + len - 3, "csh", 3) == 0) c_flag = 1; } if (k_flag) { pidstr = getenv(SSH_AGENTPID_ENV_NAME); if (pidstr == NULL) { fprintf(stderr, "%s not set, cannot kill agent\n", SSH_AGENTPID_ENV_NAME); exit(1); } pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); if (errstr) { fprintf(stderr, "%s=\"%s\", which is not a good PID: %s\n", SSH_AGENTPID_ENV_NAME, pidstr, errstr); exit(1); } if (kill(pid, SIGTERM) == -1) { perror("kill"); exit(1); } format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME); printf(format, SSH_AGENTPID_ENV_NAME); printf("echo Agent pid %ld killed;\n", (long)pid); exit(0); } /* * Minimum file descriptors: * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) + * a few spare for libc / stack protectors / sanitisers, etc. */ #define SSH_AGENT_MIN_FDS (3+1+1+1+4) if (rlim.rlim_cur < SSH_AGENT_MIN_FDS) fatal("%s: file descriptor rlimit %lld too low (minimum %u)", __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS); maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS; parent_pid = getpid(); /* Has the socket been provided via socket activation? */ if (agentsocket == NULL && ac == 0 && (d_flag || D_flag) && (pidstr = getenv("LISTEN_PID")) != NULL && (fdstr = getenv("LISTEN_FDS")) != NULL) { if (strcmp(fdstr, "1") != 0) { fatal("unexpected LISTEN_FDS contents " "(want: \"1\" got\"%s\"", fdstr); } if (fcntl(3, F_GETFL) == -1) fatal("LISTEN_FDS set but fd 3 unavailable"); pid = (int)strtonum(pidstr, 1, INT_MAX, &errstr); if (errstr != NULL) fatal("invalid LISTEN_PID: %s", errstr); if (pid != getpid()) fatal("bad LISTEN_PID: %d vs pid %d", pid, getpid()); debug("using socket activation on fd=3"); sock = 3; } /* Otherwise, create private directory for agent socket */ if (sock == -1) { if (agentsocket == NULL) { mktemp_proto(socket_dir, sizeof(socket_dir)); if (mkdtemp(socket_dir) == NULL) { perror("mkdtemp: private socket dir"); exit(1); } snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, (long)parent_pid); } else { /* Try to use specified agent socket */ socket_dir[0] = '\0'; strlcpy(socket_name, agentsocket, sizeof socket_name); } } closefrom(sock == -1 ? STDERR_FILENO + 1 : sock + 1); /* * Create socket early so it will exist before command gets run from * the parent. */ if (sock == -1) { prev_mask = umask(0177); sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0); if (sock < 0) { /* XXX - unix_listener() calls error() not perror() */ *socket_name = '\0'; /* Don't unlink existing file */ cleanup_exit(1); } umask(prev_mask); } /* * Fork, and have the parent execute the command, if any, or present * the socket data. The child continues as the authentication agent. */ if (D_flag || d_flag) { log_init(__progname, d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1); if (socket_name[0] != '\0') { format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, SSH_AUTHSOCKET_ENV_NAME); printf("echo Agent pid %ld;\n", (long)parent_pid); fflush(stdout); } goto skip; } pid = fork(); if (pid == -1) { perror("fork"); cleanup_exit(1); } if (pid != 0) { /* Parent - execute the given command. */ close(sock); snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); if (ac == 0) { format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, SSH_AUTHSOCKET_ENV_NAME); printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, SSH_AGENTPID_ENV_NAME); printf("echo Agent pid %ld;\n", (long)pid); exit(0); } if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) { perror("setenv"); exit(1); } execvp(av[0], av); perror(av[0]); exit(1); } /* child */ log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); if (setsid() == -1) { error("setsid: %s", strerror(errno)); cleanup_exit(1); } (void)chdir("/"); if (stdfd_devnull(1, 1, 1) == -1) error_f("stdfd_devnull failed"); #ifdef HAVE_SETRLIMIT /* deny core dumps, since memory contains unencrypted private keys */ rlim.rlim_cur = rlim.rlim_max = 0; if (setrlimit(RLIMIT_CORE, &rlim) == -1) { error("setrlimit RLIMIT_CORE: %s", strerror(errno)); cleanup_exit(1); } #endif skip: cleanup_pid = getpid(); #ifdef ENABLE_PKCS11 pkcs11_init(0); #endif new_socket(AUTH_SOCKET, sock); if (ac > 0) parent_alive_interval = 10; idtab_init(); ssh_signal(SIGPIPE, SIG_IGN); ssh_signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN); ssh_signal(SIGHUP, cleanup_handler); ssh_signal(SIGTERM, cleanup_handler); ssh_signal(SIGUSR1, keydrop_handler); sigemptyset(&nsigset); sigaddset(&nsigset, SIGINT); sigaddset(&nsigset, SIGHUP); sigaddset(&nsigset, SIGTERM); sigaddset(&nsigset, SIGUSR1); if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1) fatal("%s: pledge: %s", __progname, strerror(errno)); platform_pledge_agent(); while (1) { sigprocmask(SIG_BLOCK, &nsigset, &osigset); if (signalled_exit != 0) { logit("exiting on signal %d", (int)signalled_exit); cleanup_exit(2); } if (signalled_keydrop) { logit("signal %d received; removing all keys", signalled_keydrop); remove_all_identities(); signalled_keydrop = 0; } ptimeout_init(&timeout); prepare_poll(&pfd, &npfd, &timeout, maxfds); result = ppoll(pfd, npfd, ptimeout_get_tsp(&timeout), &osigset); sigprocmask(SIG_SETMASK, &osigset, NULL); saved_errno = errno; if (parent_alive_interval != 0) check_parent_exists(); (void) reaper(); /* remove expired keys */ if (result == -1) { if (saved_errno == EINTR) continue; fatal("poll: %s", strerror(saved_errno)); } else if (result > 0) after_poll(pfd, npfd, maxfds); } /* NOTREACHED */ } openssh-10.0p1/PaxHeaders.10889/ssh-dss.c100644 001750 001750 0000000003614775415623 0014704xustar0030 atime=1744182234.830883871 openssh-10.0p1/ssh-dss.c010064400017500001750000000274251477541562300133010ustar00djmdjm/* $OpenBSD: ssh-dss.c,v 1.50 2024/01/11 01:45:36 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #if defined(WITH_OPENSSL) && defined(WITH_DSA) #include #include #include #include #include #include #include "sshbuf.h" #include "ssherr.h" #include "digest.h" #define SSHKEY_INTERNAL #include "sshkey.h" #include "openbsd-compat/openssl-compat.h" #define INTBLOB_LEN 20 #define SIGBLOB_LEN (2*INTBLOB_LEN) static u_int ssh_dss_size(const struct sshkey *key) { const BIGNUM *dsa_p; if (key->dsa == NULL) return 0; DSA_get0_pqg(key->dsa, &dsa_p, NULL, NULL); return BN_num_bits(dsa_p); } static int ssh_dss_alloc(struct sshkey *k) { if ((k->dsa = DSA_new()) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } static void ssh_dss_cleanup(struct sshkey *k) { DSA_free(k->dsa); k->dsa = NULL; } static int ssh_dss_equal(const struct sshkey *a, const struct sshkey *b) { const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a; const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b; if (a->dsa == NULL || b->dsa == NULL) return 0; DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a); DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b); DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL); DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL); if (dsa_p_a == NULL || dsa_p_b == NULL || dsa_q_a == NULL || dsa_q_b == NULL || dsa_g_a == NULL || dsa_g_b == NULL || dsa_pub_key_a == NULL || dsa_pub_key_b == NULL) return 0; if (BN_cmp(dsa_p_a, dsa_p_b) != 0) return 0; if (BN_cmp(dsa_q_a, dsa_q_b) != 0) return 0; if (BN_cmp(dsa_g_a, dsa_g_b) != 0) return 0; if (BN_cmp(dsa_pub_key_a, dsa_pub_key_b) != 0) return 0; return 1; } static int ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; if (key->dsa == NULL) return SSH_ERR_INVALID_ARGUMENT; DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); DSA_get0_key(key->dsa, &dsa_pub_key, NULL); if (dsa_p == NULL || dsa_q == NULL || dsa_g == NULL || dsa_pub_key == NULL) return SSH_ERR_INTERNAL_ERROR; if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 || (r = sshbuf_put_bignum2(b, dsa_q)) != 0 || (r = sshbuf_put_bignum2(b, dsa_g)) != 0 || (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0) return r; return 0; } static int ssh_dss_serialize_private(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; const BIGNUM *dsa_priv_key; DSA_get0_key(key->dsa, NULL, &dsa_priv_key); if (!sshkey_is_cert(key)) { if ((r = ssh_dss_serialize_public(key, b, opts)) != 0) return r; } if ((r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) return r; return 0; } static int ssh_dss_generate(struct sshkey *k, int bits) { DSA *private; if (bits != 1024) return SSH_ERR_KEY_LENGTH; if ((private = DSA_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, NULL, NULL) || !DSA_generate_key(private)) { DSA_free(private); return SSH_ERR_LIBCRYPTO_ERROR; } k->dsa = private; return 0; } static int ssh_dss_copy_public(const struct sshkey *from, struct sshkey *to) { const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL; BIGNUM *dsa_pub_key_dup = NULL; int r = SSH_ERR_INTERNAL_ERROR; DSA_get0_pqg(from->dsa, &dsa_p, &dsa_q, &dsa_g); DSA_get0_key(from->dsa, &dsa_pub_key, NULL); if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || (dsa_q_dup = BN_dup(dsa_q)) == NULL || (dsa_g_dup = BN_dup(dsa_g)) == NULL || (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (!DSA_set0_pqg(to->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */ if (!DSA_set0_key(to->dsa, dsa_pub_key_dup, NULL)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } dsa_pub_key_dup = NULL; /* transferred */ /* success */ r = 0; out: BN_clear_free(dsa_p_dup); BN_clear_free(dsa_q_dup); BN_clear_free(dsa_g_dup); BN_clear_free(dsa_pub_key_dup); return r; } static int ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b, struct sshkey *key) { int ret = SSH_ERR_INTERNAL_ERROR; BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL; if (sshbuf_get_bignum2(b, &dsa_p) != 0 || sshbuf_get_bignum2(b, &dsa_q) != 0 || sshbuf_get_bignum2(b, &dsa_g) != 0 || sshbuf_get_bignum2(b, &dsa_pub_key) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } dsa_p = dsa_q = dsa_g = NULL; /* transferred */ if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } dsa_pub_key = NULL; /* transferred */ #ifdef DEBUG_PK DSA_print_fp(stderr, key->dsa, 8); #endif /* success */ ret = 0; out: BN_clear_free(dsa_p); BN_clear_free(dsa_q); BN_clear_free(dsa_g); BN_clear_free(dsa_pub_key); return ret; } static int ssh_dss_deserialize_private(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; BIGNUM *dsa_priv_key = NULL; if (!sshkey_is_cert(key)) { if ((r = ssh_dss_deserialize_public(ktype, b, key)) != 0) return r; } if ((r = sshbuf_get_bignum2(b, &dsa_priv_key)) != 0) return r; if (!DSA_set0_key(key->dsa, NULL, dsa_priv_key)) { BN_clear_free(dsa_priv_key); return SSH_ERR_LIBCRYPTO_ERROR; } return 0; } static int ssh_dss_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { DSA_SIG *sig = NULL; const BIGNUM *sig_r, *sig_s; u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); struct sshbuf *b = NULL; int ret = SSH_ERR_INVALID_ARGUMENT; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (key == NULL || key->dsa == NULL || sshkey_type_plain(key->type) != KEY_DSA) return SSH_ERR_INVALID_ARGUMENT; if (dlen == 0) return SSH_ERR_INTERNAL_ERROR; if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, digest, sizeof(digest))) != 0) goto out; if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } DSA_SIG_get0(sig, &sig_r, &sig_s); rlen = BN_num_bytes(sig_r); slen = BN_num_bytes(sig_s); if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { ret = SSH_ERR_INTERNAL_ERROR; goto out; } explicit_bzero(sigblob, SIGBLOB_LEN); BN_bn2bin(sig_r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); BN_bn2bin(sig_s, sigblob + SIGBLOB_LEN - slen); if ((b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0) goto out; len = sshbuf_len(b); if (sigp != NULL) { if ((*sigp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sshbuf_ptr(b), len); } if (lenp != NULL) *lenp = len; ret = 0; out: explicit_bzero(digest, sizeof(digest)); DSA_SIG_free(sig); sshbuf_free(b); return ret; } static int ssh_dss_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { DSA_SIG *dsig = NULL; BIGNUM *sig_r = NULL, *sig_s = NULL; u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1); int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; char *ktype = NULL; if (key == NULL || key->dsa == NULL || sshkey_type_plain(key->type) != KEY_DSA || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; if (hlen == 0) return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || sshbuf_get_string(b, &sigblob, &len) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (strcmp("ssh-dss", ktype) != 0) { ret = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } if (len != SIGBLOB_LEN) { ret = SSH_ERR_INVALID_FORMAT; goto out; } /* parse signature */ if ((dsig = DSA_SIG_new()) == NULL || (sig_r = BN_new()) == NULL || (sig_s = BN_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig_r) == NULL) || (BN_bin2bn(sigblob + INTBLOB_LEN, INTBLOB_LEN, sig_s) == NULL)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (!DSA_SIG_set0(dsig, sig_r, sig_s)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } sig_r = sig_s = NULL; /* transferred */ /* sha1 the data */ if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, dlen, digest, sizeof(digest))) != 0) goto out; switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) { case 1: ret = 0; break; case 0: ret = SSH_ERR_SIGNATURE_INVALID; goto out; default: ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } out: explicit_bzero(digest, sizeof(digest)); DSA_SIG_free(dsig); BN_clear_free(sig_r); BN_clear_free(sig_s); sshbuf_free(b); free(ktype); if (sigblob != NULL) freezero(sigblob, len); return ret; } static const struct sshkey_impl_funcs sshkey_dss_funcs = { /* .size = */ ssh_dss_size, /* .alloc = */ ssh_dss_alloc, /* .cleanup = */ ssh_dss_cleanup, /* .equal = */ ssh_dss_equal, /* .ssh_serialize_public = */ ssh_dss_serialize_public, /* .ssh_deserialize_public = */ ssh_dss_deserialize_public, /* .ssh_serialize_private = */ ssh_dss_serialize_private, /* .ssh_deserialize_private = */ ssh_dss_deserialize_private, /* .generate = */ ssh_dss_generate, /* .copy_public = */ ssh_dss_copy_public, /* .sign = */ ssh_dss_sign, /* .verify = */ ssh_dss_verify, }; const struct sshkey_impl sshkey_dss_impl = { /* .name = */ "ssh-dss", /* .shortname = */ "DSA", /* .sigalg = */ NULL, /* .type = */ KEY_DSA, /* .nid = */ 0, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_dss_funcs, }; const struct sshkey_impl sshkey_dsa_cert_impl = { /* .name = */ "ssh-dss-cert-v01@openssh.com", /* .shortname = */ "DSA-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_DSA_CERT, /* .nid = */ 0, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_dss_funcs, }; #endif /* WITH_OPENSSL && WITH_DSA */ openssh-10.0p1/PaxHeaders.10889/ssh-ecdsa-sk.c100644 001750 001750 0000000003614775415623 0015605xustar0030 atime=1744182234.830883871 openssh-10.0p1/ssh-ecdsa-sk.c010064400017500001750000000341061477541562300141740ustar00djmdjm/* $OpenBSD: ssh-ecdsa-sk.c,v 1.19 2024/08/15 00:51:51 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2019 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* #define DEBUG_SK 1 */ #include "includes.h" #include #ifdef WITH_OPENSSL #include #include #include #include #endif #include #include /* needed for DEBUG_SK only */ #include "openbsd-compat/openssl-compat.h" #include "sshbuf.h" #include "ssherr.h" #include "digest.h" #define SSHKEY_INTERNAL #include "sshkey.h" #ifndef OPENSSL_HAS_ECC /* ARGSUSED */ int ssh_ecdsa_sk_verify(const struct sshkey *key, const u_char *signature, size_t signaturelen, const u_char *data, size_t datalen, u_int compat, struct sshkey_sig_details **detailsp) { return SSH_ERR_FEATURE_UNSUPPORTED; } #else /* OPENSSL_HAS_ECC */ /* Reuse some ECDSA internals */ extern struct sshkey_impl_funcs sshkey_ecdsa_funcs; static void ssh_ecdsa_sk_cleanup(struct sshkey *k) { sshkey_sk_cleanup(k); sshkey_ecdsa_funcs.cleanup(k); } static int ssh_ecdsa_sk_equal(const struct sshkey *a, const struct sshkey *b) { if (!sshkey_sk_fields_equal(a, b)) return 0; if (!sshkey_ecdsa_funcs.equal(a, b)) return 0; return 1; } static int ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if ((r = sshkey_ecdsa_funcs.serialize_public(key, b, opts)) != 0) return r; if ((r = sshkey_serialize_sk(key, b)) != 0) return r; return 0; } static int ssh_ecdsa_sk_serialize_private(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if (!sshkey_is_cert(key)) { if ((r = sshkey_ecdsa_funcs.serialize_public(key, b, opts)) != 0) return r; } if ((r = sshkey_serialize_private_sk(key, b)) != 0) return r; return 0; } static int ssh_ecdsa_sk_copy_public(const struct sshkey *from, struct sshkey *to) { int r; if ((r = sshkey_ecdsa_funcs.copy_public(from, to)) != 0) return r; if ((r = sshkey_copy_public_sk(from, to)) != 0) return r; return 0; } static int ssh_ecdsa_sk_deserialize_public(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, b, key)) != 0) return r; if ((r = sshkey_deserialize_sk(b, key)) != 0) return r; return 0; } static int ssh_ecdsa_sk_deserialize_private(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; if (!sshkey_is_cert(key)) { if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, b, key)) != 0) return r; } if ((r = sshkey_private_deserialize_sk(b, key)) != 0) return r; return 0; } /* * Check FIDO/W3C webauthn signatures clientData field against the expected * format and prepare a hash of it for use in signature verification. * * webauthn signatures do not sign the hash of the message directly, but * instead sign a JSON-like "clientData" wrapper structure that contains the * message hash along with a other information. * * Fortunately this structure has a fixed format so it is possible to verify * that the hash of the signed message is present within the clientData * structure without needing to implement any JSON parsing. */ static int webauthn_check_prepare_hash(const u_char *data, size_t datalen, const char *origin, const struct sshbuf *wrapper, uint8_t flags, const struct sshbuf *extensions, u_char *msghash, size_t msghashlen) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *chall = NULL, *m = NULL; if ((m = sshbuf_new()) == NULL || (chall = sshbuf_from(data, datalen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* * Ensure origin contains no quote character and that the flags are * consistent with what we received */ if (strchr(origin, '\"') != NULL || (flags & 0x40) != 0 /* AD */ || ((flags & 0x80) == 0 /* ED */) != (sshbuf_len(extensions) == 0)) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* * Prepare the preamble to clientData that we expect, poking the * challenge and origin into their canonical positions in the * structure. The crossOrigin flag and any additional extension * fields present are ignored. */ #define WEBAUTHN_0 "{\"type\":\"webauthn.get\",\"challenge\":\"" #define WEBAUTHN_1 "\",\"origin\":\"" #define WEBAUTHN_2 "\"" if ((r = sshbuf_put(m, WEBAUTHN_0, sizeof(WEBAUTHN_0) - 1)) != 0 || (r = sshbuf_dtourlb64(chall, m, 0)) != 0 || (r = sshbuf_put(m, WEBAUTHN_1, sizeof(WEBAUTHN_1) - 1)) != 0 || (r = sshbuf_put(m, origin, strlen(origin))) != 0 || (r = sshbuf_put(m, WEBAUTHN_2, sizeof(WEBAUTHN_2) - 1)) != 0) goto out; #ifdef DEBUG_SK fprintf(stderr, "%s: received origin: %s\n", __func__, origin); fprintf(stderr, "%s: received clientData:\n", __func__); sshbuf_dump(wrapper, stderr); fprintf(stderr, "%s: expected clientData premable:\n", __func__); sshbuf_dump(m, stderr); #endif /* Check that the supplied clientData has the preamble we expect */ if ((r = sshbuf_cmp(wrapper, 0, sshbuf_ptr(m), sshbuf_len(m))) != 0) goto out; /* Prepare hash of clientData */ if ((r = ssh_digest_buffer(SSH_DIGEST_SHA256, wrapper, msghash, msghashlen)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(chall); sshbuf_free(m); return r; } static int ssh_ecdsa_sk_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { ECDSA_SIG *esig = NULL; EVP_MD_CTX *md_ctx = NULL; BIGNUM *sig_r = NULL, *sig_s = NULL; u_char sig_flags; u_char msghash[32], apphash[32]; u_int sig_counter; u_char *sigb = NULL, *cp; int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR, len = 0; struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL; struct sshbuf *webauthn_wrapper = NULL, *webauthn_exts = NULL; char *ktype = NULL, *webauthn_origin = NULL; struct sshkey_sig_details *details = NULL; #ifdef DEBUG_SK char *tmp = NULL; #endif if (detailsp != NULL) *detailsp = NULL; if (key == NULL || key->pkey == NULL || sshkey_type_plain(key->type) != KEY_ECDSA_SK || sig == NULL || siglen == 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(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((details = calloc(1, sizeof(*details))) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (strcmp(ktype, "webauthn-sk-ecdsa-sha2-nistp256@openssh.com") == 0) is_webauthn = 1; else if (strcmp(ktype, "sk-ecdsa-sha2-nistp256@openssh.com") != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_froms(b, &sigbuf) != 0 || sshbuf_get_u8(b, &sig_flags) != 0 || sshbuf_get_u32(b, &sig_counter) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (is_webauthn) { if (sshbuf_get_cstring(b, &webauthn_origin, NULL) != 0 || sshbuf_froms(b, &webauthn_wrapper) != 0 || sshbuf_froms(b, &webauthn_exts) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } /* parse signature */ if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 || sshbuf_get_bignum2(sigbuf, &sig_s) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(sigbuf) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } #ifdef DEBUG_SK fprintf(stderr, "%s: data: (len %zu)\n", __func__, dlen); /* sshbuf_dump_data(data, datalen, stderr); */ fprintf(stderr, "%s: sig_r: %s\n", __func__, (tmp = BN_bn2hex(sig_r))); free(tmp); fprintf(stderr, "%s: sig_s: %s\n", __func__, (tmp = BN_bn2hex(sig_s))); free(tmp); fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", __func__, sig_flags, sig_counter); if (is_webauthn) { fprintf(stderr, "%s: webauthn origin: %s\n", __func__, webauthn_origin); fprintf(stderr, "%s: webauthn_wrapper:\n", __func__); sshbuf_dump(webauthn_wrapper, stderr); } #endif if ((esig = ECDSA_SIG_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (!ECDSA_SIG_set0(esig, sig_r, sig_s)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } sig_r = sig_s = NULL; /* transferred */ /* Reconstruct data that was supposedly signed */ if ((original_signed = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (is_webauthn) { if ((ret = webauthn_check_prepare_hash(data, dlen, webauthn_origin, webauthn_wrapper, sig_flags, webauthn_exts, msghash, sizeof(msghash))) != 0) goto out; } else if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, dlen, msghash, sizeof(msghash))) != 0) goto out; /* Application value is hashed before signature */ if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application, strlen(key->sk_application), apphash, sizeof(apphash))) != 0) goto out; #ifdef DEBUG_SK fprintf(stderr, "%s: hashed application:\n", __func__); sshbuf_dump_data(apphash, sizeof(apphash), stderr); fprintf(stderr, "%s: hashed message:\n", __func__); sshbuf_dump_data(msghash, sizeof(msghash), stderr); #endif if ((ret = sshbuf_put(original_signed, apphash, sizeof(apphash))) != 0 || (ret = sshbuf_put_u8(original_signed, sig_flags)) != 0 || (ret = sshbuf_put_u32(original_signed, sig_counter)) != 0 || (ret = sshbuf_putb(original_signed, webauthn_exts)) != 0 || (ret = sshbuf_put(original_signed, msghash, sizeof(msghash))) != 0) goto out; 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); #endif if ((md_ctx = EVP_MD_CTX_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((len = i2d_ECDSA_SIG(esig, NULL)) <= 0) { len = 0; ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((sigb = calloc(1, len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } cp = sigb; /* ASN1_item_i2d increments the pointer past the object */ if (i2d_ECDSA_SIG(esig, &cp) != len) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } #ifdef DEBUG_SK fprintf(stderr, "%s: signed hash:\n", __func__); sshbuf_dump_data(sigb, len, stderr); #endif /* Verify it */ if (EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL, key->pkey) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } switch (EVP_DigestVerify(md_ctx, sigb, len, sshbuf_ptr(original_signed), sshbuf_len(original_signed))) { 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(apphash, sizeof(apphash)); sshkey_sig_details_free(details); sshbuf_free(webauthn_wrapper); sshbuf_free(webauthn_exts); free(webauthn_origin); sshbuf_free(original_signed); sshbuf_free(sigbuf); sshbuf_free(b); ECDSA_SIG_free(esig); BN_clear_free(sig_r); BN_clear_free(sig_s); free(ktype); freezero(sigb, len); EVP_MD_CTX_free(md_ctx); return ret; } static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = { /* .size = */ NULL, /* .alloc = */ NULL, /* .cleanup = */ ssh_ecdsa_sk_cleanup, /* .equal = */ ssh_ecdsa_sk_equal, /* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public, /* .ssh_deserialize_public = */ ssh_ecdsa_sk_deserialize_public, /* .ssh_serialize_private = */ ssh_ecdsa_sk_serialize_private, /* .ssh_deserialize_private = */ ssh_ecdsa_sk_deserialize_private, /* .generate = */ NULL, /* .copy_public = */ ssh_ecdsa_sk_copy_public, /* .sign = */ NULL, /* .verify = */ ssh_ecdsa_sk_verify, }; const struct sshkey_impl sshkey_ecdsa_sk_impl = { /* .name = */ "sk-ecdsa-sha2-nistp256@openssh.com", /* .shortname = */ "ECDSA-SK", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA_SK, /* .nid = */ NID_X9_62_prime256v1, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_ecdsa_sk_funcs, }; const struct sshkey_impl sshkey_ecdsa_sk_cert_impl = { /* .name = */ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", /* .shortname = */ "ECDSA-SK-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA_SK_CERT, /* .nid = */ NID_X9_62_prime256v1, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_ecdsa_sk_funcs, }; const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl = { /* .name = */ "webauthn-sk-ecdsa-sha2-nistp256@openssh.com", /* .shortname = */ "ECDSA-SK", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA_SK, /* .nid = */ NID_X9_62_prime256v1, /* .cert = */ 0, /* .sigonly = */ 1, /* .keybits = */ 256, /* .funcs = */ &sshkey_ecdsa_sk_funcs, }; #endif /* OPENSSL_HAS_ECC */ openssh-10.0p1/PaxHeaders.10889/ssh-ecdsa.c100644 001750 001750 0000000003614775415623 0015172xustar0030 atime=1744182234.831860218 openssh-10.0p1/ssh-ecdsa.c010064400017500001750000000340201477541562300135540ustar00djmdjm/* $OpenBSD: ssh-ecdsa.c,v 1.27 2024/08/15 00:51:51 djm Exp $ */ /* * Copyright (c) 2000 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 #include #include #include #include #include #include "sshbuf.h" #include "ssherr.h" #include "digest.h" #define SSHKEY_INTERNAL #include "sshkey.h" #include "openbsd-compat/openssl-compat.h" int sshkey_ecdsa_fixup_group(EVP_PKEY *k) { int nids[] = { NID_X9_62_prime256v1, NID_secp384r1, #ifdef OPENSSL_HAS_NISTP521 NID_secp521r1, #endif -1 }; int nid = -1; u_int i; const EC_GROUP *g; EC_KEY *ec = NULL; EC_GROUP *eg = NULL; if ((ec = EVP_PKEY_get1_EC_KEY(k)) == NULL || (g = EC_KEY_get0_group(ec)) == NULL) goto out; /* * The group may be stored in a ASN.1 encoded private key in one of two * ways: as a "named group", which is reconstituted by ASN.1 object ID * or explicit group parameters encoded into the key blob. Only the * "named group" case sets the group NID for us, but we can figure * it out for the other case by comparing against all the groups that * are supported. */ if ((nid = EC_GROUP_get_curve_name(g)) > 0) goto out; nid = -1; for (i = 0; nids[i] != -1; i++) { if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) goto out; if (EC_GROUP_cmp(g, eg, NULL) == 0) break; EC_GROUP_free(eg); eg = NULL; } if (nids[i] == -1) goto out; /* Use the group with the NID attached */ EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); if (EC_KEY_set_group(ec, eg) != 1 || EVP_PKEY_set1_EC_KEY(k, ec) != 1) goto out; /* success */ nid = nids[i]; out: EC_KEY_free(ec); EC_GROUP_free(eg); return nid; } static u_int ssh_ecdsa_size(const struct sshkey *key) { switch (key->ecdsa_nid) { case NID_X9_62_prime256v1: return 256; case NID_secp384r1: return 384; #ifdef OPENSSL_HAS_NISTP521 case NID_secp521r1: return 521; #endif default: return 0; } } static void ssh_ecdsa_cleanup(struct sshkey *k) { EVP_PKEY_free(k->pkey); k->pkey = NULL; } static int ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b) { if (a->pkey == NULL || b->pkey == NULL) return 0; return EVP_PKEY_cmp(a->pkey, b->pkey) == 1; } static int ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if (key->pkey == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_put_cstring(b, sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || (r = sshbuf_put_ec_pkey(b, key->pkey)) != 0) return r; return 0; } static int ssh_ecdsa_serialize_private(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if (!sshkey_is_cert(key)) { if ((r = ssh_ecdsa_serialize_public(key, b, opts)) != 0) return r; } if ((r = sshbuf_put_bignum2(b, EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(key->pkey)))) != 0) return r; return 0; } static int ssh_ecdsa_generate(struct sshkey *k, int bits) { EVP_PKEY *res = NULL; EVP_PKEY_CTX *ctx = NULL; int ret = SSH_ERR_INTERNAL_ERROR; if ((k->ecdsa_nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) return SSH_ERR_KEY_LENGTH; if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) return SSH_ERR_ALLOC_FAIL; if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, k->ecdsa_nid) <= 0 || EVP_PKEY_keygen(ctx, &res) <= 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* success */ k->pkey = res; res = NULL; ret = 0; out: EVP_PKEY_free(res); EVP_PKEY_CTX_free(ctx); return ret; } static int ssh_ecdsa_copy_public(const struct sshkey *from, struct sshkey *to) { const EC_KEY *ec_from; EC_KEY *ec_to = NULL; int ret = SSH_ERR_INTERNAL_ERROR; ec_from = EVP_PKEY_get0_EC_KEY(from->pkey); if (ec_from == NULL) return SSH_ERR_LIBCRYPTO_ERROR; to->ecdsa_nid = from->ecdsa_nid; if ((ec_to = EC_KEY_new_by_curve_name(from->ecdsa_nid)) == NULL) return SSH_ERR_ALLOC_FAIL; if (EC_KEY_set_public_key(ec_to, EC_KEY_get0_public_key(ec_from)) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } EVP_PKEY_free(to->pkey); if ((to->pkey = EVP_PKEY_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (EVP_PKEY_set1_EC_KEY(to->pkey, ec_to) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ret = 0; out: EC_KEY_free(ec_to); return ret; } static int ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; char *curve = NULL; EVP_PKEY *pkey = NULL; EC_KEY *ec = NULL; if ((key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype)) == -1) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_get_cstring(b, &curve, NULL)) != 0) goto out; if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) { r = SSH_ERR_EC_CURVE_MISMATCH; goto out; } if ((ec = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((r = sshbuf_get_eckey(b, ec)) != 0) goto out; if (sshkey_ec_validate_public(EC_KEY_get0_group(ec), EC_KEY_get0_public_key(ec)) != 0) { r = SSH_ERR_KEY_INVALID_EC_VALUE; goto out; } if ((pkey = EVP_PKEY_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (EVP_PKEY_set1_EC_KEY(pkey, ec) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } EVP_PKEY_free(key->pkey); key->pkey = pkey; pkey = NULL; /* success */ r = 0; #ifdef DEBUG_PK sshkey_dump_ec_point( EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key->pkey)), EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(key->pkey))); #endif out: EC_KEY_free(ec); EVP_PKEY_free(pkey); free(curve); return r; } static int ssh_ecdsa_deserialize_private(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; BIGNUM *exponent = NULL; EC_KEY *ec = NULL; if (!sshkey_is_cert(key)) { if ((r = ssh_ecdsa_deserialize_public(ktype, b, key)) != 0) return r; } if ((r = sshbuf_get_bignum2(b, &exponent)) != 0) goto out; if ((ec = EVP_PKEY_get1_EC_KEY(key->pkey)) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (EC_KEY_set_private_key(ec, exponent) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((r = sshkey_ec_validate_private(ec)) != 0) goto out; if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* success */ r = 0; out: BN_clear_free(exponent); EC_KEY_free(ec); return r; } static int ssh_ecdsa_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t dlen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { ECDSA_SIG *esig = NULL; unsigned char *sigb = NULL; const unsigned char *psig; const BIGNUM *sig_r, *sig_s; int hash_alg; size_t slen = 0; struct sshbuf *b = NULL, *bb = NULL; int len = 0, ret = SSH_ERR_INTERNAL_ERROR; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (key == NULL || key->pkey == NULL || sshkey_type_plain(key->type) != KEY_ECDSA) return SSH_ERR_INVALID_ARGUMENT; if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) return SSH_ERR_INTERNAL_ERROR; if ((ret = sshkey_pkey_digest_sign(key->pkey, hash_alg, &sigb, &slen, data, dlen)) != 0) goto out; psig = sigb; if ((esig = d2i_ECDSA_SIG(NULL, &psig, slen)) == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } ECDSA_SIG_get0(esig, &sig_r, &sig_s); if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 || (ret = sshbuf_put_bignum2(bb, sig_s)) != 0) goto out; if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || (ret = sshbuf_put_stringb(b, bb)) != 0) goto out; len = sshbuf_len(b); if (sigp != NULL) { if ((*sigp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sshbuf_ptr(b), len); } if (lenp != NULL) *lenp = len; ret = 0; out: freezero(sigb, slen); sshbuf_free(b); sshbuf_free(bb); ECDSA_SIG_free(esig); return ret; } static int ssh_ecdsa_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { ECDSA_SIG *esig = NULL; BIGNUM *sig_r = NULL, *sig_s = NULL; int hash_alg, len = 0; int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL, *sigbuf = NULL; char *ktype = NULL; unsigned char *sigb = NULL, *cp; if (key == NULL || key->pkey == NULL || sshkey_type_plain(key->type) != KEY_ECDSA || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || sshbuf_froms(b, &sigbuf) != 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 (sshbuf_len(sigbuf) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } if ((esig = ECDSA_SIG_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (!ECDSA_SIG_set0(esig, sig_r, sig_s)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } sig_r = sig_s = NULL; /* transferred */ if ((len = i2d_ECDSA_SIG(esig, NULL)) <= 0) { len = 0; ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((sigb = calloc(1, len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } cp = sigb; /* ASN1_item_i2d increments the pointer past the object */ if (i2d_ECDSA_SIG(esig, &cp) != len) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((ret = sshkey_pkey_digest_verify(key->pkey, hash_alg, data, dlen, sigb, len)) != 0) goto out; /* success */ out: freezero(sigb, len); sshbuf_free(sigbuf); sshbuf_free(b); ECDSA_SIG_free(esig); BN_clear_free(sig_r); BN_clear_free(sig_s); free(ktype); return ret; } /* NB. not static; used by ECDSA-SK */ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = { /* .size = */ ssh_ecdsa_size, /* .alloc = */ NULL, /* .cleanup = */ ssh_ecdsa_cleanup, /* .equal = */ ssh_ecdsa_equal, /* .ssh_serialize_public = */ ssh_ecdsa_serialize_public, /* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public, /* .ssh_serialize_private = */ ssh_ecdsa_serialize_private, /* .ssh_deserialize_private = */ ssh_ecdsa_deserialize_private, /* .generate = */ ssh_ecdsa_generate, /* .copy_public = */ ssh_ecdsa_copy_public, /* .sign = */ ssh_ecdsa_sign, /* .verify = */ ssh_ecdsa_verify, }; const struct sshkey_impl sshkey_ecdsa_nistp256_impl = { /* .name = */ "ecdsa-sha2-nistp256", /* .shortname = */ "ECDSA", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA, /* .nid = */ NID_X9_62_prime256v1, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_ecdsa_funcs, }; const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl = { /* .name = */ "ecdsa-sha2-nistp256-cert-v01@openssh.com", /* .shortname = */ "ECDSA-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA_CERT, /* .nid = */ NID_X9_62_prime256v1, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_ecdsa_funcs, }; const struct sshkey_impl sshkey_ecdsa_nistp384_impl = { /* .name = */ "ecdsa-sha2-nistp384", /* .shortname = */ "ECDSA", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA, /* .nid = */ NID_secp384r1, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_ecdsa_funcs, }; const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl = { /* .name = */ "ecdsa-sha2-nistp384-cert-v01@openssh.com", /* .shortname = */ "ECDSA-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA_CERT, /* .nid = */ NID_secp384r1, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_ecdsa_funcs, }; #ifdef OPENSSL_HAS_NISTP521 const struct sshkey_impl sshkey_ecdsa_nistp521_impl = { /* .name = */ "ecdsa-sha2-nistp521", /* .shortname = */ "ECDSA", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA, /* .nid = */ NID_secp521r1, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_ecdsa_funcs, }; const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl = { /* .name = */ "ecdsa-sha2-nistp521-cert-v01@openssh.com", /* .shortname = */ "ECDSA-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_ECDSA_CERT, /* .nid = */ NID_secp521r1, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_ecdsa_funcs, }; #endif #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ openssh-10.0p1/PaxHeaders.10889/ssh-ed25519-sk.c100644 001750 001750 0000000003614775415623 0015524xustar0030 atime=1744182234.831860218 openssh-10.0p1/ssh-ed25519-sk.c010064400017500001750000000171051477541562300141130ustar00djmdjm/* $OpenBSD: ssh-ed25519-sk.c,v 1.15 2022/10/28 00:44:44 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* #define DEBUG_SK 1 */ #include "includes.h" #define SSHKEY_INTERNAL #include #include #include "crypto_api.h" #include #include #include "log.h" #include "sshbuf.h" #include "sshkey.h" #include "ssherr.h" #include "ssh.h" #include "digest.h" /* Reuse some ED25519 internals */ extern struct sshkey_impl_funcs sshkey_ed25519_funcs; static void ssh_ed25519_sk_cleanup(struct sshkey *k) { sshkey_sk_cleanup(k); sshkey_ed25519_funcs.cleanup(k); } static int ssh_ed25519_sk_equal(const struct sshkey *a, const struct sshkey *b) { if (!sshkey_sk_fields_equal(a, b)) return 0; if (!sshkey_ed25519_funcs.equal(a, b)) return 0; return 1; } static int ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if ((r = sshkey_ed25519_funcs.serialize_public(key, b, opts)) != 0) return r; if ((r = sshkey_serialize_sk(key, b)) != 0) return r; return 0; } static int ssh_ed25519_sk_serialize_private(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if ((r = sshkey_ed25519_funcs.serialize_public(key, b, opts)) != 0) return r; if ((r = sshkey_serialize_private_sk(key, b)) != 0) return r; return 0; } static int ssh_ed25519_sk_copy_public(const struct sshkey *from, struct sshkey *to) { int r; if ((r = sshkey_ed25519_funcs.copy_public(from, to)) != 0) return r; if ((r = sshkey_copy_public_sk(from, to)) != 0) return r; return 0; } static int ssh_ed25519_sk_deserialize_public(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; if ((r = sshkey_ed25519_funcs.deserialize_public(ktype, b, key)) != 0) return r; if ((r = sshkey_deserialize_sk(b, key)) != 0) return r; return 0; } static int ssh_ed25519_sk_deserialize_private(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; if ((r = sshkey_ed25519_funcs.deserialize_public(ktype, b, key)) != 0) return r; if ((r = sshkey_private_deserialize_sk(b, key)) != 0) return r; return 0; } static int ssh_ed25519_sk_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { struct sshbuf *b = NULL; 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 || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_from(sig, siglen)) == 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, dlen, msghash, sizeof(msghash)) != 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } #ifdef DEBUG_SK fprintf(stderr, "%s: hashed application:\n", __func__); sshbuf_dump_data(apphash, sizeof(apphash), stderr); fprintf(stderr, "%s: hashed message:\n", __func__); sshbuf_dump_data(msghash, sizeof(msghash), stderr); #endif if ((details = calloc(1, sizeof(*details))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } details->sk_counter = sig_counter; details->sk_flags = sig_flags; if ((encoded = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (sshbuf_put(encoded, sigblob, len) != 0 || sshbuf_put(encoded, apphash, sizeof(apphash)) != 0 || sshbuf_put_u8(encoded, sig_flags) != 0 || sshbuf_put_u32(encoded, sig_counter) != 0 || sshbuf_put(encoded, msghash, sizeof(msghash)) != 0) { r = SSH_ERR_ALLOC_FAIL; goto out; } #ifdef DEBUG_SK fprintf(stderr, "%s: signed buf:\n", __func__); sshbuf_dump(encoded, stderr); #endif sm = sshbuf_ptr(encoded); smlen = sshbuf_len(encoded); mlen = smlen; if ((m = malloc(smlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, key->ed25519_pk)) != 0) { debug2_f("crypto_sign_ed25519_open failed: %d", ret); } if (ret != 0 || mlen != smlen - len) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } /* XXX compare 'm' and 'sm + len' ? */ /* success */ r = 0; if (detailsp != NULL) { *detailsp = details; details = NULL; } out: if (m != NULL) freezero(m, smlen); /* NB mlen may be invalid if r != 0 */ sshkey_sig_details_free(details); sshbuf_free(b); sshbuf_free(encoded); free(ktype); return r; } static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = { /* .size = */ NULL, /* .alloc = */ NULL, /* .cleanup = */ ssh_ed25519_sk_cleanup, /* .equal = */ ssh_ed25519_sk_equal, /* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public, /* .ssh_deserialize_public = */ ssh_ed25519_sk_deserialize_public, /* .ssh_serialize_private = */ ssh_ed25519_sk_serialize_private, /* .ssh_deserialize_private = */ ssh_ed25519_sk_deserialize_private, /* .generate = */ NULL, /* .copy_public = */ ssh_ed25519_sk_copy_public, /* .sign = */ NULL, /* .verify = */ ssh_ed25519_sk_verify, }; const struct sshkey_impl sshkey_ed25519_sk_impl = { /* .name = */ "sk-ssh-ed25519@openssh.com", /* .shortname = */ "ED25519-SK", /* .sigalg = */ NULL, /* .type = */ KEY_ED25519_SK, /* .nid = */ 0, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_ed25519_sk_funcs, }; const struct sshkey_impl sshkey_ed25519_sk_cert_impl = { /* .name = */ "sk-ssh-ed25519-cert-v01@openssh.com", /* .shortname = */ "ED25519-SK-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_ED25519_SK_CERT, /* .nid = */ 0, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_ed25519_sk_funcs, }; openssh-10.0p1/PaxHeaders.10889/ssh-ed25519.c100644 001750 001750 0000000003614775415623 0015111xustar0030 atime=1744182234.831860218 openssh-10.0p1/ssh-ed25519.c010064400017500001750000000175271477541562300135100ustar00djmdjm/* $OpenBSD: ssh-ed25519.c,v 1.19 2022/10/28 00:44:44 djm Exp $ */ /* * Copyright (c) 2013 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" #include #include #include "crypto_api.h" #include #include #include "log.h" #include "sshbuf.h" #define SSHKEY_INTERNAL #include "sshkey.h" #include "ssherr.h" #include "ssh.h" static void ssh_ed25519_cleanup(struct sshkey *k) { freezero(k->ed25519_pk, ED25519_PK_SZ); freezero(k->ed25519_sk, ED25519_SK_SZ); k->ed25519_pk = NULL; k->ed25519_sk = NULL; } static int ssh_ed25519_equal(const struct sshkey *a, const struct sshkey *b) { if (a->ed25519_pk == NULL || b->ed25519_pk == NULL) return 0; if (memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) != 0) return 0; return 1; } static int ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if (key->ed25519_pk == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0) return r; return 0; } static int ssh_ed25519_serialize_private(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if ((r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0 || (r = sshbuf_put_string(b, key->ed25519_sk, ED25519_SK_SZ)) != 0) return r; return 0; } static int ssh_ed25519_generate(struct sshkey *k, int bits) { if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL || (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) return SSH_ERR_ALLOC_FAIL; crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); return 0; } static int ssh_ed25519_copy_public(const struct sshkey *from, struct sshkey *to) { if (from->ed25519_pk == NULL) return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */ if ((to->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) return SSH_ERR_ALLOC_FAIL; memcpy(to->ed25519_pk, from->ed25519_pk, ED25519_PK_SZ); return 0; } static int ssh_ed25519_deserialize_public(const char *ktype, struct sshbuf *b, struct sshkey *key) { u_char *pk = NULL; size_t len = 0; int r; if ((r = sshbuf_get_string(b, &pk, &len)) != 0) return r; if (len != ED25519_PK_SZ) { freezero(pk, len); return SSH_ERR_INVALID_FORMAT; } key->ed25519_pk = pk; return 0; } static int ssh_ed25519_deserialize_private(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; size_t sklen = 0; u_char *ed25519_sk = NULL; if ((r = ssh_ed25519_deserialize_public(NULL, b, key)) != 0) goto out; if ((r = sshbuf_get_string(b, &ed25519_sk, &sklen)) != 0) goto out; if (sklen != ED25519_SK_SZ) { r = SSH_ERR_INVALID_FORMAT; goto out; } key->ed25519_sk = ed25519_sk; ed25519_sk = NULL; /* transferred */ /* success */ r = 0; out: freezero(ed25519_sk, sklen); return r; } static int ssh_ed25519_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { u_char *sig = NULL; size_t slen = 0, len; 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_ED25519 || key->ed25519_sk == NULL || datalen >= INT_MAX - crypto_sign_ed25519_BYTES) return SSH_ERR_INVALID_ARGUMENT; smlen = slen = datalen + crypto_sign_ed25519_BYTES; if ((sig = malloc(slen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, key->ed25519_sk)) != 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-ed25519")) != 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: sshbuf_free(b); if (sig != NULL) freezero(sig, slen); return r; } static int ssh_ed25519_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { struct sshbuf *b = NULL; char *ktype = NULL; const u_char *sigblob; u_char *sm = NULL, *m = NULL; size_t len; unsigned long long smlen = 0, mlen = 0; int r, ret; if (key == NULL || sshkey_type_plain(key->type) != KEY_ED25519 || key->ed25519_pk == NULL || dlen >= INT_MAX - crypto_sign_ed25519_BYTES || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0) goto out; if (strcmp("ssh-ed25519", 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 (dlen >= SIZE_MAX - len) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } smlen = len + dlen; mlen = smlen; if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(sm, sigblob, len); memcpy(sm+len, data, dlen); if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, key->ed25519_pk)) != 0) { debug2_f("crypto_sign_ed25519_open failed: %d", ret); } if (ret != 0 || mlen != dlen) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } /* XXX compare 'm' and 'data' ? */ /* success */ r = 0; out: if (sm != NULL) freezero(sm, smlen); if (m != NULL) freezero(m, smlen); /* NB mlen may be invalid if r != 0 */ sshbuf_free(b); free(ktype); return r; } /* NB. not static; used by ED25519-SK */ const struct sshkey_impl_funcs sshkey_ed25519_funcs = { /* .size = */ NULL, /* .alloc = */ NULL, /* .cleanup = */ ssh_ed25519_cleanup, /* .equal = */ ssh_ed25519_equal, /* .ssh_serialize_public = */ ssh_ed25519_serialize_public, /* .ssh_deserialize_public = */ ssh_ed25519_deserialize_public, /* .ssh_serialize_private = */ ssh_ed25519_serialize_private, /* .ssh_deserialize_private = */ ssh_ed25519_deserialize_private, /* .generate = */ ssh_ed25519_generate, /* .copy_public = */ ssh_ed25519_copy_public, /* .sign = */ ssh_ed25519_sign, /* .verify = */ ssh_ed25519_verify, }; const struct sshkey_impl sshkey_ed25519_impl = { /* .name = */ "ssh-ed25519", /* .shortname = */ "ED25519", /* .sigalg = */ NULL, /* .type = */ KEY_ED25519, /* .nid = */ 0, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_ed25519_funcs, }; const struct sshkey_impl sshkey_ed25519_cert_impl = { /* .name = */ "ssh-ed25519-cert-v01@openssh.com", /* .shortname = */ "ED25519-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_ED25519_CERT, /* .nid = */ 0, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_ed25519_funcs, }; openssh-10.0p1/PaxHeaders.10889/ssh-gss.h100644 001750 001750 0000000003614775415623 0014714xustar0030 atime=1744182234.831860218 openssh-10.0p1/ssh-gss.h010064400017500001750000000112451477541562300133020ustar00djmdjm/* $OpenBSD: ssh-gss.h,v 1.16 2024/05/17 06:42:04 jsg Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. 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_GSS_H #define _SSH_GSS_H #ifdef GSSAPI #ifdef HAVE_GSSAPI_H #include #elif defined(HAVE_GSSAPI_GSSAPI_H) #include #endif #ifdef KRB5 # ifndef HEIMDAL # ifdef HAVE_GSSAPI_GENERIC_H # include # elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) # include # endif /* Old MIT Kerberos doesn't seem to define GSS_NT_HOSTBASED_SERVICE */ # if !HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE # define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name # endif /* !HAVE_DECL_GSS_C_NT_... */ # endif /* !HEIMDAL */ #endif /* KRB5 */ /* draft-ietf-secsh-gsskeyex-06 */ #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60 #define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61 #define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63 #define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64 #define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65 #define SSH2_MSG_USERAUTH_GSSAPI_MIC 66 #define SSH_GSS_OIDTYPE 0x06 typedef struct { char *filename; char *envvar; char *envval; void *data; } ssh_gssapi_ccache; typedef struct { gss_buffer_desc displayname; gss_buffer_desc exportedname; gss_cred_id_t creds; struct ssh_gssapi_mech_struct *mech; ssh_gssapi_ccache store; } ssh_gssapi_client; typedef struct ssh_gssapi_mech_struct { char *enc_name; char *name; gss_OID_desc oid; int (*dochild) (ssh_gssapi_client *); int (*userok) (ssh_gssapi_client *, char *); int (*localname) (ssh_gssapi_client *, char **); void (*storecreds) (ssh_gssapi_client *); } ssh_gssapi_mech; typedef struct { OM_uint32 major; /* both */ OM_uint32 minor; /* both */ gss_ctx_id_t context; /* both */ gss_name_t name; /* both */ gss_OID oid; /* client */ gss_cred_id_t creds; /* server */ gss_name_t client; /* server */ gss_cred_id_t client_creds; /* server */ } Gssctxt; extern ssh_gssapi_mech *supported_mechs[]; int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); void ssh_gssapi_set_oid(Gssctxt *, gss_OID); void ssh_gssapi_supported_oids(gss_OID_set *); 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 *); OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *, gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); OM_uint32 ssh_gssapi_getclient(Gssctxt *, ssh_gssapi_client *); void ssh_gssapi_error(Gssctxt *); 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(struct sshbuf *, const char *, const char *, const char *, const struct sshbuf *); int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); /* In the server */ OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); int ssh_gssapi_userok(char *name); 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 */ #endif /* _SSH_GSS_H */ openssh-10.0p1/PaxHeaders.10889/ssh-keygen.0100644 001750 001750 0000000003614775415623 0015312xustar0030 atime=1744182234.833813542 openssh-10.0p1/ssh-keygen.0010064400017500001750000001307311477541562300137020ustar00djmdjmSSH-KEYGEN(1) General Commands Manual SSH-KEYGEN(1) NAME ssh-keygen M-bM-^@M-^S OpenSSH authentication key utility SYNOPSIS ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile] [-m format] [-N new_passphrase] [-O option] [-t ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa] [-w provider] [-Z cipher] ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase] [-P old_passphrase] [-Z cipher] ssh-keygen -i [-f input_keyfile] [-m key_format] ssh-keygen -e [-f input_keyfile] [-m key_format] ssh-keygen -y [-f input_keyfile] ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase] ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile] ssh-keygen -B [-f input_keyfile] ssh-keygen -D pkcs11 ssh-keygen -F hostname [-lv] [-f known_hosts_file] ssh-keygen -H [-f known_hosts_file] ssh-keygen -K [-a rounds] [-w provider] ssh-keygen -R hostname [-f known_hosts_file] ssh-keygen -r hostname [-g] [-f input_keyfile] ssh-keygen -M generate [-O option] output_file ssh-keygen -M screen [-f input_file] [-O option] output_file ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider] [-n principals] [-O option] [-V validity_interval] [-z serial_number] file ... ssh-keygen -L [-f input_keyfile] ssh-keygen -A [-a rounds] [-f prefix_path] ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number] file ... ssh-keygen -Q [-l] -f krl_file file ... ssh-keygen -Y find-principals [-O option] -s signature_file -f allowed_signers_file ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file ssh-keygen -Y check-novalidate [-O option] -n namespace -s signature_file ssh-keygen -Y sign [-O option] -f key_file -n namespace file ... ssh-keygen -Y verify [-O option] -f allowed_signers_file -I signer_identity -n namespace -s signature_file [-r revocation_file] DESCRIPTION ssh-keygen generates, manages and converts authentication keys for ssh(1). ssh-keygen can create 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 Ed25519 key. 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/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519, ~/.ssh/id_ed25519_sk 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. ssh-keygen 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 M-bM-^@M-^\user@hostM-bM-^@M-^] when the key is created, but can be changed using the -c option. It is still possible for ssh-keygen to write the previously-used PEM format private keys using the -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 -p (change passphrase) flag. After a key is generated, ssh-keygen will ask where the keys should be placed to be activated. The options are as follows: -A Generate host keys of all default key types (rsa, ecdsa, and ed25519) if they do not already exist. The host keys are generated with the default key file path, an empty passphrase, default bits for the key type, and default comment. If -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 /etc/rc to generate new host keys. -a rounds When saving a private key, this option specifies the number of KDF (key derivation function, currently bcrypt_pbkdf(3)) rounds used. Higher numbers result in slower passphrase verification and increased resistance to brute-force password cracking (should the keys be stolen). The default is 16 rounds. -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 1024 bits and the default is 3072 bits. Generally, 3072 bits is considered sufficient. 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. ECDSA-SK, Ed25519 and Ed25519-SK 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. 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 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 a public 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 | [hostname]:port Search for the specified hostname (with optional port number) 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 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. See the CERTIFICATES section for details. -I certificate_identity Specify the key identity when signing a public key. 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-^]. -K Download resident keys from a FIDO authenticator. Public and private key files will be written to the current directory for each downloaded key. If multiple FIDO authenticators are attached, keys will be downloaded from the first touched authenticator. See the FIDO AUTHENTICATOR section for more information. -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 one or more certificates. -l Show fingerprint of specified public key file. ssh-keygen will try to find the matching public key file and prints its fingerprint. If combined with -v, a visual ASCII art representation of the key is supplied with the fingerprint. -M generate Generate candidate Diffie-Hellman Group Exchange (DH-GEX) parameters for eventual use by the M-bM-^@M-^Xdiffie-hellman-group-exchange-*M-bM-^@M-^Y key exchange methods. The numbers generated by this operation must be further screened before use. See the MODULI GENERATION section for more information. -M 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 /etc/moduli file. See the MODULI GENERATION section for more information. -m key_format Specify a key format for key generation, the -i (import), -e (export) conversion options, and the -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: M-bM-^@M-^\RFC4716M-bM-^@M-^] (RFC 4716/SSH2 public or private key), M-bM-^@M-^\PKCS8M-bM-^@M-^] (PKCS8 public or private key) or M-bM-^@M-^\PEMM-bM-^@M-^] (PEM public key). By default OpenSSH will write newly-generated private keys in its own format, but when converting public keys for export the default format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. Setting a format of M-bM-^@M-^\PEMM-bM-^@M-^] when generating or updating a supported private key type will cause the key to be stored in the legacy PEM private key format. -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. See the CERTIFICATES section for details. -O option Specify a key/value option. These are specific to the operation that ssh-keygen has been requested to perform. When signing certificates, one of the options listed in the CERTIFICATES section may be specified here. When performing moduli generation or screening, one of the options listed in the MODULI GENERATION section may be specified. When generating FIDO authenticator-backed keys, the options listed in the FIDO AUTHENTICATOR section may be specified. When performing signature-related options using the -Y flag, the following options are accepted: hashalg=algorithm Selects the hash algorithm to use for hashing the message to be signed. Valid algorithms are M-bM-^@M-^\sha256M-bM-^@M-^] and M-bM-^@M-^\sha512.M-bM-^@M-^] The default is M-bM-^@M-^\sha512.M-bM-^@M-^] print-pubkey Print the full public key to standard output after signature verification. verify-time=timestamp Specifies a time to use when validating signatures instead of the current time. The time may be specified as a date or time in the YYYYMMDD[Z] or in YYYYMMDDHHMM[SS][Z] formats. Dates and times will be interpreted in the current system time zone unless suffixed with a Z character, which causes them to be interpreted in the UTC time zone. When generating SSHFP DNS records from public keys using the -r flag, the following options are accepted: hashalg=algorithm Selects a hash algorithm to use when printing SSHFP records using the -D flag. Valid algorithms are M-bM-^@M-^\sha1M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The default is to print both. The -O option may be specified multiple times. -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. If the -l option is also specified then the contents of the KRL will be printed. -q Silence ssh-keygen. -R hostname | [hostname]:port Removes all keys belonging to the specified hostname (with optional port number) 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 ca_key Certify (sign) a public key using the specified CA key. 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 ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa Specifies the type of key to create. The possible values are M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ecdsa-skM-bM-^@M-^], M-bM-^@M-^\ed25519 (the default),M-bM-^@M-^] M-bM-^@M-^\ed25519-skM-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^]. 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 M-bM-^@M-^\ssh-rsaM-bM-^@M-^] (SHA1 signatures, not recommended), M-bM-^@M-^\rsa-sha2-256M-bM-^@M-^], and M-bM-^@M-^\rsa-sha2-512M-bM-^@M-^] (the default for RSA keys). -U When used in combination with -s or -Y sign, this option indicates that a CA key resides in a ssh-agent(1). See the CERTIFICATES section for more information. -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: M-bM-^@M-M-bM-^@M-" The string M-bM-^@M-^\alwaysM-bM-^@M-^] to indicate the certificate has no specified start time. M-bM-^@M-M-bM-^@M-" A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. M-bM-^@M-M-bM-^@M-" A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z. M-bM-^@M-M-bM-^@M-" A relative time before the current system time consisting of a minus sign followed by an interval in the format described in the TIME FORMATS section of sshd_config(5). M-bM-^@M-M-bM-^@M-" A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal number beginning with M-bM-^@M-^\0xM-bM-^@M-^]. The end time may be specified similarly to the start time: M-bM-^@M-M-bM-^@M-" The string M-bM-^@M-^\foreverM-bM-^@M-^] to indicate the certificate has no specified end time. M-bM-^@M-M-bM-^@M-" A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. M-bM-^@M-M-bM-^@M-" A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z. M-bM-^@M-M-bM-^@M-" A relative time after the current system time consisting of a plus sign followed by an interval in the format described in the TIME FORMATS section of sshd_config(5). M-bM-^@M-M-bM-^@M-" A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal number beginning with M-bM-^@M-^\0xM-bM-^@M-^]. For example: +52w1d Valid from now to 52 weeks and one day from now. -4w:+4w Valid from four weeks ago to four weeks from now. 20100101123000:20110101123000 Valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011. 20100101123000Z:20110101123000Z Similar, but interpreted in the UTC time zone rather than the system time zone. -1d:20110101 Valid from yesterday to midnight, January 1st, 2011. 0x1:0x2000000000 Valid from roughly early 1970 to May 2033. -1m:forever Valid from one minute ago and never expiring. -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 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. -Y find-principals Find the principal(s) associated with the public key of a signature, provided using the -s flag in an authorized signers file provided using the -f flag. The format of the allowed signers file is documented in the ALLOWED SIGNERS section below. If one or more matching principals are found, they are returned on standard output. -Y match-principals Find principal matching the principal name provided using the -I flag in the authorized signers file specified using the -f flag. If one or more matching principals are found, they are returned on standard output. -Y check-novalidate Checks that a signature generated using ssh-keygen -Y sign has a valid structure. This does not validate if a signature comes from an authorized signer. When testing a signature, ssh-keygen accepts a message on standard input and a signature namespace using -n. A file containing the corresponding signature must also be supplied using the -s flag. Successful testing of the signature is signalled by ssh-keygen returning a zero exit status. -Y sign Cryptographically sign a file or some data using an SSH key. When signing, ssh-keygen accepts zero or more files to sign on the command-line - if no files are specified then ssh-keygen will sign data presented on standard input. Signatures are written to the path of the input file with M-bM-^@M-^\.sigM-bM-^@M-^] appended, or to standard output if the message to be signed was read from standard input. The key used for signing is specified using the -f option and may refer to either a private key, or a public key with the private half available via 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 -n flag. Namespaces are arbitrary strings, and may include: M-bM-^@M-^\fileM-bM-^@M-^] for file signing, M-bM-^@M-^\emailM-bM-^@M-^] for email signing. For custom uses, it is recommended to use names following a NAMESPACE@YOUR.DOMAIN pattern to generate unambiguous namespaces. -Y verify Request to verify a signature generated using ssh-keygen -Y sign as described above. When verifying a signature, ssh-keygen accepts a message on standard input and a signature namespace using -n. A file containing the corresponding signature must also be supplied using the -s flag, along with the identity of the signer using -I and a list of allowed signers via the -f flag. The format of the allowed signers file is documented in the ALLOWED SIGNERS section below. A file containing revoked keys can be passed using the -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 ssh-keygen returning a zero exit status. -y This option will read a private OpenSSH format file and print an OpenSSH public key to stdout. -Z cipher Specifies the cipher to use for encryption when writing an OpenSSH-format private key file. The list of available ciphers may be obtained using "ssh -Q cipher". The default is M-bM-^@M-^\aes256-ctrM-bM-^@M-^]. -z serial_number Specifies a serial number to be embedded in the certificate to distinguish this certificate from others from the same CA. If the serial_number is prefixed with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the serial number will be incremented for each certificate signed on a single command-line. 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 -M generate option. The desired length of the primes may be specified by the -O bits option. For example: # ssh-keygen -M generate -O bits=2048 moduli-2048.candidates By default, the search for primes begins at a random point in the desired length range. This may be overridden using the -O start 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 -M screen option. In this mode ssh-keygen will read candidates from standard input (or a file specified using the -f option). For example: # ssh-keygen -M screen -f moduli-2048.candidates moduli-2048 By default, each candidate will be subjected to 100 primality tests. This may be overridden using the -O 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 -O generator 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. A number of options are available for moduli generation and screening via the -O flag: lines=number Exit after screening the specified number of lines while performing DH candidate screening. start-line=line-number Start screening at the specified line number while performing DH candidate screening. checkpoint=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. memory=mbytes Specify the amount of memory to use (in megabytes) when generating candidate moduli for DH-GEX. start=hex-value Specify start point (in hex) when generating candidate moduli for DH-GEX. generator=value Specify desired generator (in decimal) when testing candidate moduli for DH-GEX. 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 user_key.pub Similarly, it is possible for the CA key to be hosted in a ssh-agent(1). This is indicated by the -U flag and, again, the CA key must be identified by its public half. $ ssh-keygen -Us ca_key.pub -I key_id user_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 host_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. 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. critical:name[=contents] extension:name[=contents] Includes an arbitrary certificate critical option or extension. The specified name should include a domain suffix, e.g. M-bM-^@M-^\name@example.comM-bM-^@M-^]. If 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. 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. no-touch-required Do not require signatures made using this key include demonstration of user presence (e.g. by having the user touch the authenticator). This option only makes sense for the FIDO authenticator algorithms ecdsa-sk and ed25519-sk. 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. verify-required Require signatures made using this key indicate that the user was first verified, e.g. by PIN or on-token biometrics. This option only makes sense for the FIDO authenticator algorithms ecdsa-sk and ed25519-sk. At present, no standard options are valid for host keys. 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 the 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). Refer to those manual pages for details. FIDO AUTHENTICATOR ssh-keygen is able to generate FIDO authenticator-backed keys, after which they may be used much like any other key type supported by OpenSSH, so long as the hardware authenticator is attached when the keys are used. FIDO authenticators generally require the user to explicitly authorise operations by touching or tapping them. FIDO keys consist of two parts: a key handle part stored in the private key file on disk, and a per- device private key that is unique to each FIDO authenticator and that cannot be exported from the authenticator hardware. These are combined by the hardware at authentication time to derive the real key that is used to sign authentication challenges. Supported key types are ecdsa-sk and ed25519-sk. The options that are valid for FIDO keys are: application Override the default FIDO application/origin string of M-bM-^@M-^\ssh:M-bM-^@M-^]. This may be useful when generating host or domain-specific resident keys. The specified application string must begin with M-bM-^@M-^\ssh:M-bM-^@M-^]. challenge=path Specifies a path to a challenge string that will be passed to the FIDO authenticator 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). device Explicitly specify a fido(4) device to use, rather than letting the authenticator middleware select one. no-touch-required Indicate that the generated private key should not require touch events (user presence) when making signatures. Note that sshd(8) will refuse such signatures by default, unless overridden via an authorized_keys option. resident Indicate that the key handle should be stored on the FIDO authenticator itself. This makes it easier to use the authenticator on multiple computers. Resident keys may be supported on FIDO2 authenticators and typically require that a PIN be set on the authenticator prior to generation. Resident keys may be loaded off the authenticator using ssh-add(1). Storing both parts of a key on a FIDO authenticator increases the likelihood of an attacker being able to use a stolen authenticator device. 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. verify-required Indicate that this private key should require user verification for each signature. Not all FIDO authenticators support this option. Currently PIN authentication is the only supported verification method, but other methods may be supported in the future. write-attestation=path May be used at key generation time to record the attestation data returned from FIDO authenticators during key generation. This information is potentially sensitive. By default, this information is discarded. 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 including its SHA1 hash in the KRL. sha256: 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. hash: fingerprint Revokes a key using a fingerprint hash, as obtained from a sshd(8) authentication log message or the ssh-keygen -l flag. Only SHA256 fingerprints are supported here and resultant KRLs are not supported by OpenSSH versions prior to 7.9. 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 command line. 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. ALLOWED SIGNERS When verifying signatures, ssh-keygen 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 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 M-bM-^@M-^X#M-bM-^@M-^Y are ignored as comments. The principals field is a pattern-list (see PATTERNS in 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 -I option must match a principals pattern in order for the corresponding key to be considered acceptable for verification. 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 Indicates that this key is accepted as a certificate authority (CA) and that certificates signed by this CA may be accepted for verification. 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. valid-after=timestamp Indicates that the key is valid for use at or after the specified timestamp, which may be a date or time in the YYYYMMDD[Z] or YYYYMMDDHHMM[SS][Z] formats. Dates and times will be interpreted in the current system time zone unless suffixed with a Z character, which causes them to be interpreted in the UTC time zone. valid-before=timestamp Indicates that the key is valid for use at or before the specified timestamp. 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. An example allowed signers file: # 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... ENVIRONMENT 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. FILES ~/.ssh/id_ecdsa ~/.ssh/id_ecdsa_sk ~/.ssh/id_ed25519 ~/.ssh/id_ed25519_sk ~/.ssh/id_rsa Contains the 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 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_ecdsa.pub ~/.ssh/id_ecdsa_sk.pub ~/.ssh/id_ed25519.pub ~/.ssh/id_ed25519_sk.pub ~/.ssh/id_rsa.pub Contains the ECDSA, authenticator-hosted ECDSA, Ed25519, authenticator-hosted 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 7.6 November 27, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh-keygen.1100644 001750 001750 0000000003614775415623 0015313xustar0030 atime=1744182234.833813542 openssh-10.0p1/ssh-keygen.1010064400017500001750000001214471477541562300137070ustar00djmdjm.\" $OpenBSD: ssh-keygen.1,v 1.234 2024/11/27 13:00:23 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .Dd $Mdocdate: November 27 2024 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME .Nm ssh-keygen .Nd OpenSSH authentication key utility .Sh SYNOPSIS .Nm ssh-keygen .Op Fl q .Op Fl a Ar rounds .Op Fl b Ar bits .Op Fl C Ar comment .Op Fl f Ar output_keyfile .Op Fl m Ar format .Op Fl N Ar new_passphrase .Op Fl O Ar option .Op Fl t Cm ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa .Op Fl w Ar provider .Op Fl Z Ar cipher .Nm ssh-keygen .Fl p .Op Fl a Ar rounds .Op Fl f Ar keyfile .Op Fl m Ar format .Op Fl N Ar new_passphrase .Op Fl P Ar old_passphrase .Op Fl Z Ar cipher .Nm ssh-keygen .Fl i .Op Fl f Ar input_keyfile .Op Fl m Ar key_format .Nm ssh-keygen .Fl e .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 a Ar rounds .Op Fl C Ar comment .Op Fl f Ar keyfile .Op Fl P Ar passphrase .Nm ssh-keygen .Fl l .Op Fl v .Op Fl E Ar fingerprint_hash .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl B .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl D Ar pkcs11 .Nm ssh-keygen .Fl F Ar hostname .Op Fl lv .Op Fl f Ar known_hosts_file .Nm ssh-keygen .Fl H .Op Fl f Ar known_hosts_file .Nm ssh-keygen .Fl K .Op Fl a Ar rounds .Op Fl w Ar provider .Nm ssh-keygen .Fl R Ar hostname .Op Fl f Ar known_hosts_file .Nm ssh-keygen .Fl r Ar hostname .Op Fl g .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl M Cm generate .Op Fl O Ar option .Ar output_file .Nm ssh-keygen .Fl M Cm screen .Op Fl f Ar input_file .Op Fl O Ar option .Ar output_file .Nm ssh-keygen .Fl I Ar certificate_identity .Fl s Ar ca_key .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 .Op Fl z Ar serial_number .Ar .Nm ssh-keygen .Fl L .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl A .Op Fl a Ar rounds .Op Fl f Ar prefix_path .Nm ssh-keygen .Fl k .Fl f Ar krl_file .Op Fl u .Op Fl s Ar ca_public .Op Fl z Ar version_number .Ar .Nm ssh-keygen .Fl Q .Op Fl l .Fl f Ar krl_file .Ar .Nm ssh-keygen .Fl Y Cm find-principals .Op Fl O Ar option .Fl s Ar signature_file .Fl f Ar allowed_signers_file .Nm ssh-keygen .Fl Y Cm match-principals .Fl I Ar signer_identity .Fl f Ar allowed_signers_file .Nm ssh-keygen .Fl Y Cm check-novalidate .Op Fl O Ar option .Fl n Ar namespace .Fl s Ar signature_file .Nm ssh-keygen .Fl Y Cm sign .Op Fl O Ar option .Fl f Ar key_file .Fl n Ar namespace .Ar .Nm ssh-keygen .Fl Y Cm verify .Op Fl O Ar option .Fl f Ar allowed_signers_file .Fl I Ar signer_identity .Fl n Ar namespace .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 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 Ed25519 key. .Pp .Nm is also used to generate groups for use in Diffie-Hellman group exchange (DH-GEX). See the .Sx MODULI GENERATION section for details. .Pp Finally, .Nm can be used to generate and update Key Revocation Lists, and to test whether given keys have been revoked by one. See the .Sx KEY REVOCATION LISTS section for details. .Pp Normally each user wishing to use SSH with public key authentication runs this once to create the authentication key in .Pa ~/.ssh/id_ecdsa , .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, as seen in .Pa /etc/rc . .Pp 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 .Dq .pub 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 .Fl p option. .Pp 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 .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, .Nm will ask where the keys should be placed to be activated. .Pp The options are as follows: .Bl -tag -width Ds .It Fl A Generate host keys of all default key types (rsa, ecdsa, and ed25519) if they do not already exist. The host keys are generated 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 private key, this option specifies the number of KDF (key derivation function, currently .Xr bcrypt_pbkdf 3 ) rounds used. Higher numbers result in slower passphrase verification and increased resistance to brute-force password cracking (should the keys be stolen). The default is 16 rounds. .It Fl B Show the bubblebabble digest of specified private or public key file. .It Fl b Ar bits Specifies the number of bits in the key to create. For RSA keys, the minimum size is 1024 bits and the default is 3072 bits. Generally, 3072 bits is considered sufficient. For ECDSA keys, the .Fl 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. 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. 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 public keys provided by the PKCS#11 shared library .Ar pkcs11 . When used in combination with .Fl s , this option indicates that a CA key resides in a PKCS#11 token (see the .Sx CERTIFICATES section for details). .It Fl E Ar fingerprint_hash Specifies the hash algorithm used when displaying key fingerprints. Valid options are: .Dq md5 and .Dq sha256 . The default is .Dq sha256 . .It Fl e This option will read a private or public OpenSSH key file and 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 | [hostname]:port Search for the specified .Ar hostname (with optional port number) in a .Pa 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 .Fl H option to print found keys in a hashed format. .It Fl f Ar filename Specifies the filename of the key file. .It Fl g Use generic DNS format when printing fingerprint resource records using the .Fl r command. .It Fl H Hash a .Pa 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 .Nm ssh and .Nm 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. .It Fl h When signing a key, create a host certificate instead of a user certificate. See the .Sx CERTIFICATES section for details. .It Fl I Ar certificate_identity Specify the key identity when signing a public key. See the .Sx CERTIFICATES section for details. .It Fl i This option will read an unencrypted private (or public) key file in the format specified by the .Fl 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 .Dq RFC4716 . .It Fl K Download resident keys from a FIDO authenticator. Public and private key files will be written to the current directory for each downloaded key. If multiple FIDO authenticators are attached, keys will be downloaded from the first touched authenticator. See the .Sx FIDO AUTHENTICATOR section for more information. .It Fl k Generate a KRL file. In this mode, .Nm will generate a KRL file at the location specified via the .Fl 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 .Sx KEY REVOCATION LISTS section. .It Fl L Prints the contents of one or more certificates. .It Fl l Show fingerprint of specified public key file. .Nm will try to find the matching public key file and prints its fingerprint. If combined with .Fl v , 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 key generation, the .Fl i (import), .Fl e (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 (PKCS8 public or private key) or .Dq PEM (PEM public key). 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 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. See the .Sx CERTIFICATES section for details. .It Fl O Ar option Specify a key/value option. These are specific to the operation that .Nm has been requested to perform. .Pp When signing certificates, one of the options listed in the .Sx CERTIFICATES section may be specified here. .Pp When performing moduli generation or screening, one of the options listed in the .Sx MODULI GENERATION section may be specified. .Pp When generating FIDO authenticator-backed keys, the options listed in the .Sx FIDO AUTHENTICATOR section may be specified. .Pp When performing signature-related options using the .Fl Y flag, the following options are accepted: .Bl -tag -width Ds .It Cm hashalg Ns = Ns Ar algorithm Selects the hash algorithm to use for hashing the message to be signed. Valid algorithms are .Dq sha256 and .Dq sha512. The default is .Dq sha512. .It Cm print-pubkey Print the full public key to standard output after signature verification. .It Cm verify-time Ns = Ns Ar timestamp Specifies a time to use when validating signatures instead of the current time. The time may be specified as a date or time in the YYYYMMDD[Z] or in YYYYMMDDHHMM[SS][Z] formats. Dates and times will be interpreted in the current system time zone unless suffixed with a Z character, which causes them to be interpreted in the UTC time zone. .El .Pp When generating SSHFP DNS records from public keys using the .Fl r flag, the following options are accepted: .Bl -tag -width Ds .It Cm hashalg Ns = Ns Ar algorithm Selects a hash algorithm to use when printing SSHFP records using the .Fl D flag. Valid algorithms are .Dq sha1 and .Dq sha256 . The default is to print both. .El .Pp The .Fl O option may be specified multiple times. .It Fl P Ar passphrase Provides the (old) passphrase. .It Fl p Requests changing the passphrase of a private key file instead of creating a new private key. The program will prompt for the file containing the private key, for the old passphrase, and twice for the new passphrase. .It Fl Q Test whether keys have been revoked in a KRL. If the .Fl l option is also specified then the contents of the KRL will be printed. .It Fl q Silence .Nm ssh-keygen . .It Fl R Ar hostname | [hostname]:port Removes all keys belonging to the specified .Ar hostname (with optional port number) from a .Pa known_hosts file. This option is useful to delete hashed hosts (see the .Fl H option above). .It Fl r Ar hostname Print the SSHFP fingerprint resource record named .Ar hostname for the specified public key file. .It Fl s Ar ca_key Certify (sign) a public key using the specified CA key. See the .Sx CERTIFICATES section for details. .Pp When generating a KRL, .Fl s specifies a path to a CA public key file used to revoke certificates directly by key ID or serial number. See the .Sx KEY REVOCATION LISTS section for details. .It Fl t Cm ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa Specifies the type of key to create. The possible values are .Dq ecdsa , .Dq ecdsa-sk , .Dq ed25519 (the default), .Dq ed25519-sk , or .Dq rsa . .Pp This flag may also be used to specify the desired signature type when signing certificates using an RSA CA key. The available RSA signature variants are .Dq ssh-rsa (SHA1 signatures, not recommended), .Dq rsa-sha2-256 , and .Dq rsa-sha2-512 (the default for RSA keys). .It Fl U When used in combination with .Fl s or .Fl Y Cm sign , this option indicates that a CA key resides in a .Xr ssh-agent 1 . See the .Sx CERTIFICATES section for more information. .It Fl u Update a KRL. When specified with .Fl k , keys listed via the command line are added to the existing KRL rather than a new KRL being created. .It Fl V Ar validity_interval Specify a validity interval when signing a certificate. A validity interval may consist of a single time, indicating that the certificate is valid beginning now and expiring at that time, or may consist of two times separated by a colon to indicate an explicit time interval. .Pp The start time may be specified as: .Bl -bullet -compact .It The string .Dq always to indicate the certificate has no specified start time. .It A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. .It A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z. .It A relative time before the current system time consisting of a minus sign followed by an interval in the format described in the TIME FORMATS section of .Xr sshd_config 5 . .It A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal number beginning with .Dq 0x . .El .Pp The end time may be specified similarly to the start time: .Bl -bullet -compact .It The string .Dq forever to indicate the certificate has no specified end time. .It A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. .It A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z. .It A relative time after the current system time consisting of a plus sign followed by an interval in the format described in the TIME FORMATS section of .Xr sshd_config 5 . .It A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal number beginning with .Dq 0x . .El .Pp For example: .Bl -tag -width Ds .It +52w1d Valid from now to 52 weeks and one day from now. .It -4w:+4w Valid from four weeks ago to four weeks from now. .It 20100101123000:20110101123000 Valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011. .It 20100101123000Z:20110101123000Z Similar, but interpreted in the UTC time zone rather than the system time zone. .It -1d:20110101 Valid from yesterday to midnight, January 1st, 2011. .It 0x1:0x2000000000 Valid from roughly early 1970 to May 2033. .It -1m:forever Valid from one minute ago and never expiring. .El .It Fl v Verbose mode. Causes .Nm to print debugging messages about its progress. This is helpful for debugging moduli generation. Multiple .Fl v options increase the verbosity. The maximum is 3. .It Fl w Ar provider Specifies a path to a library that will be used when creating FIDO authenticator-hosted keys, overriding the default of using the internal USB HID support. .It Fl Y Cm find-principals Find the principal(s) associated with the public key of a signature, provided using the .Fl s flag in an authorized signers file provided using the .Fl f flag. The format of the allowed signers file is documented in the .Sx ALLOWED SIGNERS section below. If one or more matching principals are found, they are returned on standard output. .It Fl Y Cm match-principals Find principal matching the principal name provided using the .Fl I flag in the authorized signers file specified using the .Fl f flag. 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 an SSH key. When signing, .Nm accepts zero or more files to sign on the command-line - if no files are specified then .Nm will sign data presented on standard input. Signatures are written to the path of the input file with .Dq .sig appended, or to standard output if the message to be signed was read from standard input. .Pp The key used for signing is specified using the .Fl f option and may refer to either a private key, or a public key with the private half available via .Xr ssh-agent 1 . An additional signature namespace, used to prevent signature confusion across different domains of use (e.g. file signing vs email signing) must be provided via the .Fl n flag. Namespaces are arbitrary strings, and may include: .Dq file for file signing, .Dq email for email signing. For custom uses, it is recommended to use names following a NAMESPACE@YOUR.DOMAIN pattern to generate unambiguous namespaces. .It Fl Y Cm verify Request to verify a signature generated using .Nm .Fl Y Cm sign as described above. When verifying a signature, .Nm accepts a message on standard input and a signature namespace using .Fl n . A file containing the corresponding signature must also be supplied using the .Fl s flag, along with the identity of the signer using .Fl I and a list of allowed signers via the .Fl f flag. The format of the allowed signers file is documented in the .Sx ALLOWED SIGNERS section below. A file containing revoked keys can be passed using the .Fl r flag. The revocation file may be a KRL or a one-per-line list of public keys. Successful verification by an authorized signer is signalled by .Nm returning a zero exit status. .It Fl y This option will read a private OpenSSH format file and print an OpenSSH public key to stdout. .It Fl Z Ar cipher Specifies the cipher to use for encryption when writing an OpenSSH-format private key file. The list of available ciphers may be obtained using .Qq ssh -Q cipher . The default is .Dq aes256-ctr . .It Fl z Ar serial_number Specifies a serial number to be embedded in the certificate to distinguish this certificate from others from the same CA. If the .Ar serial_number is prefixed with a .Sq + character, then the serial number will be incremented for each certificate signed on a single command-line. The default serial number is zero. .Pp When generating a KRL, the .Fl z flag is used to specify a KRL version number. .El .Sh MODULI GENERATION .Nm may be used to generate groups for the Diffie-Hellman Group Exchange (DH-GEX) protocol. Generating these groups is a two-step process: first, candidate primes are generated using a fast, but memory intensive process. These candidate primes are then tested for suitability (a CPU-intensive process). .Pp Generation of primes is performed using the .Fl M Cm generate option. The desired length of the primes may be specified by the .Fl O Cm bits option. For example: .Pp .Dl # ssh-keygen -M generate -O bits=2048 moduli-2048.candidates .Pp By default, the search for primes begins at a random point in the desired length range. This may be overridden using the .Fl O Cm start option, which specifies a different start point (in hex). .Pp Once a set of candidates have been generated, they must be screened for suitability. This may be performed using the .Fl M Cm screen option. In this mode .Nm will read candidates from standard input (or a file specified using the .Fl f option). For example: .Pp .Dl # ssh-keygen -M screen -f moduli-2048.candidates moduli-2048 .Pp By default, each candidate will be subjected to 100 primality tests. This may be overridden using the .Fl O Cm prime-tests option. The DH generator value will be chosen automatically for the prime under consideration. If a specific generator is desired, it may be requested using the .Fl O Cm generator option. Valid generator values are 2, 3, and 5. .Pp Screened DH groups may be installed in .Pa /etc/moduli . It is important that this file contains moduli of a range of bit lengths. .Pp A number of options are available for moduli generation and screening via the .Fl O flag: .Bl -tag -width Ds .It Ic lines Ns = Ns Ar number Exit after screening the specified number of lines while performing DH candidate screening. .It Ic start-line Ns = Ns Ar line-number Start screening at the specified line number while performing DH candidate screening. .It Ic checkpoint Ns = Ns Ar filename Write the last line processed to the specified file while performing DH candidate screening. This will be used to skip lines in the input file that have already been processed if the job is restarted. .It Ic memory Ns = Ns Ar mbytes Specify the amount of memory to use (in megabytes) when generating candidate moduli for DH-GEX. .It Ic start Ns = Ns Ar hex-value Specify start point (in hex) when generating candidate moduli for DH-GEX. .It Ic generator Ns = Ns Ar value Specify desired generator (in decimal) when testing candidate moduli for DH-GEX. .El .Sh CERTIFICATES .Nm supports signing of keys to produce certificates that may be used for user or host authentication. Certificates consist of a public key, some identity information, zero or more principal (user or host) names and a set of options that are signed by a Certification Authority (CA) key. Clients or servers may then trust only the CA key and verify its signature on a certificate rather than trusting many user/host keys. Note that OpenSSH certificates are a different, and much simpler, format to the X.509 certificates used in .Xr ssl 8 . .Pp .Nm supports two types of certificates: user and host. User certificates authenticate users to servers, whereas host certificates authenticate server hosts to users. To generate a user certificate: .Pp .Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub .Pp The resultant certificate will be placed in .Pa /path/to/user_key-cert.pub . A host certificate requires the .Fl h option: .Pp .Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub .Pp The host certificate will be output to .Pa /path/to/host_key-cert.pub . .Pp It is possible to sign using a CA key stored in a PKCS#11 token by providing the token library using .Fl D and identifying the CA key by providing its public half as an argument to .Fl s : .Pp .Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub .Pp Similarly, it is possible for the CA key to be hosted in a .Xr ssh-agent 1 . This is indicated by the .Fl U flag and, again, the CA key must be identified by its public half. .Pp .Dl $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub .Pp In all cases, .Ar key_id is a "key identifier" that is logged by the server when the certificate is used for authentication. .Pp Certificates may be limited to be valid for a set of principal (user/host) names. By default, generated certificates are valid for all users or hosts. To generate a certificate for a specified set of principals: .Pp .Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub .Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub" .Pp Additional limitations on the validity and use of user certificates may be specified through certificate options. A certificate option may disable features of the SSH session, may be valid only when presented from particular source addresses or may force the use of a specific command. .Pp 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 include demonstration of user presence (e.g. by having the user touch the authenticator). This option only makes sense for the FIDO authenticator algorithms .Cm ecdsa-sk and .Cm ed25519-sk . .Pp .It Ic source-address Ns = Ns Ar address_list Restrict the source addresses from which the certificate is considered valid. The .Ar address_list is a comma-separated list of one or more address/netmask pairs in CIDR format. .Pp .It Ic verify-required Require signatures made using this key indicate that the user was first verified, e.g. by PIN or on-token biometrics. This option only makes sense for the FIDO authenticator algorithms .Cm ecdsa-sk and .Cm ed25519-sk . .El .Pp At present, no standard options are valid for host keys. .Pp Finally, certificates may be defined with a validity lifetime. The .Fl 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 the .Ux Epoch to the distant future. .Pp For certificates to be used for user or host authentication, the CA public key must be trusted by .Xr sshd 8 or .Xr ssh 1 . Refer to those manual pages for details. .Sh FIDO AUTHENTICATOR .Nm is able to generate FIDO authenticator-backed keys, after which they may be used much like any other key type supported by OpenSSH, so long as the hardware authenticator is attached when the keys are used. FIDO authenticators generally require the user to explicitly authorise operations by touching or tapping them. FIDO keys consist of two parts: a key handle part stored in the private key file on disk, and a per-device private key that is unique to each FIDO authenticator and that cannot be exported from the authenticator hardware. These are combined by the hardware at authentication time to derive the real key that is used to sign authentication challenges. Supported key types are .Cm ecdsa-sk and .Cm ed25519-sk . .Pp The options that are valid for FIDO keys are: .Bl -tag -width Ds .It Cm application Override the default FIDO application/origin string of .Dq ssh: . This may be useful when generating host or domain-specific resident keys. The specified application string must begin with .Dq ssh: . .It Cm challenge Ns = Ns Ar path Specifies a path to a challenge string that will be passed to the FIDO authenticator 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 authenticator middleware select one. .It Cm no-touch-required Indicate that the generated private key should not require touch events (user presence) when making signatures. Note that .Xr sshd 8 will refuse such signatures by default, unless overridden via an authorized_keys option. .It Cm resident Indicate that the key handle should be stored on the FIDO authenticator itself. This makes it easier to use the authenticator on multiple computers. Resident keys may be supported on FIDO2 authenticators and typically require that a PIN be set on the authenticator prior to generation. Resident keys may be loaded off the authenticator using .Xr ssh-add 1 . Storing both parts of a key on a FIDO authenticator increases the likelihood of an attacker being able to use a stolen authenticator device. .It Cm user A username to be associated with a resident key, overriding the empty default username. Specifying a username may be useful when generating multiple resident keys for the same application name. .It Cm verify-required Indicate that this private key should require user verification for each signature. Not all FIDO authenticators support this option. Currently PIN authentication is the only supported verification method, but other methods may be supported in the future. .It Cm write-attestation Ns = Ns Ar path May be used at key generation time to record the attestation data returned from FIDO authenticators during key generation. This information is potentially sensitive. By default, this information is discarded. .El .Sh KEY REVOCATION LISTS .Nm 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. .Pp KRLs may be generated using the .Fl 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). .Pp 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. .Bl -tag -width Ds .It Cm serial : Ar serial_number Ns Op - Ns Ar 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 .Nm command line using the .Fl s option. .It Cm id : Ar key_id Revokes a certificate with the specified key ID string. The CA key must have been specified on the .Nm command line using the .Fl s option. .It Cm key : Ar public_key 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 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 .Fl u flag in addition to .Fl k . When this option is specified, keys listed via the command line are merged into the KRL, adding to those already there. .Pp 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 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 ALLOWED SIGNERS When verifying signatures, .Nm 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 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 Ns = Ns "namespace-list" Specifies a pattern-list of namespaces that are accepted for this key. If this option is present, the signature namespace embedded in the signature object and presented on the verification command-line must match the specified list before the key will be considered acceptable. .It Cm valid-after Ns = Ns "timestamp" Indicates that the key is valid for use at or after the specified timestamp, which may be a date or time in the YYYYMMDD[Z] or YYYYMMDDHHMM[SS][Z] formats. Dates and times will be interpreted in the current system time zone unless suffixed with a Z character, which causes them to be interpreted in the UTC time zone. .It Cm valid-before Ns = Ns "timestamp" Indicates that the key is valid for use at or before the specified timestamp. .El .Pp When verifying signatures made by certificates, the expected principal 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_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 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 used to encrypt the private part of this file using 128-bit AES. This file is not automatically accessed by .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. .Pp .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 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 where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. .Pp .It Pa /etc/moduli Contains Diffie-Hellman groups used for DH-GEX. The file format is described in .Xr moduli 5 . .El .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , .Xr moduli 5 , .Xr sshd 8 .Rs .%R RFC 4716 .%T "The Secure Shell (SSH) Public Key File Format" .%D 2006 .Re .Sh AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song removed many bugs, re-added newer features and created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. openssh-10.0p1/PaxHeaders.10889/ssh-keygen.c100644 001750 001750 0000000003414775415623 0015373xustar0028 atime=1744182234.8416263 openssh-10.0p1/ssh-keygen.c010064400017500001750000003276071477541562300137770ustar00djmdjm/* $OpenBSD: ssh-keygen.c,v 1.477 2024/12/04 14:24:20 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland * All rights reserved * Identity and host key generation and maintenance. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #ifdef WITH_OPENSSL #include #include #include "openbsd-compat/openssl-compat.h" #endif #ifdef HAVE_STDINT_H # include #endif #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "sshkey.h" #include "authfile.h" #include "sshbuf.h" #include "pathnames.h" #include "log.h" #include "misc.h" #include "match.h" #include "hostfile.h" #include "dns.h" #include "ssh.h" #include "ssh2.h" #include "ssherr.h" #include "ssh-pkcs11.h" #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 */ #include "cipher.h" #define DEFAULT_KEY_TYPE_NAME "ed25519" /* * 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. */ #define DEFAULT_BITS 3072 #define DEFAULT_BITS_DSA 1024 #define DEFAULT_BITS_ECDSA 256 static int quiet = 0; /* Flag indicating that we just want to see the key fingerprint */ static int print_fingerprint = 0; static int print_bubblebabble = 0; /* Hash algorithm to use for fingerprints. */ static int fingerprint_hash = SSH_FP_HASH_DEFAULT; /* The identity file name, given on the command line or entered by the user. */ static char identity_file[PATH_MAX]; static int have_identity = 0; /* This is set to the passphrase if given on the command line. */ static char *identity_passphrase = NULL; /* This is set to the new passphrase if given on the command line. */ static char *identity_new_passphrase = NULL; /* Key type when certifying */ static u_int cert_key_type = SSH2_CERT_TYPE_USER; /* "key ID" of signed key */ static char *cert_key_id = NULL; /* Comma-separated list of principal names for certifying keys */ static char *cert_principals = NULL; /* Validity period for certificates */ 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_NO_REQUIRE_USER_PRESENCE (1<<5) #define CERTOPT_REQUIRE_VERIFY (1<<6) #define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \ CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC) static u_int32_t certflags_flags = CERTOPT_DEFAULT; static char *certflags_command = NULL; static char *certflags_src_addr = NULL; /* Arbitrary extensions specified by user */ struct cert_ext { char *key; char *val; int crit; }; static struct cert_ext *cert_ext; static size_t ncert_ext; /* Conversion to/from various formats */ enum { FMT_RFC4716, FMT_PKCS8, FMT_PEM } convert_format = FMT_RFC4716; static char *key_type_name = NULL; /* Load key from this PKCS#11 provider */ static char *pkcs11provider = NULL; /* FIDO/U2F provider to use */ static char *sk_provider = NULL; /* Format for writing private keys */ static int private_key_format = SSHKEY_PRIVATE_OPENSSH; /* Cipher for new-format private keys */ static char *openssh_format_cipher = NULL; /* Number of KDF rounds to derive new format keys. */ static int rounds = 0; /* argv0 */ extern char *__progname; 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) { if (type == KEY_UNSPEC) fatal("unknown key type %s", key_type_name); if (*bitsp == 0) { #ifdef WITH_OPENSSL int nid; switch(type) { case KEY_DSA: *bitsp = DEFAULT_BITS_DSA; break; case KEY_ECDSA: if (name != NULL && (nid = sshkey_ecdsa_nid_from_name(name)) > 0) *bitsp = sshkey_curve_nid_to_bits(nid); if (*bitsp == 0) *bitsp = DEFAULT_BITS_ECDSA; break; case KEY_RSA: *bitsp = DEFAULT_BITS; break; } #endif } #ifdef WITH_OPENSSL switch (type) { case KEY_DSA: if (*bitsp != 1024) fatal("Invalid DSA key length: must be 1024 bits"); break; case KEY_RSA: if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE) fatal("Invalid RSA key length: minimum is %d bits", 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) #ifdef OPENSSL_HAS_NISTP521 fatal("Invalid ECDSA key length: valid lengths are " "256, 384 or 521 bits"); #else fatal("Invalid ECDSA key length: valid lengths are " "256 or 384 bits"); #endif } #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) { char buf[1024]; char *name = NULL; if (key_type_name == NULL) name = _PATH_SSH_CLIENT_ID_ED25519; else { switch (sshkey_type_from_shortname(key_type_name)) { #ifdef WITH_DSA case KEY_DSA_CERT: case KEY_DSA: name = _PATH_SSH_CLIENT_ID_DSA; break; #endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA_CERT: case KEY_ECDSA: 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: name = _PATH_SSH_CLIENT_ID_RSA; break; case KEY_ED25519: case KEY_ED25519_CERT: name = _PATH_SSH_CLIENT_ID_ED25519; break; case KEY_ED25519_SK: case KEY_ED25519_SK_CERT: name = _PATH_SSH_CLIENT_ID_ED25519_SK; break; case KEY_XMSS: case KEY_XMSS_CERT: name = _PATH_SSH_CLIENT_ID_XMSS; break; default: fatal("bad key type"); } } 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'; if (strcmp(buf, "") != 0) strlcpy(identity_file, buf, sizeof(identity_file)); have_identity = 1; } static struct sshkey * load_identity(const char *filename, char **commentp) { char *prompt, *pass; struct sshkey *prv; int r; if (commentp != NULL) *commentp = NULL; if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0) return prv; if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) fatal_r(r, "Load key \"%s\"", filename); if (identity_passphrase) pass = xstrdup(identity_passphrase); else { xasprintf(&prompt, "Enter passphrase for \"%s\": ", filename); pass = read_passphrase(prompt, RP_ALLOW_STDIN); free(prompt); } r = sshkey_load_private(filename, pass, &prv, commentp); freezero(pass, strlen(pass)); if (r != 0) fatal_r(r, "Load key \"%s\"", filename); return prv; } #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----" #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----" #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb #ifdef WITH_OPENSSL static void do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) { struct sshbuf *b; char comment[61], *b64; int r; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshkey_putb(k, b)) != 0) fatal_fr(r, "put key"); if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL) fatal_f("sshbuf_dtob64_string failed"); /* 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%s", comment, b64); fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); free(b64); exit(0); } static void do_convert_to_pkcs8(struct sshkey *k) { switch (sshkey_type_plain(k->type)) { case KEY_RSA: if (!PEM_write_RSA_PUBKEY(stdout, EVP_PKEY_get0_RSA(k->pkey))) fatal("PEM_write_RSA_PUBKEY failed"); break; #ifdef WITH_DSA case KEY_DSA: if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) fatal("PEM_write_DSA_PUBKEY failed"); break; #endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if (!PEM_write_EC_PUBKEY(stdout, EVP_PKEY_get0_EC_KEY(k->pkey))) fatal("PEM_write_EC_PUBKEY failed"); break; #endif default: fatal_f("unsupported key type %s", sshkey_type(k)); } exit(0); } static void do_convert_to_pem(struct sshkey *k) { switch (sshkey_type_plain(k->type)) { case KEY_RSA: if (!PEM_write_RSAPublicKey(stdout, EVP_PKEY_get0_RSA(k->pkey))) fatal("PEM_write_RSAPublicKey failed"); break; #ifdef WITH_DSA case KEY_DSA: if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) fatal("PEM_write_DSA_PUBKEY failed"); break; #endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if (!PEM_write_EC_PUBKEY(stdout, EVP_PKEY_get0_EC_KEY(k->pkey))) fatal("PEM_write_EC_PUBKEY failed"); break; #endif default: fatal_f("unsupported key type %s", sshkey_type(k)); } exit(0); } static void do_convert_to(struct passwd *pw) { struct sshkey *k; struct stat st; int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); 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, NULL); switch (convert_format) { case FMT_RFC4716: do_convert_to_ssh2(pw, k); break; case FMT_PKCS8: do_convert_to_pkcs8(k); break; case FMT_PEM: do_convert_to_pem(k); break; default: fatal_f("unknown key format %d", convert_format); } exit(0); } /* * This is almost exactly the bignum1 encoding, but with 32 bit for length * instead of 16. */ static void buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value) { u_int bytes, bignum_bits; int r; if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0) fatal_fr(r, "parse"); bytes = (bignum_bits + 7) / 8; if (sshbuf_len(b) < bytes) fatal_f("input buffer too small: need %d have %zu", bytes, sshbuf_len(b)); if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL) fatal_f("BN_bin2bn failed"); if ((r = sshbuf_consume(b, bytes)) != 0) fatal_fr(r, "consume"); } static struct sshkey * do_convert_private_ssh2(struct sshbuf *b) { struct sshkey *key = NULL; char *type, *cipher; const char *alg = NULL; u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; int r, rlen, ktype; u_int magic, i1, i2, i3, i4; size_t slen; u_long e; #ifdef WITH_DSA BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; #endif BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL; RSA *rsa = NULL; if ((r = sshbuf_get_u32(b, &magic)) != 0) fatal_fr(r, "parse magic"); if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); return NULL; } if ((r = sshbuf_get_u32(b, &i1)) != 0 || (r = sshbuf_get_cstring(b, &type, NULL)) != 0 || (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 || (r = sshbuf_get_u32(b, &i2)) != 0 || (r = sshbuf_get_u32(b, &i3)) != 0 || (r = sshbuf_get_u32(b, &i4)) != 0) fatal_fr(r, "parse"); debug("ignore (%d %d %d %d)", i1, i2, i3, i4); if (strcmp(cipher, "none") != 0) { error("unsupported cipher %s", cipher); free(cipher); free(type); return NULL; } free(cipher); if (strstr(type, "rsa")) { ktype = KEY_RSA; #ifdef WITH_DSA } else if (strstr(type, "dsa")) { ktype = KEY_DSA; #endif } else { free(type); return NULL; } if ((key = sshkey_new(ktype)) == NULL) fatal("sshkey_new failed"); free(type); switch (key->type) { #ifdef WITH_DSA case KEY_DSA: if ((dsa_p = BN_new()) == NULL || (dsa_q = BN_new()) == NULL || (dsa_g = BN_new()) == NULL || (dsa_pub_key = BN_new()) == NULL || (dsa_priv_key = BN_new()) == NULL) fatal_f("BN_new"); buffer_get_bignum_bits(b, dsa_p); buffer_get_bignum_bits(b, dsa_g); buffer_get_bignum_bits(b, dsa_q); buffer_get_bignum_bits(b, dsa_pub_key); buffer_get_bignum_bits(b, dsa_priv_key); if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) fatal_f("DSA_set0_pqg failed"); dsa_p = dsa_q = dsa_g = NULL; /* transferred */ if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key)) fatal_f("DSA_set0_key failed"); dsa_pub_key = dsa_priv_key = NULL; /* transferred */ break; #endif case KEY_RSA: if ((r = sshbuf_get_u8(b, &e1)) != 0 || (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0)) fatal_fr(r, "parse RSA"); e = e1; debug("e %lx", e); if (e < 30) { e <<= 8; e += e2; debug("e %lx", e); e <<= 8; e += e3; debug("e %lx", e); } if ((rsa_e = BN_new()) == NULL) fatal_f("BN_new"); if (!BN_set_word(rsa_e, e)) { BN_clear_free(rsa_e); sshkey_free(key); return NULL; } 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_f("BN_new"); buffer_get_bignum_bits(b, rsa_d); buffer_get_bignum_bits(b, rsa_n); buffer_get_bignum_bits(b, rsa_iqmp); buffer_get_bignum_bits(b, rsa_q); buffer_get_bignum_bits(b, rsa_p); if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q, rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0) fatal_fr(r, "generate RSA CRT parameters"); if ((key->pkey = EVP_PKEY_new()) == NULL) fatal_f("EVP_PKEY_new failed"); if ((rsa = RSA_new()) == NULL) fatal_f("RSA_new failed"); if (!RSA_set0_key(rsa, rsa_n, rsa_e, rsa_d)) fatal_f("RSA_set0_key failed"); rsa_n = rsa_e = rsa_d = NULL; /* transferred */ if (!RSA_set0_factors(rsa, rsa_p, rsa_q)) fatal_f("RSA_set0_factors failed"); rsa_p = rsa_q = NULL; /* transferred */ if (RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp) != 1) fatal_f("RSA_set0_crt_params failed"); rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) fatal_f("EVP_PKEY_set1_RSA failed"); RSA_free(rsa); alg = "rsa-sha2-256"; break; } rlen = sshbuf_len(b); if (rlen != 0) error_f("remaining bytes in key blob %d", rlen); /* try the key */ if ((r = sshkey_sign(key, &sig, &slen, data, sizeof(data), alg, NULL, NULL, 0)) != 0) error_fr(r, "signing with converted key failed"); else if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), alg, 0, NULL)) != 0) error_fr(r, "verification with converted key failed"); if (r != 0) { sshkey_free(key); free(sig); return NULL; } free(sig); return key; } static int get_line(FILE *fp, char *line, size_t len) { int c; size_t pos = 0; line[0] = '\0'; while ((c = fgetc(fp)) != EOF) { 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) fatal("unget: %s", strerror(errno)); return pos; case '\n': return pos; } line[pos++] = c; line[pos] = '\0'; } /* We reached EOF */ return -1; } static void do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private) { int r, blen, escaped = 0; u_int len; char line[1024]; 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'; while ((blen = get_line(fp, line, sizeof(line))) != -1) { if (blen > 0 && line[blen - 1] == '\\') escaped++; if (strncmp(line, "----", 4) == 0 || strstr(line, ": ") != NULL) { if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) *private = 1; if (strstr(line, " END ") != NULL) { break; } /* fprintf(stderr, "ignore: %s", line); */ continue; } if (escaped) { escaped--; /* fprintf(stderr, "escaped: %s", line); */ continue; } strlcat(encoded, line, sizeof(encoded)); } len = strlen(encoded); if (((len % 4) == 3) && (encoded[len-1] == '=') && (encoded[len-2] == '=') && (encoded[len-3] == '=')) encoded[len-3] = '\0'; if ((r = sshbuf_b64tod(buf, encoded)) != 0) fatal_fr(r, "base64 decode"); if (*private) { if ((*k = do_convert_private_ssh2(buf)) == NULL) fatal_f("private key conversion failed"); } else if ((r = sshkey_fromb(buf, k)) != 0) fatal_fr(r, "parse key"); sshbuf_free(buf); fclose(fp); } static void do_convert_from_pkcs8(struct sshkey **k, int *private) { EVP_PKEY *pubkey; FILE *fp; if ((fp = fopen(identity_file, "r")) == NULL) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) { fatal_f("%s is not a recognised public key format", identity_file); } fclose(fp); switch (EVP_PKEY_base_id(pubkey)) { case EVP_PKEY_RSA: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) fatal("sshkey_new failed"); (*k)->type = KEY_RSA; (*k)->pkey = pubkey; pubkey = NULL; break; #ifdef WITH_DSA case EVP_PKEY_DSA: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) fatal("sshkey_new failed"); (*k)->type = KEY_DSA; (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); break; #endif #ifdef OPENSSL_HAS_ECC case EVP_PKEY_EC: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) fatal("sshkey_new failed"); if (((*k)->ecdsa_nid = sshkey_ecdsa_fixup_group(pubkey)) == -1) fatal("sshkey_ecdsa_fixup_group failed"); (*k)->type = KEY_ECDSA; (*k)->pkey = pubkey; pubkey = NULL; break; #endif default: fatal_f("unsupported pubkey type %d", EVP_PKEY_base_id(pubkey)); } EVP_PKEY_free(pubkey); return; } static void do_convert_from_pem(struct sshkey **k, int *private) { FILE *fp; RSA *rsa; if ((fp = fopen(identity_file, "r")) == NULL) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) fatal("sshkey_new failed"); if (((*k)->pkey = EVP_PKEY_new()) == NULL) fatal("EVP_PKEY_new failed"); (*k)->type = KEY_RSA; if (EVP_PKEY_set1_RSA((*k)->pkey, rsa) != 1) fatal("EVP_PKEY_set1_RSA failed"); RSA_free(rsa); fclose(fp); return; } fatal_f("unrecognised raw private key format"); } static void do_convert_from(struct passwd *pw) { struct sshkey *k = NULL; int r, private = 0, ok = 0; struct stat st; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); if (stat(identity_file, &st) == -1) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); switch (convert_format) { case FMT_RFC4716: do_convert_from_ssh2(pw, &k, &private); break; case FMT_PKCS8: do_convert_from_pkcs8(&k, &private); break; case FMT_PEM: do_convert_from_pem(&k, &private); break; default: fatal_f("unknown key format %d", convert_format); } if (!private) { if ((r = sshkey_write(k, stdout)) == 0) ok = 1; if (ok) fprintf(stdout, "\n"); } else { switch (k->type) { #ifdef WITH_DSA case KEY_DSA: ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL); break; #endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: ok = PEM_write_ECPrivateKey(stdout, EVP_PKEY_get0_EC_KEY(k->pkey), NULL, NULL, 0, NULL, NULL); break; #endif case KEY_RSA: ok = PEM_write_RSAPrivateKey(stdout, EVP_PKEY_get0_RSA(k->pkey), NULL, NULL, 0, NULL, NULL); break; default: fatal_f("unsupported key type %s", sshkey_type(k)); } } if (!ok) fatal("key write failed"); sshkey_free(k); exit(0); } #endif static void 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) == -1) fatal("%s: %s", identity_file, strerror(errno)); prv = load_identity(identity_file, &comment); if ((r = sshkey_write(prv, stdout)) != 0) fatal_fr(r, "write key"); if (comment != NULL && *comment != '\0') fprintf(stdout, " %s", comment); fprintf(stdout, "\n"); if (sshkey_is_sk(prv)) { debug("sk_application: \"%s\", sk_flags 0x%02x", prv->sk_application, prv->sk_flags); } sshkey_free(prv); free(comment); exit(0); } static void do_download(struct passwd *pw) { #ifdef ENABLE_PKCS11 struct sshkey **keys = NULL; int i, nkeys; enum sshkey_fp_rep rep; int fptype; char *fp, *ra, **comments = NULL; fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; pkcs11_init(1); nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys, &comments); if (nkeys <= 0) fatal("cannot read public key from pkcs11"); for (i = 0; i < nkeys; i++) { if (print_fingerprint) { fp = sshkey_fingerprint(keys[i], fptype, rep); ra = sshkey_fingerprint(keys[i], fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal_f("sshkey_fingerprint fail"); printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]), fp, sshkey_type(keys[i])); if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) printf("%s\n", ra); free(ra); free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ 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); #else fatal("no pkcs11 support"); #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 fingerprint_one_key(const struct sshkey *public, const char *comment) { char *fp = NULL, *ra = NULL; enum sshkey_fp_rep rep; int fptype; fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; fp = sshkey_fingerprint(public, fptype, rep); ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal_f("sshkey_fingerprint failed"); mprintf("%u %s %s (%s)\n", sshkey_size(public), fp, comment ? comment : "no comment", sshkey_type(public)); if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) 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_r(r, "load public \"%s\"", path); if (pubkey == NULL || comment == NULL || *comment == '\0') { free(comment); if ((r = sshkey_load_private(path, NULL, &privkey, &comment)) != 0) debug_r(r, "load private \"%s\"", path); } if (pubkey == NULL && privkey == NULL) fatal("%s is not a key file.", path); 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; 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, "\r\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. */ comment = NULL; 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'; } } /* 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; } /* Find trailing comment, if any */ for (; *cp == ' ' || *cp == '\t'; cp++) ; if (*cp != '\0' && *cp != '#') comment = cp; fingerprint_one_key(public, comment); sshkey_free(public); invalid = 0; /* One good key in the file is sufficient */ } fclose(f); free(line); if (invalid) fatal("%s is not a public key file.", path); exit(0); } static void do_gen_all_hostkeys(struct passwd *pw) { struct { char *key_type; char *key_type_display; char *path; } key_types[] = { #ifdef WITH_OPENSSL { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, #ifdef OPENSSL_HAS_ECC { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE }, #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], *prv_tmp, *pub_tmp, *prv_file, *pub_file; int i, type, fd, r; for (i = 0; key_types[i].key_type; i++) { 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)); 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); } printf("%s ", key_types[i].key_type_display); fflush(stdout); type = sshkey_type_from_shortname(key_types[i].key_type); 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) { error_r(r, "sshkey_generate failed"); goto failnext; } if ((r = sshkey_from_private(private, &public)) != 0) fatal_fr(r, "sshkey_from_private"); snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); if ((r = sshkey_save_private(private, prv_tmp, "", comment, private_key_format, openssh_format_cipher, rounds)) != 0) { error_r(r, "Saving key \"%s\" failed", prv_tmp); goto failnext; } if ((fd = mkstemp(pub_tmp)) == -1) { error("Could not save your public key in %s: %s", pub_tmp, strerror(errno)); goto failnext; } (void)fchmod(fd, 0644); (void)close(fd); if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) { error_r(r, "Unable to save public key to %s", identity_file); goto failnext; } /* 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; goto next; } next: sshkey_free(private); sshkey_free(public); free(prv_tmp); free(pub_tmp); free(prv_file); free(pub_file); } if (first != 0) printf("\n"); } struct known_hosts_ctx { const char *host; /* Hostname searched for in find/delete case */ FILE *out; /* Output file, stdout for find_hosts case */ 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 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: case HKF_STATUS_MATCHED: /* * Don't hash hosts already hashed, with wildcard * characters or a CA/revocation marker. */ if (was_hashed || has_wild || l->marker != MRK_NONE) { fprintf(ctx->out, "%s\n", l->line); if (has_wild && !ctx->find_host) { logit("%s:%lu: ignoring host name " "with wildcard: %.64s", l->path, l->linenum, l->hosts); } return 0; } /* * Split any comma-separated hostnames from the host list, * hash and store separately. */ 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); free(hashed); ctx->has_unhashed = 1; } free(ohosts); return 0; case HKF_STATUS_INVALID: /* Retain invalid lines, but mark file as invalid. */ ctx->invalid = 1; logit("%s:%lu: invalid line", l->path, l->linenum); /* FALLTHROUGH */ default: fprintf(ctx->out, "%s\n", l->line); return 0; } /* NOTREACHED */ return -1; } 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 (ctx->delete_host) { if (l->marker != MRK_NONE) { /* Don't remove CA and revocation lines */ fprintf(ctx->out, "%s\n", l->line); } else { /* * Hostname matches and has no CA/revoke * marker, delete it by *not* writing the * line to ctx->out. */ ctx->found_key = 1; if (!quiet) printf("# Host %s found: line %lu\n", ctx->host, l->linenum); } return 0; } else if (ctx->find_host) { ctx->found_key = 1; if (!quiet) { printf("# Host %s found: line %lu %s\n", ctx->host, l->linenum, l->marker == MRK_CA ? "CA" : (l->marker == MRK_REVOKE ? "REVOKED" : "")); } if (ctx->hash_hosts) known_hosts_hash(l, ctx); 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_f("sshkey_fingerprint failed"); mprintf("%s %s %s%s%s\n", ctx->host, sshkey_type(l->key), fp, l->comment[0] ? " " : "", l->comment); if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) printf("%s\n", ra); free(ra); free(fp); } else fprintf(ctx->out, "%s\n", l->line); return 0; } } else if (ctx->delete_host) { /* Retain non-matching hosts when deleting */ if (l->status == HKF_STATUS_INVALID) { ctx->invalid = 1; logit("%s:%lu: invalid line", l->path, l->linenum); } fprintf(ctx->out, "%s\n", l->line); } return 0; } static void 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; struct stat sb; if (!have_identity) { cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); if (strlcpy(identity_file, cp, sizeof(identity_file)) >= sizeof(identity_file)) fatal("Specified known hosts path too long"); free(cp); have_identity = 1; } if (stat(identity_file, &sb) != 0) fatal("Cannot stat %s: %s", identity_file, strerror(errno)); memset(&ctx, 0, sizeof(ctx)); ctx.out = stdout; 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 * A corner case is ssh-keygen -HF foo, which should go to stdout */ if (!find_host && (hash_hosts || delete_host)) { if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) || strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) || strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) || strlcat(old, ".old", sizeof(old)) >= sizeof(old)) fatal("known_hosts path too long"); umask(077); if ((fd = mkstemp(tmp)) == -1) fatal("mkstemp: %s", strerror(errno)); if ((ctx.out = fdopen(fd, "w")) == NULL) { oerrno = errno; unlink(tmp); fatal("fdopen: %s", strerror(oerrno)); } (void)fchmod(fd, sb.st_mode & 0644); inplace = 1; } /* XXX support identity_file == "-" for stdin */ 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)) != 0) { if (inplace) unlink(tmp); fatal_fr(r, "hostkeys_foreach"); } if (inplace) fclose(ctx.out); if (ctx.invalid) { error("%s is not a valid known_hosts file.", identity_file); if (inplace) { error("Not replacing existing known_hosts " "file because of errors"); unlink(tmp); } exit(1); } else if (delete_host && !ctx.found_key) { 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) fatal("unlink %.100s: %s", old, strerror(errno)); if (link(identity_file, old) == -1) fatal("link %.100s to %.100s: %s", identity_file, old, strerror(errno)); /* Move new one into place */ if (rename(tmp, identity_file) == -1) { error("rename\"%s\" to \"%s\": %s", tmp, identity_file, strerror(errno)); unlink(tmp); unlink(old); exit(1); } printf("%s updated.\n", identity_file); printf("Original contents retained as %s\n", old); if (ctx.has_unhashed) { logit("WARNING: %s contains unhashed entries", old); logit("Delete this file to ensure privacy " "of hostnames"); } } exit (find_host && !ctx.found_key); } /* * Perform changing a passphrase. The argument is the passwd structure * for the current user. */ static void do_change_passphrase(struct passwd *pw) { char *comment; char *old_passphrase, *passphrase1, *passphrase2; struct stat st; struct sshkey *private; int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); 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) { if (identity_passphrase) old_passphrase = xstrdup(identity_passphrase); else old_passphrase = read_passphrase("Enter old passphrase: ", RP_ALLOW_STDIN); r = sshkey_load_private(identity_file, old_passphrase, &private, &comment); freezero(old_passphrase, strlen(old_passphrase)); if (r != 0) goto badkey; } else if (r != 0) { badkey: fatal_r(r, "Failed to load key %s", identity_file); } if (comment) mprintf("Key has comment '%s'\n", comment); /* Ask the new passphrase (twice). */ if (identity_new_passphrase) { passphrase1 = xstrdup(identity_new_passphrase); passphrase2 = NULL; } else { passphrase1 = read_passphrase("Enter new passphrase (empty for no " "passphrase): ", RP_ALLOW_STDIN); passphrase2 = read_passphrase("Enter same passphrase again: ", RP_ALLOW_STDIN); /* Verify that they are the same. */ if (strcmp(passphrase1, passphrase2) != 0) { explicit_bzero(passphrase1, strlen(passphrase1)); explicit_bzero(passphrase2, strlen(passphrase2)); free(passphrase1); free(passphrase2); printf("Pass phrases do not match. Try again.\n"); exit(1); } /* Destroy the other copy. */ freezero(passphrase2, strlen(passphrase2)); } /* Save the file using the new passphrase. */ if ((r = sshkey_save_private(private, identity_file, passphrase1, comment, private_key_format, openssh_format_cipher, rounds)) != 0) { error_r(r, "Saving key \"%s\" failed", identity_file); freezero(passphrase1, strlen(passphrase1)); sshkey_free(private); free(comment); exit(1); } /* Destroy the passphrase and the copy of the key in memory. */ freezero(passphrase1, strlen(passphrase1)); sshkey_free(private); /* Destroys contents */ free(comment); printf("Your identification has been saved with the new passphrase.\n"); exit(0); } /* * Print the SSHFP RR. */ static int do_print_resource_record(struct passwd *pw, char *fname, char *hname, int print_generic, char * const *opts, size_t nopts) { struct sshkey *public; char *comment = NULL; struct stat st; int r, hash = -1; size_t i; for (i = 0; i < nopts; i++) { if (strncasecmp(opts[i], "hashalg=", 8) == 0) { if ((hash = ssh_digest_alg_by_name(opts[i] + 8)) == -1) fatal("Unsupported hash algorithm"); } else { error("Invalid option \"%s\"", opts[i]); return SSH_ERR_INVALID_ARGUMENT; } } if (fname == NULL) fatal_f("no filename"); if (stat(fname, &st) == -1) { if (errno == ENOENT) return 0; fatal("%s: %s", fname, strerror(errno)); } if ((r = sshkey_load_public(fname, &public, &comment)) != 0) fatal_r(r, "Failed to read v2 public key from \"%s\"", fname); export_dns_rr(hname, public, stdout, print_generic, hash); sshkey_free(public); free(comment); return 1; } /* * Change the comment of a private key file. */ static void 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; int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); 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) fatal_r(r, "Cannot load private key \"%s\"", identity_file); else { if (identity_passphrase) passphrase = xstrdup(identity_passphrase); else if (identity_new_passphrase) passphrase = xstrdup(identity_new_passphrase); else passphrase = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); /* Try to load using the passphrase. */ if ((r = sshkey_load_private(identity_file, passphrase, &private, &comment)) != 0) { freezero(passphrase, strlen(passphrase)); fatal_r(r, "Cannot load private key \"%s\"", identity_file); } } 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); } 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("New comment: "); fflush(stdout); if (!fgets(new_comment, sizeof(new_comment), stdin)) { explicit_bzero(passphrase, strlen(passphrase)); sshkey_free(private); exit(1); } 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, private_key_format, openssh_format_cipher, rounds)) != 0) { error_r(r, "Saving key \"%s\" failed", identity_file); freezero(passphrase, strlen(passphrase)); sshkey_free(private); free(comment); exit(1); } freezero(passphrase, strlen(passphrase)); if ((r = sshkey_from_private(private, &public)) != 0) fatal_fr(r, "sshkey_from_private"); sshkey_free(private); strlcat(identity_file, ".pub", sizeof(identity_file)); if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0) fatal_r(r, "Unable to save public key to %s", identity_file); sshkey_free(public); free(comment); if (strlen(new_comment) > 0) printf("Comment '%s' applied\n", new_comment); else printf("Comment removed\n"); exit(0); } static void cert_ext_add(const char *key, const char *value, int iscrit) { cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext)); cert_ext[ncert_ext].key = xstrdup(key); cert_ext[ncert_ext].val = value == NULL ? NULL : xstrdup(value); cert_ext[ncert_ext].crit = iscrit; ncert_ext++; } /* qsort(3) comparison function for certificate extensions */ static int cert_ext_cmp(const void *_a, const void *_b) { const struct cert_ext *a = (const struct cert_ext *)_a; const struct cert_ext *b = (const struct cert_ext *)_b; int r; if (a->crit != b->crit) return (a->crit < b->crit) ? -1 : 1; if ((r = strcmp(a->key, b->key)) != 0) return r; if ((a->val == NULL) != (b->val == NULL)) return (a->val == NULL) ? -1 : 1; if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0) return r; return 0; } #define OPTIONS_CRITICAL 1 #define OPTIONS_EXTENSIONS 2 static void prepare_options_buf(struct sshbuf *c, int which) { struct sshbuf *b; size_t i; int r; const struct cert_ext *ext; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); sshbuf_reset(c); for (i = 0; i < ncert_ext; i++) { ext = &cert_ext[i]; if ((ext->crit && (which & OPTIONS_EXTENSIONS)) || (!ext->crit && (which & OPTIONS_CRITICAL))) continue; if (ext->val == NULL) { /* flag option */ debug3_f("%s", ext->key); if ((r = sshbuf_put_cstring(c, ext->key)) != 0 || (r = sshbuf_put_string(c, NULL, 0)) != 0) fatal_fr(r, "prepare flag"); } else { /* key/value option */ debug3_f("%s=%s", ext->key, ext->val); sshbuf_reset(b); if ((r = sshbuf_put_cstring(c, ext->key)) != 0 || (r = sshbuf_put_cstring(b, ext->val)) != 0 || (r = sshbuf_put_stringb(c, b)) != 0) fatal_fr(r, "prepare k/v"); } } sshbuf_free(b); } static void finalise_cert_exts(void) { /* critical options */ if (certflags_command != NULL) cert_ext_add("force-command", certflags_command, 1); if (certflags_src_addr != NULL) cert_ext_add("source-address", certflags_src_addr, 1); if ((certflags_flags & CERTOPT_REQUIRE_VERIFY) != 0) cert_ext_add("verify-required", NULL, 1); /* extensions */ if ((certflags_flags & CERTOPT_X_FWD) != 0) cert_ext_add("permit-X11-forwarding", NULL, 0); if ((certflags_flags & CERTOPT_AGENT_FWD) != 0) cert_ext_add("permit-agent-forwarding", NULL, 0); if ((certflags_flags & CERTOPT_PORT_FWD) != 0) cert_ext_add("permit-port-forwarding", NULL, 0); if ((certflags_flags & CERTOPT_PTY) != 0) cert_ext_add("permit-pty", NULL, 0); if ((certflags_flags & CERTOPT_USER_RC) != 0) cert_ext_add("permit-user-rc", NULL, 0); if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) cert_ext_add("no-touch-required", NULL, 0); /* order lexically by key */ if (ncert_ext > 0) qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp); } static struct sshkey * load_pkcs11_key(char *path) { #ifdef ENABLE_PKCS11 struct sshkey **keys = NULL, *public, *private = NULL; int r, i, nkeys; if ((r = sshkey_load_public(path, &public, NULL)) != 0) fatal_r(r, "Couldn't load CA public key \"%s\"", path); nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys, NULL); debug3_f("%d keys", nkeys); if (nkeys <= 0) fatal("cannot read public key from pkcs11"); for (i = 0; i < nkeys; i++) { if (sshkey_equal_public(public, keys[i])) { private = keys[i]; continue; } sshkey_free(keys[i]); } free(keys); sshkey_free(public); return private; #else fatal("no pkcs11 support"); #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, const char *pin, 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, const char *ca_key_path, int prefer_agent, unsigned long long cert_serial, int cert_serial_autoinc, int argc, char **argv) { int r, i, found, agent_fd = -1; u_int n; struct sshkey *ca, *public; char valid[64], *otmp, *tmp, *cp, *out, *comment; char *ca_fp = NULL, **plist = NULL, *pin = NULL; struct ssh_identitylist *agent_ids; size_t j; struct notifier_ctx *notifier = NULL; #ifdef ENABLE_PKCS11 pkcs11_init(1); #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 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_r(r, "Cannot load CA public key %s", tmp); if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) fatal_r(r, "Cannot use public key for CA signature"); if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0) fatal_r(r, "Retrieve agent key list"); found = 0; for (j = 0; j < agent_ids->nkeys; j++) { if (sshkey_equal(ca, agent_ids->keys[j])) { 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); if (sshkey_is_sk(ca) && (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { if ((pin = read_passphrase("Enter PIN for CA key: ", RP_ALLOW_STDIN)) == NULL) fatal_f("couldn't read PIN"); } } free(tmp); if (key_type_name != NULL) { if (sshkey_type_from_shortname(key_type_name) != ca->type) { fatal("CA key type %s doesn't match specified %s", sshkey_ssh_name(ca), key_type_name); } } else if (ca->type == KEY_RSA) { /* Default to a good signature algorithm */ key_type_name = "rsa-sha2-512"; } ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT); finalise_cert_exts(); for (i = 0; i < argc; i++) { /* Split list of principals */ n = 0; if (cert_principals != NULL) { otmp = tmp = xstrdup(cert_principals); plist = NULL; for (; (cp = strsep(&tmp, ",")) != NULL; n++) { 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_r(r, "load pubkey \"%s\"", tmp); if (sshkey_is_cert(public)) fatal_f("key \"%s\" type %s cannot be certified", tmp, sshkey_type(public)); /* Prepare certificate to sign */ if ((r = sshkey_to_certified(public)) != 0) fatal_r(r, "Could not upgrade key %s to certificate", tmp); public->cert->type = cert_key_type; public->cert->serial = (u_int64_t)cert_serial; public->cert->key_id = xstrdup(cert_key_id); public->cert->nprincipals = n; public->cert->principals = plist; public->cert->valid_after = cert_valid_from; public->cert->valid_before = cert_valid_to; 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_r(r, "sshkey_from_private (ca key)"); if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { if ((r = sshkey_certify_custom(public, ca, key_type_name, sk_provider, NULL, agent_signer, &agent_fd)) != 0) fatal_r(r, "Couldn't certify %s via agent", tmp); } 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, pin); notify_complete(notifier, "User presence confirmed"); if (r != 0) fatal_r(r, "Couldn't certify key %s", tmp); } if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0) *cp = '\0'; xasprintf(&out, "%s-cert.pub", tmp); free(tmp); if ((r = sshkey_save_public(public, out, comment)) != 0) { fatal_r(r, "Unable to save public key to %s", identity_file); } if (!quiet) { sshkey_format_cert_validity(public->cert, valid, sizeof(valid)); logit("Signed %s key %s: id \"%s\" serial %llu%s%s " "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 : "", valid); } sshkey_free(public); free(out); if (cert_serial_autoinc) cert_serial++; } if (pin != NULL) freezero(pin, strlen(pin)); free(ca_fp); #ifdef ENABLE_PKCS11 pkcs11_terminate(); #endif exit(0); } static u_int64_t parse_relative_time(const char *s, time_t now) { int64_t mul, secs; mul = *s == '-' ? -1 : 1; if ((secs = convtime(s + 1)) == -1) fatal("Invalid relative certificate time %s", s); if (mul == -1 && secs > now) fatal("Certificate time %s cannot be represented", s); return now + (u_int64_t)(secs * mul); } static void parse_hex_u64(const char *s, uint64_t *up) { char *ep; unsigned long long ull; errno = 0; ull = strtoull(s, &ep, 16); if (*s == '\0' || *ep != '\0') fatal("Invalid certificate time: not a number"); if (errno == ERANGE && ull == ULONG_MAX) fatal_fr(SSH_ERR_SYSTEM_ERROR, "Invalid certificate time"); *up = (uint64_t)ull; } static void parse_cert_times(char *timespec) { char *from, *to; time_t now = time(NULL); int64_t secs; /* +timespec relative to now */ if (*timespec == '+' && strchr(timespec, ':') == NULL) { if ((secs = convtime(timespec + 1)) == -1) fatal("Invalid relative certificate life %s", timespec); cert_valid_to = now + secs; /* * Backdate certificate one minute to avoid problems on hosts * with poorly-synchronised clocks. */ cert_valid_from = ((now - 59)/ 60) * 60; return; } /* * from:to, where * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "always" * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "forever" */ from = xstrdup(timespec); to = strchr(from, ':'); if (to == NULL || from == to || *(to + 1) == '\0') fatal("Invalid certificate life specification %s", timespec); *to++ = '\0'; if (*from == '-' || *from == '+') cert_valid_from = parse_relative_time(from, now); else if (strcmp(from, "always") == 0) cert_valid_from = 0; else if (strncmp(from, "0x", 2) == 0) parse_hex_u64(from, &cert_valid_from); 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 if (strcmp(to, "forever") == 0) cert_valid_to = ~(u_int64_t)0; else if (strncmp(to, "0x", 2) == 0) parse_hex_u64(to, &cert_valid_to); 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"); free(from); } static void add_cert_option(char *opt) { char *val, *cp; int iscrit = 0; if (strcasecmp(opt, "clear") == 0) certflags_flags = 0; else if (strcasecmp(opt, "no-x11-forwarding") == 0) certflags_flags &= ~CERTOPT_X_FWD; else if (strcasecmp(opt, "permit-x11-forwarding") == 0) certflags_flags |= CERTOPT_X_FWD; else if (strcasecmp(opt, "no-agent-forwarding") == 0) certflags_flags &= ~CERTOPT_AGENT_FWD; else if (strcasecmp(opt, "permit-agent-forwarding") == 0) certflags_flags |= CERTOPT_AGENT_FWD; else if (strcasecmp(opt, "no-port-forwarding") == 0) certflags_flags &= ~CERTOPT_PORT_FWD; else if (strcasecmp(opt, "permit-port-forwarding") == 0) certflags_flags |= CERTOPT_PORT_FWD; else if (strcasecmp(opt, "no-pty") == 0) certflags_flags &= ~CERTOPT_PTY; else if (strcasecmp(opt, "permit-pty") == 0) certflags_flags |= CERTOPT_PTY; else if (strcasecmp(opt, "no-user-rc") == 0) 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 (strcasecmp(opt, "no-verify-required") == 0) certflags_flags &= ~CERTOPT_REQUIRE_VERIFY; else if (strcasecmp(opt, "verify-required") == 0) certflags_flags |= CERTOPT_REQUIRE_VERIFY; else if (strncasecmp(opt, "force-command=", 14) == 0) { val = opt + 14; if (*val == '\0') fatal("Empty force-command option"); if (certflags_command != NULL) fatal("force-command already specified"); certflags_command = xstrdup(val); } else if (strncasecmp(opt, "source-address=", 15) == 0) { val = opt + 15; if (*val == '\0') fatal("Empty source-address option"); if (certflags_src_addr != NULL) fatal("source-address already specified"); 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_ext_add(val, cp, iscrit); free(val); } else fatal("Unsupported certificate option \"%s\"", opt); } static void show_options(struct sshbuf *optbuf, int in_critical) { char *name, *arg, *hex; struct sshbuf *options, *option = NULL; int r; if ((options = sshbuf_fromb(optbuf)) == NULL) fatal_f("sshbuf_fromb failed"); while (sshbuf_len(options) != 0) { sshbuf_free(option); option = NULL; if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 || (r = sshbuf_froms(options, &option)) != 0) fatal_fr(r, "parse option"); printf(" %s", name); if (!in_critical && (strcmp(name, "permit-X11-forwarding") == 0 || strcmp(name, "permit-agent-forwarding") == 0 || strcmp(name, "permit-port-forwarding") == 0 || strcmp(name, "permit-pty") == 0 || strcmp(name, "permit-user-rc") == 0 || strcmp(name, "no-touch-required") == 0)) { printf("\n"); } else if (in_critical && (strcmp(name, "force-command") == 0 || strcmp(name, "source-address") == 0)) { if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0) fatal_fr(r, "parse critical"); printf(" %s\n", arg); free(arg); } else if (in_critical && strcmp(name, "verify-required") == 0) { printf("\n"); } else if (sshbuf_len(option) > 0) { hex = sshbuf_dtob16(option); printf(" UNKNOWN OPTION: %s (len %zu)\n", hex, sshbuf_len(option)); sshbuf_reset(option); free(hex); } else printf(" UNKNOWN FLAG OPTION\n"); free(name); if (sshbuf_len(option) != 0) fatal("Option corrupt: extra data at end"); } sshbuf_free(option); sshbuf_free(options); } static void print_cert(struct sshkey *key) { 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_f("sshkey_fingerprint fail"); sshkey_format_cert_validity(key->cert, valid, sizeof(valid)); 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 (using %s)\n", sshkey_type(key->cert->signature_key), ca_fp, key->cert->signature_type); printf(" Key ID: \"%s\"\n", key->cert->key_id); 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"); else { for (i = 0; i < key->cert->nprincipals; i++) printf("\n %s", key->cert->principals[i]); printf("\n"); } printf(" Critical Options: "); if (sshbuf_len(key->cert->critical) == 0) printf("(none)\n"); else { printf("\n"); show_options(key->cert->critical, 1); } 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_r(r, "%s:%lu: invalid key", path, lnum); 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); } 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; if ((r = sshbuf_load_file(path, &krlbuf)) != 0) fatal_r(r, "Unable to load KRL %s", path); /* XXX check sigs */ if ((r = ssh_krl_from_blob(krlbuf, krlp)) != 0 || *krlp == NULL) fatal_r(r, "Invalid KRL file %s", path); sshbuf_free(krlbuf); } 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. */ if ((tlen = strlen(cp)) >= SIZE_MAX - 5) fatal_f("hash too long: %zu bytes", tlen); 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_f("sshbuf_new failed"); if ((r = sshbuf_b64tod(b, tmp)) != 0) fatal_r(r, "%s:%lu: decode hash failed", file, lnum); 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 = NULL; u_char *blob = NULL; size_t blen = 0, linesize = 0; unsigned long long serial, serial2; int i, was_explicit_key, was_sha1, was_sha256, was_hash, r; FILE *krl_spec; path = tilde_expand_filename(file, pw->pw_uid); if (strcmp(path, "-") == 0) { krl_spec = stdin; free(path); path = xstrdup("(standard input)"); } else if ((krl_spec = fopen(path, "r")) == NULL) fatal("fopen %s: %s", path, strerror(errno)); if (!quiet) printf("Revoking from %s\n", path); while (getline(&line, &linesize, krl_spec) != -1) { if (linesize >= INT_MAX) { fatal_f("%s contains unparsable line, len=%zu", path, linesize); } 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++) { if (cp[i] == '#' || cp[i] == '\n') { cp[i] = '\0'; break; } if (cp[i] == ' ' || cp[i] == '\t') { /* Remember the start of a span of whitespace */ if (r == -1) r = i; } else r = -1; } if (r != -1) cp[r] = '\0'; if (*cp == '\0') continue; if (strncasecmp(cp, "serial:", 7) == 0) { if (ca == NULL && !wild_ca) { fatal("revoking certificates by serial number " "requires specification of a CA key"); } cp += 7; cp = cp + strspn(cp, " \t"); errno = 0; serial = strtoull(cp, &ep, 0); if (*cp == '\0' || (*ep != '\0' && *ep != '-')) fatal("%s:%lu: invalid serial \"%s\"", path, lnum, cp); if (errno == ERANGE && serial == ULLONG_MAX) fatal("%s:%lu: serial out of range", path, lnum); serial2 = serial; if (*ep == '-') { cp = ep + 1; errno = 0; serial2 = strtoull(cp, &ep, 0); if (*cp == '\0' || *ep != '\0') fatal("%s:%lu: invalid serial \"%s\"", path, lnum, cp); if (errno == ERANGE && serial2 == ULLONG_MAX) fatal("%s:%lu: serial out of range", path, lnum); if (serial2 <= serial) fatal("%s:%lu: invalid serial range " "%llu:%llu", path, lnum, (unsigned long long)serial, (unsigned long long)serial2); } if (ssh_krl_revoke_cert_by_serial_range(krl, ca, serial, serial2) != 0) { fatal_f("revoke serial failed"); } } else if (strncasecmp(cp, "id:", 3) == 0) { if (ca == NULL && !wild_ca) { fatal("revoking certificates by key ID " "requires specification of a CA key"); } cp += 3; cp = cp + strspn(cp, " \t"); if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0) fatal_f("revoke key ID failed"); } else if (strncasecmp(cp, "hash:", 5) == 0) { cp += 5; cp = cp + strspn(cp, " \t"); hash_to_blob(cp, &blob, &blen, file, lnum); r = ssh_krl_revoke_key_sha256(krl, blob, blen); if (r != 0) fatal_fr(r, "revoke key failed"); } else { if (strncasecmp(cp, "key:", 4) == 0) { cp += 4; cp = cp + strspn(cp, " \t"); was_explicit_key = 1; } else if (strncasecmp(cp, "sha1:", 5) == 0) { cp += 5; cp = cp + strspn(cp, " \t"); was_sha1 = 1; } 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("sshkey_new"); if ((r = sshkey_read(key, &cp)) != 0) fatal_r(r, "%s:%lu: invalid key", path, lnum); if (was_explicit_key) r = ssh_krl_revoke_key_explicit(krl, key); else if (was_sha1) { 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_fr(r, "revoke key failed"); 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, 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 i, r, wild_ca = 0; char *tmp; struct sshbuf *kbuf; if (*identity_file == '\0') fatal("KRL generation requires an output file"); if (stat(identity_file, &sb) == -1) { if (errno != ENOENT) fatal("Cannot access KRL \"%s\": %s", identity_file, strerror(errno)); if (updating) fatal("KRL \"%s\" does not exist", identity_file); } if (ca_key_path != NULL) { if (strcasecmp(ca_key_path, "none") == 0) wild_ca = 1; else { tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0) fatal_r(r, "Cannot load CA public key %s", tmp); free(tmp); } } if (updating) load_krl(identity_file, &krl); else if ((krl = ssh_krl_init()) == NULL) fatal("couldn't create KRL"); 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); if ((kbuf = sshbuf_new()) == NULL) fatal("sshbuf_new failed"); if (ssh_krl_to_blob(krl, kbuf) != 0) fatal("Couldn't generate KRL"); if ((r = sshbuf_write_file(identity_file, kbuf)) != 0) fatal("write %s: %s", identity_file, strerror(errno)); sshbuf_free(kbuf); ssh_krl_free(krl); sshkey_free(ca); } static void do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv) { int i, r, ret = 0; char *comment; struct ssh_krl *krl; struct sshkey *k; 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_r(r, "Cannot load public key %s", argv[i]); r = ssh_krl_check_key(krl, k); printf("%s%s%s%s: %s\n", argv[i], *comment ? " (" : "", comment, *comment ? ")" : "", r == 0 ? "ok" : "REVOKED"); if (r != 0) ret = 1; sshkey_free(k); free(comment); } ssh_krl_free(krl); 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); static const char * const suffixes[] = { "-cert.pub", ".pub", NULL }; struct sshkey *ret = NULL, *privkey = NULL; int r, waspub = 0; struct stat st; /* * 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_f("%s looks like a public key, using private key " "path %s instead", keypath, privpath); waspub = 1; } if (waspub && stat(privpath, &st) != 0 && errno == ENOENT) fatal("No private key found for public key \"%s\"", keypath); if ((r = sshkey_load_private(privpath, "", &privkey, NULL)) != 0 && (r != SSH_ERR_KEY_WRONG_PASSPHRASE)) { debug_fr(r, "load private key \"%s\"", privpath); fatal("No private key found for \"%s\"", privpath); } else if (privkey == NULL) privkey = load_identity(privpath, NULL); 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_fr(r, "sshkey_to_certified"); goto done; } if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) { error_fr(r, "sshkey_cert_copy"); 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, const char *hashalg, 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; char *pin = NULL, *prompt = 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)) { if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { xasprintf(&prompt, "Enter PIN for %s key: ", sshkey_type(signkey)); if ((pin = read_passphrase(prompt, RP_ALLOW_STDIN)) == NULL) fatal_f("couldn't read PIN"); } if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); fprintf(stderr, "Confirm user presence for key %s %s\n", sshkey_type(signkey), fp); free(fp); } } if ((r = sshsig_sign_fd(signkey, hashalg, sk_provider, pin, fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) { error_r(r, "Signing %s failed", filename); goto out; } if ((r = sshsig_armor(sigbuf, &abuf)) != 0) { error_fr(r, "sshsig_armor"); goto out; } if ((asig = sshbuf_dup_string(abuf)) == NULL) { error_f("buffer error"); 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(prompt); free(asig); if (pin != NULL) freezero(pin, strlen(pin)); sshbuf_free(abuf); sshbuf_free(sigbuf); if (wfd != -1) close(wfd); return r; } static int sig_process_opts(char * const *opts, size_t nopts, char **hashalgp, uint64_t *verify_timep, int *print_pubkey) { size_t i; time_t now; if (verify_timep != NULL) *verify_timep = 0; if (print_pubkey != NULL) *print_pubkey = 0; if (hashalgp != NULL) *hashalgp = NULL; for (i = 0; i < nopts; i++) { if (hashalgp != NULL && strncasecmp(opts[i], "hashalg=", 8) == 0) { *hashalgp = xstrdup(opts[i] + 8); } else if (verify_timep && strncasecmp(opts[i], "verify-time=", 12) == 0) { if (parse_absolute_time(opts[i] + 12, verify_timep) != 0 || *verify_timep == 0) { error("Invalid \"verify-time\" option"); return SSH_ERR_INVALID_ARGUMENT; } } else if (print_pubkey && strcasecmp(opts[i], "print-pubkey") == 0) { *print_pubkey = 1; } else { error("Invalid option \"%s\"", opts[i]); return SSH_ERR_INVALID_ARGUMENT; } } if (verify_timep && *verify_timep == 0) { if ((now = time(NULL)) < 0) { error("Time is before epoch"); return SSH_ERR_INVALID_ARGUMENT; } *verify_timep = (uint64_t)now; } return 0; } static int sig_sign(const char *keypath, const char *sig_namespace, int require_agent, int argc, char **argv, char * const *opts, size_t nopts) { int i, fd = -1, r, ret = -1; int agent_fd = -1; struct sshkey *pubkey = NULL, *privkey = NULL, *signkey = NULL; sshsig_signer *signer = NULL; char *hashalg = 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 (sig_process_opts(opts, nopts, &hashalg, NULL, NULL) != 0) goto done; /* error already logged */ if ((r = sshkey_load_public(keypath, &pubkey, NULL)) != 0) { error_r(r, "Couldn't load public key %s", keypath); goto done; } if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { if (require_agent) fatal("Couldn't get agent socket"); debug_r(r, "Couldn't get agent socket"); } else { if ((r = ssh_agent_has_key(agent_fd, pubkey)) == 0) signer = agent_signer; else { if (require_agent) fatal("Couldn't find key in agent"); debug_r(r, "Couldn't find key in agent"); } } 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, hashalg, 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, hashalg, 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); free(hashalg); return ret; } static int sig_verify(const char *signature, const char *sig_namespace, const char *principal, const char *allowed_keys, const char *revoked_keys, char * const *opts, size_t nopts) { int r, ret = -1; int print_pubkey = 0; struct sshbuf *sigbuf = NULL, *abuf = NULL; struct sshkey *sign_key = NULL; char *fp = NULL; struct sshkey_sig_details *sig_details = NULL; uint64_t verify_time = 0; if (sig_process_opts(opts, nopts, NULL, &verify_time, &print_pubkey) != 0) goto done; /* error already logged */ memset(&sig_details, 0, sizeof(sig_details)); if ((r = sshbuf_load_file(signature, &abuf)) != 0) { error_r(r, "Couldn't read signature file"); goto done; } if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { error_fr(r, "sshsig_armor"); goto done; } if ((r = sshsig_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_f("sshkey_fingerprint failed"); debug("Valid (unverified) signature from key %s", fp); if (sig_details != NULL) { debug2_f("signature details: counter = %u, flags = 0x%02x", sig_details->sk_counter, sig_details->sk_flags); } free(fp); fp = NULL; if (revoked_keys != NULL) { if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) { debug3_fr(r, "sshkey_check_revoked"); goto done; } } if (allowed_keys != NULL && (r = sshsig_check_allowed_keys(allowed_keys, sign_key, principal, sig_namespace, verify_time)) != 0) { debug3_fr(r, "sshsig_check_allowed_keys"); goto done; } /* success */ ret = 0; done: if (!quiet) { if (ret == 0) { if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); if (principal == NULL) { printf("Good \"%s\" signature with %s key %s\n", sig_namespace, sshkey_type(sign_key), fp); } 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"); } } /* Print the signature key if requested */ if (ret == 0 && print_pubkey && sign_key != NULL) { if ((r = sshkey_write(sign_key, stdout)) == 0) fputc('\n', stdout); else { error_r(r, "Could not print public key.\n"); ret = -1; } } sshbuf_free(sigbuf); sshbuf_free(abuf); sshkey_free(sign_key); sshkey_sig_details_free(sig_details); free(fp); return ret; } static int sig_find_principals(const char *signature, const char *allowed_keys, char * const *opts, size_t nopts) { int r, ret = -1; struct sshbuf *sigbuf = NULL, *abuf = NULL; struct sshkey *sign_key = NULL; char *principals = NULL, *cp, *tmp; uint64_t verify_time = 0; if (sig_process_opts(opts, nopts, NULL, &verify_time, NULL) != 0) goto done; /* error already logged */ if ((r = sshbuf_load_file(signature, &abuf)) != 0) { error_r(r, "Couldn't read signature file"); goto done; } if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { error_fr(r, "sshsig_armor"); goto done; } if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) { error_fr(r, "sshsig_get_pubkey"); goto done; } if ((r = sshsig_find_principals(allowed_keys, sign_key, verify_time, &principals)) != 0) { if (r != SSH_ERR_KEY_NOT_FOUND) error_fr(r, "sshsig_find_principal"); goto done; } ret = 0; done: if (ret == 0 ) { /* Emit matching principals one per line */ tmp = principals; while ((cp = strsep(&tmp, ",")) != NULL && *cp != '\0') puts(cp); } else { fprintf(stderr, "No principal matched.\n"); } sshbuf_free(sigbuf); sshbuf_free(abuf); sshkey_free(sign_key); free(principals); return ret; } static int sig_match_principals(const char *allowed_keys, char *principal, char * const *opts, size_t nopts) { int r; char **principals = NULL; size_t i, nprincipals = 0; if ((r = sig_process_opts(opts, nopts, NULL, NULL, NULL)) != 0) return r; /* error already logged */ if ((r = sshsig_match_principals(allowed_keys, principal, &principals, &nprincipals)) != 0) { debug_f("match: %s", ssh_err(r)); fprintf(stderr, "No principal matched.\n"); return r; } for (i = 0; i < nprincipals; i++) { printf("%s\n", principals[i]); free(principals[i]); } free(principals); return 0; } 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 (strcmp(out_file, "-") == 0) out = stdout; else 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) { free(checkpoint); checkpoint = xstrdup(opts[i]+11); } else if (strncmp(opts[i], "generator=", 10) == 0) { generator_wanted = (u_int32_t)strtonum( opts[i]+10, 1, UINT_MAX, &errstr); 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 (strcmp(out_file, "-") == 0) out = stdout; else 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"); if (in != stdin) (void)fclose(in); free(checkpoint); #else /* WITH_OPENSSL */ fatal("Moduli screening is not supported"); #endif /* WITH_OPENSSL */ } /* Read and confirm a passphrase */ static char * read_check_passphrase(const char *prompt1, const char *prompt2, const char *retry_prompt) { char *passphrase1, *passphrase2; for (;;) { passphrase1 = read_passphrase(prompt1, RP_ALLOW_STDIN); passphrase2 = read_passphrase(prompt2, RP_ALLOW_STDIN); if (strcmp(passphrase1, passphrase2) == 0) { freezero(passphrase2, strlen(passphrase2)); return passphrase1; } /* The passphrases do not match. Clear them and retry. */ freezero(passphrase1, strlen(passphrase1)); freezero(passphrase2, strlen(passphrase2)); fputs(retry_prompt, stdout); fputc('\n', stdout); fflush(stdout); } /* NOTREACHED */ return NULL; } static char * private_key_passphrase(const char *path) { char *prompt, *ret; if (identity_passphrase) return xstrdup(identity_passphrase); if (identity_new_passphrase) return xstrdup(identity_new_passphrase); xasprintf(&prompt, "Enter passphrase for \"%s\" " "(empty for no passphrase): ", path); ret = read_check_passphrase(prompt, "Enter same passphrase again: ", "Passphrases do not match. Try again."); free(prompt); return ret; } static char * sk_suffix(const char *application, const uint8_t *user, size_t userlen) { char *ret, *cp; size_t slen, i; /* Trim off URL-like preamble */ if (strncmp(application, "ssh://", 6) == 0) ret = xstrdup(application + 6); else if (strncmp(application, "ssh:", 4) == 0) ret = xstrdup(application + 4); else ret = xstrdup(application); /* Count trailing zeros in user */ for (i = 0; i < userlen; i++) { if (user[userlen - i - 1] != 0) break; } if (i >= userlen) return ret; /* user-id was default all-zeros */ /* Append user-id, escaping non-UTF-8 characters */ slen = userlen - i; if (asmprintf(&cp, INT_MAX, NULL, "%.*s", (int)slen, user) == -1) fatal_f("asmprintf failed"); /* Don't emit a user-id that contains path or control characters */ if (strchr(cp, '/') != NULL || strstr(cp, "..") != NULL || strchr(cp, '\\') != NULL) { free(cp); cp = tohex(user, slen); } xextendf(&ret, "_", "%s", cp); free(cp); return ret; } static int do_download_sk(const char *skprovider, const char *device) { struct sshsk_resident_key **srks; size_t nsrks, i; int r, ret = -1; char *fp, *pin = NULL, *pass = NULL, *path, *pubpath; const char *ext; struct sshkey *key; if (skprovider == NULL) fatal("Cannot download keys without provider"); pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); if (!quiet) { printf("You may need to touch your authenticator " "to authorize key download.\n"); } if ((r = sshsk_load_resident(skprovider, device, pin, 0, &srks, &nsrks)) != 0) { if (pin != NULL) freezero(pin, strlen(pin)); error_r(r, "Unable to load resident keys"); return -1; } if (nsrks == 0) logit("No keys to download"); if (pin != NULL) freezero(pin, strlen(pin)); for (i = 0; i < nsrks; i++) { key = srks[i]->key; if (key->type != KEY_ECDSA_SK && key->type != KEY_ED25519_SK) { error("Unsupported key type %s (%d)", sshkey_type(key), key->type); continue; } if ((fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); debug_f("key %zu: %s %s %s (flags 0x%02x)", i, sshkey_type(key), fp, key->sk_application, key->sk_flags); ext = sk_suffix(key->sk_application, srks[i]->user_id, srks[i]->user_id_len); xasprintf(&path, "id_%s_rk%s%s", key->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(path); if ((r = sshkey_save_private(key, path, pass, key->sk_application, private_key_format, openssh_format_cipher, rounds)) != 0) { error_r(r, "Saving key \"%s\" failed", path); free(path); break; } if (!quiet) { printf("Saved %s key%s%s to %s\n", sshkey_type(key), *ext != '\0' ? " " : "", *ext != '\0' ? key->sk_application : "", path); } /* Save public key too */ xasprintf(&pubpath, "%s.pub", path); free(path); if ((r = sshkey_save_public(key, pubpath, key->sk_application)) != 0) { error_r(r, "Saving public key \"%s\" failed", pubpath); free(pubpath); break; } free(pubpath); } if (i >= nsrks) ret = 0; /* success */ if (pass != NULL) freezero(pass, strlen(pass)); sshsk_free_resident_keys(srks, nsrks); return ret; } static void save_attestation(struct sshbuf *attest, const char *path) { mode_t omask; int r; if (path == NULL) return; /* nothing to do */ if (attest == NULL || sshbuf_len(attest) == 0) fatal("Enrollment did not return attestation data"); omask = umask(077); r = sshbuf_write_file(path, attest); umask(omask); if (r != 0) fatal_r(r, "Unable to write attestation data \"%s\"", path); if (!quiet) printf("Your FIDO attestation certificate has been saved in " "%s\n", path); } static int confirm_sk_overwrite(const char *application, const char *user) { char yesno[3]; printf("A resident key scoped to '%s' with user id '%s' already " "exists.\n", application == NULL ? "ssh:" : application, user == NULL ? "null" : user); printf("Overwrite key in token (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 usage(void) { fprintf(stderr, "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n" " [-m format] [-N new_passphrase] [-O option]\n" " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" " [-w provider] [-Z cipher]\n" " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n" " [-P old_passphrase] [-Z cipher]\n" #ifdef WITH_OPENSSL " ssh-keygen -i [-f input_keyfile] [-m key_format]\n" " ssh-keygen -e [-f input_keyfile] [-m key_format]\n" #endif " ssh-keygen -y [-f input_keyfile]\n" " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n" " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n" " ssh-keygen -B [-f input_keyfile]\n"); #ifdef ENABLE_PKCS11 fprintf(stderr, " ssh-keygen -D pkcs11\n"); #endif fprintf(stderr, " ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n" " ssh-keygen -H [-f known_hosts_file]\n" " ssh-keygen -K [-a rounds] [-w provider]\n" " ssh-keygen -R hostname [-f known_hosts_file]\n" " ssh-keygen -r hostname [-g] [-f input_keyfile]\n" #ifdef WITH_OPENSSL " ssh-keygen -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 [-a rounds] [-f prefix_path]\n" " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" " file ...\n" " ssh-keygen -Q [-l] -f krl_file [file ...]\n" " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n" " ssh-keygen -Y match-principals -I signer_identity -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 [-O option] ...\n" " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n" " -n namespace -s signature_file [-r krl_file] [-O option]\n"); exit(1); } /* * Main program for key management. */ int main(int argc, char **argv) { char comment[1024], *passphrase = NULL; char *rr_hostname = NULL, *ep, *fp, *ra; struct sshkey *private, *public; struct passwd *pw; int r, opt, type; int change_passphrase = 0, change_comment = 0, show_cert = 0; int find_host = 0, delete_host = 0, hash_hosts = 0; int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; int prefer_agent = 0, convert_to = 0, convert_from = 0; int print_public = 0, print_generic = 0, cert_serial_autoinc = 0; int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0; unsigned long long cert_serial = 0; char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL; char *sk_attestation_path = NULL; struct sshbuf *challenge = NULL, *attest = NULL; size_t i, nopts = 0; u_int32_t bits = 0; 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; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); __progname = ssh_get_progname(argv[0]); seed_rng(); log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); msetlocale(); /* we need this for the home * directory. */ pw = getpwuid(getuid()); if (!pw) fatal("No user exists for uid %lu", (u_long)getuid()); pw = pwcopy(pw); if (gethostname(hostname, sizeof(hostname)) == -1) fatal("gethostname: %s", strerror(errno)); 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, 1, UINT32_MAX, &errstr); if (errstr) fatal("Bits has bad value %s (%s)", optarg, errstr); break; case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); if (fingerprint_hash == -1) fatal("Invalid hash algorithm \"%s\"", optarg); break; case 'F': find_host = 1; rr_hostname = optarg; break; case 'H': hash_hosts = 1; break; case 'I': cert_key_id = optarg; break; case 'R': delete_host = 1; rr_hostname = optarg; break; case 'L': show_cert = 1; break; case 'l': print_fingerprint = 1; break; case 'B': print_bubblebabble = 1; break; case 'm': if (strcasecmp(optarg, "RFC4716") == 0 || strcasecmp(optarg, "ssh2") == 0) { convert_format = FMT_RFC4716; break; } 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); case 'n': cert_principals = optarg; break; case 'o': /* no-op; new format is already the default */ break; case 'p': change_passphrase = 1; break; case 'c': change_comment = 1; break; case 'f': 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; case 'N': identity_new_passphrase = optarg; break; case 'Q': check_krl = 1; break; case 'O': opts = xrecallocarray(opts, nopts, nopts + 1, sizeof(*opts)); opts[nopts++] = xstrdup(optarg); break; case 'Z': openssh_format_cipher = optarg; if (cipher_by_name(openssh_format_cipher) == NULL) fatal("Invalid OpenSSH-format cipher '%s'", openssh_format_cipher); break; case 'C': identity_comment = optarg; break; case 'q': quiet = 1; break; case 'e': /* export key */ convert_to = 1; break; case 'h': cert_key_type = SSH2_CERT_TYPE_HOST; certflags_flags = 0; break; case 'k': gen_krl = 1; break; case 'i': case 'X': /* import key */ convert_from = 1; break; case 'y': print_public = 1; break; case 's': ca_key_path = optarg; break; case 't': key_type_name = optarg; break; case 'D': pkcs11provider = optarg; break; case 'U': prefer_agent = 1; break; case 'u': update_krl = 1; break; case 'v': if (log_level == SYSLOG_LEVEL_INFO) log_level = SYSLOG_LEVEL_DEBUG1; else { if (log_level >= SYSLOG_LEVEL_DEBUG1 && log_level < SYSLOG_LEVEL_DEBUG3) log_level++; } break; case 'r': rr_hostname = optarg; break; case 'a': rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr); if (errstr) fatal("Invalid number: %s (%s)", optarg, errstr); break; 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; 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, opts, nopts); } else if (strncmp(sign_op, "match-principals", 16) == 0) { if (!have_identity) { error("Too few arguments for match-principals:" "missing allowed keys file"); exit(1); } if (cert_key_id == NULL) { error("Too few arguments for match-principals: " "missing principal ID"); exit(1); } return sig_match_principals(identity_file, cert_key_id, opts, nopts); } else if (strncmp(sign_op, "sign", 4) == 0) { /* NB. cert_principals is actually namespace, via -n */ 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, prefer_agent, argc, argv, opts, nopts); } else if (strncmp(sign_op, "check-novalidate", 16) == 0) { /* NB. cert_principals is actually namespace, via -n */ if (cert_principals == NULL || *cert_principals == '\0') { error("Too few arguments for check-novalidate: " "missing namespace"); exit(1); } 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, opts, nopts); } else if (strncmp(sign_op, "verify", 6) == 0) { /* NB. cert_principals is actually namespace, via -n */ 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 identity"); exit(1); } return sig_verify(ca_key_path, cert_principals, cert_key_id, identity_file, rr_hostname, opts, nopts); } error("Unsupported operation for -Y: \"%s\"", sign_op); usage(); /* NOTREACHED */ } if (ca_key_path != NULL) { if (argc < 1 && !gen_krl) { error("Too few arguments."); usage(); } } else if (argc > 0 && !gen_krl && !check_krl && !do_gen_candidates && !do_screen_candidates) { error("Too many arguments."); usage(); } if (change_passphrase && change_comment) { error("Can only have one of -p and -c."); usage(); } if (print_fingerprint && (delete_host || hash_hosts)) { error("Cannot use -l with -H or -R."); usage(); } if (gen_krl) { do_gen_krl(pw, update_krl, ca_key_path, cert_serial, identity_comment, argc, argv); return (0); } if (check_krl) { do_check_krl(pw, print_fingerprint, argc, argv); return (0); } if (ca_key_path != NULL) { if (cert_key_id == NULL) fatal("Must specify key id (-I) when certifying"); for (i = 0; i < nopts; i++) add_cert_option(opts[i]); do_ca_sign(pw, ca_key_path, prefer_agent, cert_serial, cert_serial_autoinc, argc, argv); } if (show_cert) do_show_cert(pw); 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, identity_comment); #ifdef WITH_OPENSSL if (convert_to) do_convert_to(pw); if (convert_from) do_convert_from(pw); #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, print_generic, opts, nopts); 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, print_generic, opts, nopts); #ifdef WITH_DSA n += do_print_resource_record(pw, _PATH_HOST_DSA_KEY_FILE, rr_hostname, print_generic, opts, nopts); #endif n += do_print_resource_record(pw, _PATH_HOST_ECDSA_KEY_FILE, rr_hostname, print_generic, opts, nopts); n += do_print_resource_record(pw, _PATH_HOST_ED25519_KEY_FILE, rr_hostname, print_generic, opts, nopts); n += do_print_resource_record(pw, _PATH_HOST_XMSS_KEY_FILE, rr_hostname, print_generic, opts, nopts); if (n == 0) fatal("no keys found."); exit(0); } } 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) { do_moduli_gen(argv[0], opts, nopts); return 0; } if (do_screen_candidates) { do_moduli_screen(argv[0], opts, nopts); return 0; } if (gen_all_hostkeys) { do_gen_all_hostkeys(pw); return (0); } if (key_type_name == NULL) key_type_name = DEFAULT_KEY_TYPE_NAME; type = sshkey_type_from_shortname(key_type_name); type_bits_valid(type, key_type_name, &bits); if (!quiet) printf("Generating public/private %s key pair.\n", key_type_name); switch (type) { case KEY_ECDSA_SK: case KEY_ED25519_SK: for (i = 0; i < nopts; i++) { if (strcasecmp(opts[i], "no-touch-required") == 0) { sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; } else if (strcasecmp(opts[i], "verify-required") == 0) { sk_flags |= SSH_SK_USER_VERIFICATION_REQD; } else if (strcasecmp(opts[i], "resident") == 0) { sk_flags |= SSH_SK_RESIDENT_KEY; } else if (strncasecmp(opts[i], "device=", 7) == 0) { sk_device = xstrdup(opts[i] + 7); } else if (strncasecmp(opts[i], "user=", 5) == 0) { sk_user = xstrdup(opts[i] + 5); } else if (strncasecmp(opts[i], "challenge=", 10) == 0) { if ((r = sshbuf_load_file(opts[i] + 10, &challenge)) != 0) { fatal_r(r, "Unable to load FIDO " "enrollment challenge \"%s\"", opts[i] + 10); } } else if (strncasecmp(opts[i], "write-attestation=", 18) == 0) { sk_attestation_path = opts[i] + 18; } else if (strncasecmp(opts[i], "application=", 12) == 0) { sk_application = xstrdup(opts[i] + 12); if (strncmp(sk_application, "ssh:", 4) != 0) { fatal("FIDO application string must " "begin with \"ssh:\""); } } else { fatal("Option \"%s\" is unsupported for " "FIDO authenticator enrollment", opts[i]); } } if ((attest = sshbuf_new()) == NULL) fatal("sshbuf_new failed"); r = 0; for (i = 0 ;;) { if (!quiet) { printf("You may need to touch your " "authenticator%s to authorize key " "generation.\n", r == 0 ? "" : " again"); } 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_BAD_PERMISSIONS && (sk_flags & SSH_SK_RESIDENT_KEY) != 0 && (sk_flags & SSH_SK_FORCE_OPERATION) == 0 && confirm_sk_overwrite(sk_application, sk_user)) { sk_flags |= SSH_SK_FORCE_OPERATION; continue; } if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) fatal_r(r, "Key enrollment failed"); else if (passphrase != NULL) { error("PIN incorrect"); freezero(passphrase, strlen(passphrase)); passphrase = NULL; } if (++i >= 3) fatal("Too many incorrect PINs"); passphrase = read_passphrase("Enter PIN for " "authenticator: ", RP_ALLOW_STDIN); } if (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_r(r, "sshkey_from_private"); if (!have_identity) ask_filename(pw, "Enter file in which to save the key"); /* Create ~/.ssh directory if it doesn't already exist. */ hostfile_create_user_ssh_dir(identity_file, !quiet); /* If the file already exists, ask the user to confirm. */ if (!confirm_overwrite(identity_file)) exit(1); /* Determine the passphrase for the private key */ passphrase = private_key_passphrase(identity_file); if (identity_comment) { strlcpy(comment, identity_comment, sizeof(comment)); } else { /* Create default comment field for the passphrase. */ snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); } /* Save the key with the given passphrase and comment. */ if ((r = sshkey_save_private(private, identity_file, passphrase, comment, private_key_format, openssh_format_cipher, rounds)) != 0) { error_r(r, "Saving key \"%s\" failed", identity_file); freezero(passphrase, strlen(passphrase)); exit(1); } freezero(passphrase, strlen(passphrase)); sshkey_free(private); if (!quiet) { printf("Your identification has been saved in %s\n", identity_file); } strlcat(identity_file, ".pub", sizeof(identity_file)); if ((r = sshkey_save_public(public, identity_file, comment)) != 0) fatal_r(r, "Unable to save public key to %s", identity_file); if (!quiet) { fp = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_DEFAULT); ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal("sshkey_fingerprint failed"); printf("Your public key has been saved in %s\n", identity_file); printf("The key fingerprint is:\n"); printf("%s %s\n", fp, comment); printf("The key's randomart image is:\n"); printf("%s\n", ra); free(ra); free(fp); } if (sk_attestation_path != NULL) save_attestation(attest, sk_attestation_path); sshbuf_free(attest); sshkey_free(public); exit(0); } openssh-10.0p1/PaxHeaders.10889/ssh-keyscan.0100644 001750 001750 0000000003614775415623 0015465xustar0030 atime=1744182234.842601305 openssh-10.0p1/ssh-keyscan.0010064400017500001750000000121171477541562300140520ustar00djmdjmSSH-KEYSCAN(1) General Commands Manual SSH-KEYSCAN(1) NAME ssh-keyscan M-bM-^@M-^S gather SSH public keys from servers SYNOPSIS ssh-keyscan [-46cDHqv] [-f file] [-O option] [-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, the format of which is documented in sshd(8). 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 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. Hosts to be scanned may be specified by hostname, address or by CIDR network range (e.g. 192.168.16/28). If a network range is specified, then all addresses in that range will be scanned. The options are as follows: -4 Force ssh-keyscan to use IPv4 addresses only. -6 Force ssh-keyscan to use IPv6 addresses only. -c Request certificates from target hosts instead of plain keys. -D Print keys found as SSHFP DNS records. The default is to print keys in a format usable as a ssh(1) known_hosts file. -f file Read hosts or M-bM-^@M-^\addrlist namelistM-bM-^@M-^] pairs from file, one per line. If M-bM-^@M-^X-M-bM-^@M-^Y is supplied instead of a filename, ssh-keyscan will read from the standard input. Names read from a file must start with an address, hostname or CIDR network range to be scanned. Addresses and hostnames may optionally be followed by comma- separated name or address aliases that will be copied to the output. For example: 192.168.11.0/24 10.20.1.1 happy.example.org 10.0.0.1,sad.example.org -H Hash all hostnames and addresses in the output. 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. -O option Specify a key/value option. At present, only a single option is supported: hashalg=algorithm Selects a hash algorithm to use when printing SSHFP records using the -D flag. Valid algorithms are M-bM-^@M-^\sha1M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The default is to print both. -p port Connect to port on the remote host. -q Quiet mode: do not print server host name and banners in comments. -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, the connection is closed and the host in question considered unavailable. The default is 5 seconds. -t type Specify the type of the key to fetch from the scanned hosts. The possible values are M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], M-bM-^@M-^\ecdsa-skM-bM-^@M-^], M-bM-^@M-^\ed25519-skM-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^]. Multiple values may be specified by separating them with commas. The default is to fetch all the above key types. -v Verbose mode: print debugging messages about progress. 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 /etc/ssh/ssh_known_hosts EXAMPLES Print the RSA host key for machine hostname: $ ssh-keyscan -t rsa hostname Search a network range, printing all supported key types: $ ssh-keyscan 192.168.0.64/25 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,ecdsa,ed25519 -f ssh_hosts | \ sort -u - ssh_known_hosts | diff ssh_known_hosts - SEE ALSO ssh(1), sshd(8) Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints, RFC 4255, 2006. AUTHORS David Mazieres wrote the initial version, and Wayne Davison added support for protocol version 2. OpenBSD 7.6 June 17, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh-keyscan.1100644 001750 001750 0000000003614775415623 0015466xustar0030 atime=1744182234.842601305 openssh-10.0p1/ssh-keyscan.1010064400017500001750000000113341477541562300140530ustar00djmdjm.\" $OpenBSD: ssh-keyscan.1,v 1.52 2024/06/17 08:30:29 djm Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" .\" Modification and redistribution in source and binary forms is .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" .Dd $Mdocdate: June 17 2024 $ .Dt SSH-KEYSCAN 1 .Os .Sh NAME .Nm ssh-keyscan .Nd gather SSH public keys from servers .Sh SYNOPSIS .Nm ssh-keyscan .Op Fl 46cDHqv .Op Fl f Ar file .Op Fl O Ar option .Op Fl p Ar port .Op Fl T Ar timeout .Op Fl t Ar type .Op Ar host | addrlist namelist .Sh DESCRIPTION .Nm 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, the format of which is documented in .Xr sshd 8 . .Nm provides a minimal interface suitable for use by shell and perl scripts. .Pp .Nm 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 .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. .Pp Hosts to be scanned may be specified by hostname, address or by CIDR network range (e.g. 192.168.16/28). If a network range is specified, then all addresses in that range will be scanned. .Pp The options are as follows: .Bl -tag -width Ds .It Fl 4 Force .Nm to use IPv4 addresses only. .It Fl 6 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 pairs from .Ar file , one per line. If .Sq - is supplied instead of a filename, .Nm will read from the standard input. Names read from a file must start with an address, hostname or CIDR network range to be scanned. Addresses and hostnames may optionally be followed by comma-separated name or address aliases that will be copied to the output. For example: .Bd -literal 192.168.11.0/24 10.20.1.1 happy.example.org 10.0.0.1,sad.example.org .Ed .It Fl H Hash all hostnames and addresses in the output. 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. .It Fl O Ar option Specify a key/value option. At present, only a single option is supported: .Bl -tag -width Ds .It Cm hashalg Ns = Ns Ar algorithm Selects a hash algorithm to use when printing SSHFP records using the .Fl D flag. Valid algorithms are .Dq sha1 and .Dq sha256 . The default is to print both. .El .It Fl p Ar port Connect to .Ar port on the remote host. .It Fl q Quiet mode: do not print server host name and banners in comments. .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, the connection is closed and the host in question considered unavailable. The default is 5 seconds. .It Fl t Ar type Specify the type of the key to fetch from the scanned hosts. The possible values are .Dq ecdsa , .Dq ed25519 , .Dq ecdsa-sk , .Dq ed25519-sk , or .Dq rsa . Multiple values may be specified by separating them with commas. The default is to fetch all the above key types. .It Fl v Verbose mode: print debugging messages about progress. .El .Pp If an ssh_known_hosts file is constructed using .Nm without verifying the keys, users will be vulnerable to .Em man in the middle attacks. On the other hand, if the security model allows such a risk, .Nm 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 .Pa /etc/ssh/ssh_known_hosts .Sh EXAMPLES Print the RSA host key for machine .Ar hostname : .Pp .Dl $ ssh-keyscan -t rsa hostname .Pp Search a network range, printing all supported key types: .Pp .Dl $ ssh-keyscan 192.168.0.64/25 .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 -offset indent $ ssh-keyscan -t rsa,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. openssh-10.0p1/PaxHeaders.10889/ssh-keyscan.c100644 001750 001750 0000000003614775415623 0015550xustar0030 atime=1744182234.843578142 openssh-10.0p1/ssh-keyscan.c010064400017500001750000000462161477541562300141440ustar00djmdjm/* $OpenBSD: ssh-keyscan.c,v 1.165 2024/12/06 15:17:15 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the * OpenBSD project by leaving this copyright notice intact. */ #include "includes.h" #include #include "openbsd-compat/sys-queue.h" #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #ifdef WITH_OPENSSL #include #endif #include #include #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #include "xmalloc.h" #include "ssh.h" #include "sshbuf.h" #include "sshkey.h" #include "cipher.h" #include "digest.h" #include "kex.h" #include "compat.h" #include "myproposal.h" #include "packet.h" #include "dispatch.h" #include "log.h" #include "atomicio.h" #include "misc.h" #include "hostfile.h" #include "ssherr.h" #include "ssh_api.h" #include "dns.h" #include "addr.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. */ int IPv4or6 = AF_UNSPEC; int ssh_port = SSH_DEFAULT_PORT; #define KT_DSA (1) #define KT_RSA (1<<1) #define KT_ECDSA (1<<2) #define KT_ED25519 (1<<3) #define KT_XMSS (1<<4) #define KT_ECDSA_SK (1<<5) #define KT_ED25519_SK (1<<6) #define KT_MIN KT_DSA #define KT_MAX KT_ED25519_SK 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 */ int hashalg = -1; /* Hash for SSHFP records or -1 for all */ int quiet = 0; /* Don't print key comment lines */ #define MAXMAXFD 256 /* The number of seconds after which to give up on a TCP connection */ int timeout = 5; int maxfd; #define MAXCON (maxfd - 10) extern char *__progname; struct pollfd *read_wait; int ncon; /* * Keep a connection structure for each file descriptor. The state * associated with file descriptor n is held in fdcon[n]. */ typedef struct Connection { u_char c_status; /* State of connection on this file desc. */ #define CS_UNUSED 0 /* File descriptor unused */ #define CS_CON 1 /* Waiting to connect/read greeting */ int c_fd; /* Quick lookup: c->c_fd == c - fdcon */ 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 */ char *c_output_name; /* Hostname of connection for output */ struct ssh *c_ssh; /* SSH-connection */ struct timespec c_ts; /* Time at which connection gets aborted */ TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */ } con; TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */ con *fdcon; static void keyprint(con *c, struct sshkey *key); static int fdlim_get(int hard) { #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) struct rlimit rlfd; rlim_t lim; if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1) return -1; lim = hard ? rlfd.rlim_max : rlfd.rlim_cur; if (lim <= 0) return -1; if (lim == RLIM_INFINITY) lim = SSH_SYSFDMAX; if (lim >= INT_MAX) lim = INT_MAX; return lim; #else return (SSH_SYSFDMAX <= 0) ? -1 : ((SSH_SYSFDMAX >= INT_MAX) ? INT_MAX : SSH_SYSFDMAX); #endif } static int fdlim_set(int lim) { #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) struct rlimit rlfd; #endif if (lim <= 0) return (-1); #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1) return (-1); rlfd.rlim_cur = lim; if (setrlimit(RLIMIT_NOFILE, &rlfd) == -1) return (-1); #elif defined (HAVE_SETDTABLESIZE) setdtablesize(lim); #endif return (0); } /* * This is an strsep function that returns a null field for adjacent * separators. This is the same as the 4.4BSD strsep, but different from the * one in the GNU libc. */ static char * xstrsep(char **str, const char *delim) { char *s, *e; if (!**str) return (NULL); s = *str; e = s + strcspn(s, delim); if (*e != '\0') *e++ = '\0'; *str = e; return (s); } /* * Get the next non-null token (like GNU strsep). Strsep() will return a * null token for two adjacent separators, so we may have to loop. */ static char * strnnsep(char **stringp, char *delim) { char *tok; do { tok = xstrsep(stringp, delim); } while (tok && *tok == '\0'); return (tok); } static int key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh) { con *c; if ((c = ssh_get_app_data(ssh)) != NULL) keyprint(c, hostkey); /* always abort key exchange */ return -1; } static int ssh2_capable(int remote_major, int remote_minor) { switch (remote_major) { case 1: if (remote_minor == 99) return 1; break; case 2: return 1; default: break; } return 0; } static void keygrab_ssh2(con *c) { char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; int r; switch (c->c_keytype) { case KT_DSA: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? "ssh-dss-cert-v01@openssh.com" : "ssh-dss"; break; case KT_RSA: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? "rsa-sha2-512-cert-v01@openssh.com," "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] = 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] = kex_gen_client; # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; c->c_ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = 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); } static void keyprint_one(const char *host, struct sshkey *key) { char *hostport = NULL, *hashed = NULL; const char *known_host; int r = 0; found_one = 1; if (print_sshfp) { export_dns_rr(host, key, stdout, 0, hashalg); return; } hostport = put_host_port(host, ssh_port); lowercase(hostport); if (hash_hosts && (hashed = host_hash(hostport, NULL, 0)) == NULL) fatal("host_hash failed"); known_host = hash_hosts ? hashed : hostport; if (!get_cert) r = fprintf(stdout, "%s ", known_host); if (r >= 0 && sshkey_write(key, stdout) == 0) (void)fputs("\n", stdout); free(hashed); 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 tcpconnect(char *host) { struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr, s = -1; snprintf(strport, sizeof strport, "%d", ssh_port); memset(&hints, 0, sizeof(hints)); hints.ai_family = IPv4or6; hints.ai_socktype = SOCK_STREAM; if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { error("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); return -1; } for (ai = aitop; ai; ai = ai->ai_next) { s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s == -1) { error("socket: %s", strerror(errno)); continue; } if (set_nonblock(s) == -1) fatal_f("set_nonblock(%d)", s); if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1 && errno != EINPROGRESS) error("connect (`%s'): %s", host, strerror(errno)); else break; close(s); s = -1; } freeaddrinfo(aitop); return s; } static int conalloc(const char *iname, const char *oname, int keytype) { char *namebase, *name, *namelist; int s; namebase = namelist = xstrdup(iname); do { name = xstrsep(&namelist, ","); if (!name) { free(namebase); return (-1); } } while ((s = tcpconnect(name)) < 0); if (s >= maxfd) fatal("conalloc: fdno %d too high", s); if (fdcon[s].c_status) fatal("conalloc: attempt to reuse fdno %d", s); debug3_f("oname %s kt %d", oname, keytype); fdcon[s].c_fd = s; fdcon[s].c_status = CS_CON; fdcon[s].c_namebase = namebase; fdcon[s].c_name = name; fdcon[s].c_namelist = namelist; fdcon[s].c_output_name = xstrdup(oname); fdcon[s].c_keytype = keytype; monotime_ts(&fdcon[s].c_ts); fdcon[s].c_ts.tv_sec += timeout; TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); read_wait[s].fd = s; read_wait[s].events = POLLIN; ncon++; return (s); } static void confree(int s) { if (s >= maxfd || fdcon[s].c_status == CS_UNUSED) fatal("confree: attempt to free bad fdno %d", s); free(fdcon[s].c_namebase); free(fdcon[s].c_output_name); fdcon[s].c_status = CS_UNUSED; fdcon[s].c_keytype = 0; if (fdcon[s].c_ssh) { 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); read_wait[s].fd = -1; read_wait[s].events = 0; ncon--; } static int conrecycle(int s) { con *c = &fdcon[s]; int ret; ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); confree(s); return (ret); } static void congreet(int s) { int n = 0, remote_major = 0, remote_minor = 0; char buf[256], *cp; char remote_version[sizeof buf]; 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; } /* * Read the server banner as per RFC4253 section 4.2. The "SSH-" * protocol identification string may be preceded by an arbitrarily * large banner which we must read and ignore. Loop while reading * newline-terminated lines until we have one starting with "SSH-". * The ID string cannot be longer than 255 characters although the * preceding banner lines may (in which case they'll be discarded * in multiple iterations of the outer loop). */ for (;;) { memset(buf, '\0', sizeof(buf)); bufsiz = sizeof(buf); cp = buf; while (bufsiz-- && (n = atomicio(read, s, cp, 1)) == 1 && *cp != '\n') { if (*cp == '\r') *cp = '\n'; cp++; } if (n != 1 || strncmp(buf, "SSH-", 4) == 0) break; } if (n == 0) { switch (errno) { case EPIPE: error("%s: Connection closed by remote host", c->c_name); break; case ECONNREFUSED: break; default: error("read (%s): %s", c->c_name, strerror(errno)); break; } conrecycle(s); return; } if (cp >= buf + sizeof(buf)) { error("%s: greeting exceeds allowable length", c->c_name); confree(s); return; } if (*cp != '\n' && *cp != '\r') { error("%s: bad greeting", c->c_name); confree(s); return; } *cp = '\0'; if ((c->c_ssh = ssh_packet_set_connection(NULL, s, s)) == NULL) fatal("ssh_packet_set_connection failed"); ssh_packet_set_timeout(c->c_ssh, timeout, 1); ssh_set_app_data(c->c_ssh, c); /* back link */ c->c_ssh->compat = 0; if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) == 3) compat_banner(c->c_ssh, remote_version); if (!ssh2_capable(remote_major, remote_minor)) { debug("%s doesn't support ssh2", c->c_name); confree(s); return; } if (!quiet) { fprintf(stdout, "%c %s:%d %s\n", print_sshfp ? ';' : '#', c->c_name, ssh_port, chop(buf)); } keygrab_ssh2(c); confree(s); } static void conread(int s) { con *c = &fdcon[s]; if (c->c_status != CS_CON) fatal("conread: invalid status %d", c->c_status); congreet(s); } static void conloop(void) { struct timespec seltime, now; con *c; int i; monotime_ts(&now); c = TAILQ_FIRST(&tq); if (c && timespeccmp(&c->c_ts, &now, >)) timespecsub(&c->c_ts, &now, &seltime); else timespecclear(&seltime); while (ppoll(read_wait, maxfd, &seltime, NULL) == -1) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) continue; error("poll error"); } for (i = 0; i < maxfd; i++) { if (read_wait[i].revents & (POLLHUP|POLLERR|POLLNVAL)) confree(i); else if (read_wait[i].revents & (POLLIN)) conread(i); } c = TAILQ_FIRST(&tq); while (c && timespeccmp(&c->c_ts, &now, <)) { int s = c->c_fd; c = TAILQ_NEXT(c, c_link); conrecycle(s); } } static void do_one_host(char *host) { char *name = strnnsep(&host, " \t\n"); int j; if (name == NULL) return; for (j = KT_MIN; j <= KT_MAX; j *= 2) { if (get_keytypes & j) { while (ncon >= MAXCON) conloop(); conalloc(name, *host ? host : name, j); } } } static void do_host(char *host) { char daddr[128]; struct xaddr addr, end_addr; u_int masklen; if (host == NULL) return; if (addr_pton_cidr(host, &addr, &masklen) != 0) { /* Assume argument is a hostname */ do_one_host(host); } else { /* Argument is a CIDR range */ debug("CIDR range %s", host); end_addr = addr; if (addr_host_to_all1s(&end_addr, masklen) != 0) goto badaddr; /* * Note: we deliberately include the all-zero/ones addresses. */ for (;;) { if (addr_ntop(&addr, daddr, sizeof(daddr)) != 0) { badaddr: error("Invalid address %s", host); return; } debug("CIDR expand: address %s", daddr); do_one_host(daddr); if (addr_cmp(&addr, &end_addr) == 0) break; addr_increment(&addr); } } } static void usage(void) { fprintf(stderr, "usage: ssh-keyscan [-46cDHqv] [-f file] [-O option] [-p port] [-T timeout]\n" " [-t type] [host | addrlist namelist]\n"); exit(1); } int main(int argc, char **argv) { int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO; int opt, fopt_count = 0, j; char *tname, *cp, *line = NULL; size_t linesize = 0; FILE *fp; extern int optind; extern char *optarg; __progname = ssh_get_progname(argv[0]); seed_rng(); TAILQ_INIT(&tq); /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); if (argc <= 1) usage(); while ((opt = getopt(argc, argv, "cDHqv46O:p: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) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(1); } break; case 'T': timeout = convtime(optarg); if (timeout == -1 || timeout == 0) { fprintf(stderr, "Bad timeout '%s'\n", optarg); usage(); } break; case 'v': if (!debug_flag) { debug_flag = 1; log_level = SYSLOG_LEVEL_DEBUG1; } else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; else fatal("Too high debugging level."); break; case 'q': quiet = 1; break; case 'f': if (strcmp(optarg, "-") == 0) optarg = NULL; argv[fopt_count++] = optarg; break; case 'O': /* Maybe other misc options in the future too */ if (strncmp(optarg, "hashalg=", 8) != 0) fatal("Unsupported -O option"); if ((hashalg = ssh_digest_alg_by_name( optarg + 8)) == -1) fatal("Unsupported hash algorithm"); break; case 't': get_keytypes = 0; tname = strtok(optarg, ","); while (tname) { int type = sshkey_type_from_shortname(tname); switch (type) { #ifdef WITH_DSA case KEY_DSA: get_keytypes |= KT_DSA; break; #endif case KEY_ECDSA: get_keytypes |= KT_ECDSA; break; case KEY_RSA: get_keytypes |= KT_RSA; break; 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: default: fatal("Unknown key type \"%s\"", tname); } tname = strtok(NULL, ","); } break; case '4': IPv4or6 = AF_INET; break; case '6': IPv4or6 = AF_INET6; break; default: usage(); } } if (optind == argc && !fopt_count) usage(); log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1); maxfd = fdlim_get(1); if (maxfd < 0) fatal("%s: fdlim_get: bad value", __progname); if (maxfd > MAXMAXFD) maxfd = MAXMAXFD; if (MAXCON <= 0) fatal("%s: not enough file descriptors", __progname); if (maxfd > fdlim_get(0)) fdlim_set(maxfd); fdcon = xcalloc(maxfd, sizeof(con)); read_wait = xcalloc(maxfd, sizeof(struct pollfd)); for (j = 0; j < maxfd; j++) read_wait[j].fd = -1; ssh_signal(SIGPIPE, SIG_IGN); for (j = 0; j < fopt_count; j++) { if (argv[j] == NULL) fp = stdin; else if ((fp = fopen(argv[j], "r")) == NULL) fatal("%s: %s: %s", __progname, fp == stdin ? "" : argv[j], strerror(errno)); while (getline(&line, &linesize, fp) != -1) { /* Chomp off trailing whitespace and comments */ if ((cp = strchr(line, '#')) == NULL) cp = line + strlen(line) - 1; while (cp >= line) { if (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '#') *cp-- = '\0'; else break; } /* Skip empty lines */ if (*line == '\0') continue; do_host(line); } if (ferror(fp)) fatal("%s: %s: %s", __progname, fp == stdin ? "" : argv[j], strerror(errno)); if (fp != stdin) fclose(fp); } free(line); while (optind < argc) do_host(argv[optind++]); while (ncon > 0) conloop(); return found_one ? 0 : 1; } openssh-10.0p1/PaxHeaders.10889/ssh-keysign.0100644 001750 001750 0000000003614775415623 0015501xustar0030 atime=1744182234.843578142 openssh-10.0p1/ssh-keysign.0010064400017500001750000000033661477541562300140740ustar00djmdjmSSH-KEYSIGN(8) System Manager's Manual SSH-KEYSIGN(8) NAME ssh-keysign M-bM-^@M-^S OpenSSH helper 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. 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_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_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 OpenBSD 7.6 June 17, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh-keysign.8100644 001750 001750 0000000003614775415623 0015511xustar0030 atime=1744182234.843578142 openssh-10.0p1/ssh-keysign.8010064400017500001750000000055711477541562300141040ustar00djmdjm.\" $OpenBSD: ssh-keysign.8,v 1.18 2024/06/17 08:30:29 djm Exp $ .\" .\" Copyright (c) 2002 Markus Friedl. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .Dd $Mdocdate: June 17 2024 $ .Dt SSH-KEYSIGN 8 .Os .Sh NAME .Nm ssh-keysign .Nd OpenSSH helper for host-based authentication .Sh SYNOPSIS .Nm .Sh DESCRIPTION .Nm is used by .Xr ssh 1 to access the local host keys and generate the digital signature required during host-based authentication. .Pp .Nm is disabled by default and can only be enabled in the global client configuration file .Pa /etc/ssh/ssh_config by setting .Cm EnableSSHKeysign to .Dq yes . .Pp .Nm is not intended to be invoked by the user, but from .Xr ssh 1 . See .Xr ssh 1 and .Xr sshd 8 for more information about host-based authentication. .Sh FILES .Bl -tag -width Ds -compact .It Pa /etc/ssh/ssh_config Controls whether .Nm is enabled. .Pp .It Pa /etc/ssh/ssh_host_ecdsa_key .It Pa /etc/ssh/ssh_host_ed25519_key .It Pa /etc/ssh/ssh_host_rsa_key These files contain the private parts of the host keys 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, .Nm must be set-uid root if host-based authentication is used. .Pp .It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub .It Pa /etc/ssh/ssh_host_ed25519_key-cert.pub .It Pa /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. .El .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-keygen 1 , .Xr ssh_config 5 , .Xr sshd 8 .Sh HISTORY .Nm first appeared in .Ox 3.2 . .Sh AUTHORS .An Markus Friedl Aq Mt markus@openbsd.org openssh-10.0p1/PaxHeaders.10889/ssh-keysign.c100644 001750 001750 0000000003614775415623 0015564xustar0030 atime=1744182234.843578142 openssh-10.0p1/ssh-keysign.c010064400017500001750000000201611477541562300141470ustar00djmdjm/* $OpenBSD: ssh-keysign.c,v 1.75 2025/02/15 01:48:30 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #ifdef HAVE_PATHS_H #include #endif #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #include #include "openbsd-compat/openssl-compat.h" #endif #include "xmalloc.h" #include "log.h" #include "sshkey.h" #include "ssh.h" #include "ssh2.h" #include "misc.h" #include "sshbuf.h" #include "authfile.h" #include "msg.h" #include "canohost.h" #include "pathnames.h" #include "readconf.h" #include "uidswap.h" #include "ssherr.h" extern char *__progname; static int valid_request(struct passwd *pw, char *host, struct sshkey **ret, char **pkalgp, u_char *data, size_t datalen) { struct sshbuf *b; struct sshkey *key = NULL; u_char type, *pkblob; char *p; size_t blen, len; char *pkalg, *luser; int r, pktype, fail; if (ret != NULL) *ret = NULL; if (pkalgp != NULL) *pkalgp = NULL; fail = 0; if ((b = sshbuf_from(data, datalen)) == NULL) fatal_f("sshbuf_from failed"); /* session id */ if ((r = sshbuf_get_string(b, NULL, &len)) != 0) fatal_fr(r, "parse session ID"); if (len != 20 && /* SHA1 */ len != 32 && /* SHA256 */ len != 48 && /* SHA384 */ len != 64) /* SHA512 */ fail++; if ((r = sshbuf_get_u8(b, &type)) != 0) fatal_fr(r, "parse type"); if (type != SSH2_MSG_USERAUTH_REQUEST) fail++; /* server user */ if ((r = sshbuf_skip_string(b)) != 0) fatal_fr(r, "parse user"); /* service */ if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0) fatal_fr(r, "parse service"); if (strcmp("ssh-connection", p) != 0) fail++; free(p); /* method */ if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0) fatal_fr(r, "parse method"); if (strcmp("hostbased", p) != 0) fail++; free(p); /* pubkey */ if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || (r = sshbuf_get_string(b, &pkblob, &blen)) != 0) fatal_fr(r, "parse pk"); pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) fail++; else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { error_fr(r, "decode key"); fail++; } else if (key->type != pktype) fail++; /* client host name, handle trailing dot */ if ((r = sshbuf_get_cstring(b, &p, &len)) != 0) fatal_fr(r, "parse hostname"); debug2_f("check expect chost %s got %s", host, p); if (strlen(host) != len - 1) fail++; else if (p[len - 1] != '.') fail++; else if (strncasecmp(host, p, len - 1) != 0) fail++; free(p); /* local user */ if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0) fatal_fr(r, "parse luser"); if (strcmp(pw->pw_name, luser) != 0) fail++; free(luser); /* end of message */ if (sshbuf_len(b) != 0) fail++; sshbuf_free(b); debug3_f("fail %d", fail); if (!fail) { if (ret != NULL) { *ret = key; key = NULL; } if (pkalgp != NULL) { *pkalgp = pkalg; pkalg = NULL; } } sshkey_free(key); free(pkalg); free(pkblob); return (fail ? -1 : 0); } int main(int argc, char **argv) { struct sshbuf *b; Options options; #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, *pkalg; size_t slen, dlen; 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) exit(1); /* Leave /dev/null fd iff it is attached to stderr */ if (fd > 2) close(fd); for (i = 0; i < NUM_KEYTYPES; i++) key_fd[i] = -1; i = 0; /* XXX This really needs to read sshd_config for the paths */ #ifdef WITH_DSA key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); #endif key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_XMSS_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY); if ((pw = getpwuid(getuid())) == NULL) fatal("getpwuid failed"); pw = pwcopy(pw); permanently_set_uid(pw); seed_rng(); #ifdef DEBUG_SSH_KEYSIGN log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); #endif /* verify that ssh-keysign is enabled by the admin */ initialize_options(&options); (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", "", &options, 0, NULL); (void)fill_default_options(&options); if (options.enable_ssh_keysign != 1) fatal("ssh-keysign not enabled in %s", _PATH_HOST_CONFIG_FILE); if (pledge("stdio dns", NULL) != 0) fatal("%s: pledge: %s", __progname, strerror(errno)); for (i = found = 0; i < NUM_KEYTYPES; i++) { if (key_fd[i] != -1) found = 1; } if (found == 0) fatal("could not open any host key"); found = 0; for (i = 0; i < NUM_KEYTYPES; i++) { keys[i] = NULL; if (key_fd[i] == -1) continue; r = sshkey_load_private_type_fd(key_fd[i], KEY_UNSPEC, NULL, &key, NULL); close(key_fd[i]); if (r != 0) debug_r(r, "parse key %d", i); else if (key != NULL) { keys[i] = key; found = 1; } } if (!found) fatal("no hostkey found"); if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if (ssh_msg_recv(STDIN_FILENO, b) < 0) fatal("%s: ssh_msg_recv failed", __progname); if ((r = sshbuf_get_u8(b, &rver)) != 0) fatal_r(r, "%s: buffer error", __progname); if (rver != version) fatal("%s: bad version: received %d, expected %d", __progname, rver, version); if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0) fatal_r(r, "%s: buffer error", __progname); if (fd <= STDERR_FILENO) fatal("%s: bad fd = %d", __progname, fd); if ((host = get_local_name(fd)) == NULL) fatal("%s: cannot get local name for fd", __progname); if ((r = sshbuf_get_string(b, &data, &dlen)) != 0) fatal_r(r, "%s: buffer error", __progname); if (valid_request(pw, host, &key, &pkalg, data, dlen) < 0) fatal("%s: not a valid request", __progname); free(host); found = 0; for (i = 0; i < NUM_KEYTYPES; i++) { if (keys[i] != NULL && sshkey_equal_public(key, keys[i])) { found = 1; break; } } if (!found) { if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal("%s: sshkey_fingerprint failed", __progname); fatal("%s: no matching hostkey found for key %s %s", __progname, sshkey_type(key), fp ? fp : ""); } if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, pkalg, NULL, NULL, 0)) != 0) fatal_r(r, "%s: sshkey_sign failed", __progname); free(data); /* send reply */ sshbuf_reset(b); if ((r = sshbuf_put_string(b, signature, slen)) != 0) fatal_r(r, "%s: buffer error", __progname); if (ssh_msg_send(STDOUT_FILENO, version, b) == -1) fatal("%s: ssh_msg_send failed", __progname); return (0); } openssh-10.0p1/PaxHeaders.10889/ssh-pkcs11-client.c100644 001750 001750 0000000003614775415623 0016471xustar0030 atime=1744182234.844557134 openssh-10.0p1/ssh-pkcs11-client.c010064400017500001750000000454431477541562300150660ustar00djmdjm/* $OpenBSD: ssh-pkcs11-client.c,v 1.20 2024/08/15 00:51:51 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef ENABLE_PKCS11 #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #include #include #include "pathnames.h" #include "xmalloc.h" #include "sshbuf.h" #include "log.h" #include "misc.h" #include "sshkey.h" #include "authfd.h" #include "atomicio.h" #include "ssh-pkcs11.h" #include "ssherr.h" #include "openbsd-compat/openssl-compat.h" #if !defined(OPENSSL_HAS_ECC) || !defined(HAVE_EC_KEY_METHOD_NEW) #define EC_KEY_METHOD void #define EC_KEY void #endif /* borrows code from sftp-server and ssh-agent */ /* * Maintain a list of ssh-pkcs11-helper subprocesses. These may be looked up * by provider path or their unique EC/RSA METHOD pointers. */ struct helper { char *path; pid_t pid; int fd; RSA_METHOD *rsa_meth; EC_KEY_METHOD *ec_meth; int (*rsa_finish)(RSA *rsa); void (*ec_finish)(EC_KEY *key); size_t nrsa, nec; /* number of active keys of each type */ }; static struct helper **helpers; static size_t nhelpers; static struct helper * helper_by_provider(const char *path) { size_t i; for (i = 0; i < nhelpers; i++) { if (helpers[i] == NULL || helpers[i]->path == NULL || helpers[i]->fd == -1) continue; if (strcmp(helpers[i]->path, path) == 0) return helpers[i]; } return NULL; } static struct helper * helper_by_rsa(const RSA *rsa) { size_t i; const RSA_METHOD *meth; if ((meth = RSA_get_method(rsa)) == NULL) return NULL; for (i = 0; i < nhelpers; i++) { if (helpers[i] != NULL && helpers[i]->rsa_meth == meth) return helpers[i]; } return NULL; } #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) static struct helper * helper_by_ec(const EC_KEY *ec) { size_t i; const EC_KEY_METHOD *meth; if ((meth = EC_KEY_get_method(ec)) == NULL) return NULL; for (i = 0; i < nhelpers; i++) { if (helpers[i] != NULL && helpers[i]->ec_meth == meth) return helpers[i]; } return NULL; } #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ static void helper_free(struct helper *helper) { size_t i; int found = 0; if (helper == NULL) return; if (helper->path == NULL || helper->ec_meth == NULL || helper->rsa_meth == NULL) fatal_f("inconsistent helper"); debug3_f("free helper for provider %s", helper->path); for (i = 0; i < nhelpers; i++) { if (helpers[i] == helper) { if (found) fatal_f("helper recorded more than once"); found = 1; } else if (found) helpers[i - 1] = helpers[i]; } if (found) { helpers = xrecallocarray(helpers, nhelpers, nhelpers - 1, sizeof(*helpers)); nhelpers--; } free(helper->path); #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) EC_KEY_METHOD_free(helper->ec_meth); #endif RSA_meth_free(helper->rsa_meth); free(helper); } static void helper_terminate(struct helper *helper) { if (helper == NULL) { return; } else if (helper->fd == -1) { debug3_f("already terminated"); } else { debug3_f("terminating helper for %s; " "remaining %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); close(helper->fd); /* XXX waitpid() */ helper->fd = -1; helper->pid = -1; } /* * Don't delete the helper entry until there are no remaining keys * that reference it. Otherwise, any signing operation would call * a free'd METHOD pointer and that would be bad. */ if (helper->nrsa == 0 && helper->nec == 0) helper_free(helper); } static void send_msg(int fd, struct sshbuf *m) { u_char buf[4]; size_t mlen = sshbuf_len(m); int r; if (fd == -1) return; POKE_U32(buf, mlen); if (atomicio(vwrite, fd, buf, 4) != 4 || atomicio(vwrite, fd, sshbuf_mutable_ptr(m), sshbuf_len(m)) != sshbuf_len(m)) error("write to helper failed"); if ((r = sshbuf_consume(m, mlen)) != 0) fatal_fr(r, "consume"); } static int recv_msg(int fd, struct sshbuf *m) { u_int l, len; u_char c, buf[1024]; int r; sshbuf_reset(m); if (fd == -1) return 0; /* XXX */ if ((len = atomicio(read, fd, buf, 4)) != 4) { error("read from helper failed: %u", len); return (0); /* XXX */ } len = PEEK_U32(buf); if (len > 256 * 1024) fatal("response too long: %u", len); /* read len bytes into m */ while (len > 0) { l = len; if (l > sizeof(buf)) l = sizeof(buf); if (atomicio(read, fd, buf, l) != l) { error("response from helper failed."); return (0); /* XXX */ } if ((r = sshbuf_put(m, buf, l)) != 0) fatal_fr(r, "sshbuf_put"); len -= l; } if ((r = sshbuf_get_u8(m, &c)) != 0) fatal_fr(r, "parse type"); return c; } int pkcs11_init(int interactive) { return 0; } void pkcs11_terminate(void) { size_t i; debug3_f("terminating %zu helpers", nhelpers); for (i = 0; i < nhelpers; i++) helper_terminate(helpers[i]); } static int rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) { struct sshkey *key = NULL; struct sshbuf *msg = NULL; u_char *blob = NULL, *signature = NULL; size_t blen, slen = 0; int r, ret = -1; struct helper *helper; if ((helper = helper_by_rsa(rsa)) == NULL || helper->fd == -1) fatal_f("no helper for PKCS11 key"); debug3_f("signing with PKCS11 provider %s", helper->path); if (padding != RSA_PKCS1_PADDING) goto fail; if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { error_f("sshkey_new failed"); goto fail; } if ((key->pkey = EVP_PKEY_new()) == NULL || EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) { error_f("pkey setup failed"); goto fail; } key->type = KEY_RSA; if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { error_fr(r, "encode key"); goto fail; } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0 || (r = sshbuf_put_string(msg, from, flen)) != 0 || (r = sshbuf_put_u32(msg, 0)) != 0) fatal_fr(r, "compose"); send_msg(helper->fd, msg); sshbuf_reset(msg); if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) fatal_fr(r, "parse"); if (slen <= (size_t)RSA_size(rsa)) { memcpy(to, signature, slen); ret = slen; } free(signature); } fail: free(blob); sshkey_free(key); sshbuf_free(msg); return (ret); } static int rsa_finish(RSA *rsa) { struct helper *helper; if ((helper = helper_by_rsa(rsa)) == NULL) fatal_f("no helper for PKCS11 key"); debug3_f("free PKCS11 RSA key for provider %s", helper->path); if (helper->rsa_finish != NULL) helper->rsa_finish(rsa); if (helper->nrsa == 0) fatal_f("RSA refcount error"); helper->nrsa--; debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); if (helper->nrsa == 0 && helper->nec == 0) helper_terminate(helper); return 1; } #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) static ECDSA_SIG * ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, const BIGNUM *rp, EC_KEY *ec) { struct sshkey *key = NULL; struct sshbuf *msg = NULL; ECDSA_SIG *ret = NULL; const u_char *cp; u_char *blob = NULL, *signature = NULL; size_t blen, slen = 0; int r, nid; struct helper *helper; if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1) fatal_f("no helper for PKCS11 key"); debug3_f("signing with PKCS11 provider %s", helper->path); if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { error_f("sshkey_new failed"); goto fail; } if ((key->pkey = EVP_PKEY_new()) == NULL || EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) { error("pkey setup failed"); goto fail; } if ((nid = sshkey_ecdsa_pkey_to_nid(key->pkey)) < 0) { error("couldn't get curve nid"); goto fail; } key->ecdsa_nid = nid; key->type = KEY_ECDSA; if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { error_fr(r, "encode key"); goto fail; } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0 || (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 || (r = sshbuf_put_u32(msg, 0)) != 0) fatal_fr(r, "compose"); send_msg(helper->fd, msg); sshbuf_reset(msg); if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) fatal_fr(r, "parse"); cp = signature; ret = d2i_ECDSA_SIG(NULL, &cp, slen); free(signature); } fail: free(blob); sshkey_free(key); sshbuf_free(msg); return (ret); } static void ecdsa_do_finish(EC_KEY *ec) { struct helper *helper; if ((helper = helper_by_ec(ec)) == NULL) fatal_f("no helper for PKCS11 key"); debug3_f("free PKCS11 ECDSA key for provider %s", helper->path); if (helper->ec_finish != NULL) helper->ec_finish(ec); if (helper->nec == 0) fatal_f("ECDSA refcount error"); helper->nec--; debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); if (helper->nrsa == 0 && helper->nec == 0) helper_terminate(helper); } #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ /* redirect private key crypto operations to the ssh-pkcs11-helper */ static void wrap_key(struct helper *helper, struct sshkey *k) { RSA *rsa = NULL; EC_KEY *ecdsa = NULL; debug3_f("wrap %s for provider %s", sshkey_type(k), helper->path); if (k->type == KEY_RSA) { if ((rsa = EVP_PKEY_get1_RSA(k->pkey)) == NULL) fatal_f("no RSA key"); if (RSA_set_method(rsa, helper->rsa_meth) != 1) fatal_f("RSA_set_method failed"); if (helper->nrsa++ >= INT_MAX) fatal_f("RSA refcount error"); if (EVP_PKEY_set1_RSA(k->pkey, rsa) != 1) fatal_f("EVP_PKEY_set1_RSA failed"); RSA_free(rsa); #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) } else if (k->type == KEY_ECDSA) { if ((ecdsa = EVP_PKEY_get1_EC_KEY(k->pkey)) == NULL) fatal_f("no ECDSA key"); if (EC_KEY_set_method(ecdsa, helper->ec_meth) != 1) fatal_f("EC_KEY_set_method failed"); if (helper->nec++ >= INT_MAX) fatal_f("EC refcount error"); if (EVP_PKEY_set1_EC_KEY(k->pkey, ecdsa) != 1) fatal_f("EVP_PKEY_set1_EC_KEY failed"); EC_KEY_free(ecdsa); #endif } else fatal_f("unknown key type"); k->flags |= SSHKEY_FLAG_EXT; debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); } /* * Make a private PKCS#11-backed certificate by grafting a previously-loaded * PKCS#11 private key and a public certificate key. */ int pkcs11_make_cert(const struct sshkey *priv, const struct sshkey *certpub, struct sshkey **certprivp) { struct helper *helper = NULL; struct sshkey *ret; int r; RSA *rsa_priv = NULL, *rsa_cert = NULL; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) EC_KEY *ec_priv = NULL, *ec_cert = NULL; #endif debug3_f("private key type %s cert type %s", sshkey_type(priv), sshkey_type(certpub)); *certprivp = NULL; if (!sshkey_is_cert(certpub) || sshkey_is_cert(priv) || !sshkey_equal_public(priv, certpub)) { error_f("private key %s doesn't match cert %s", sshkey_type(priv), sshkey_type(certpub)); return SSH_ERR_INVALID_ARGUMENT; } *certprivp = NULL; if (priv->type == KEY_RSA) { if ((rsa_priv = EVP_PKEY_get1_RSA(priv->pkey)) == NULL) fatal_f("no RSA pkey"); if ((helper = helper_by_rsa(rsa_priv)) == NULL || helper->fd == -1) fatal_f("no helper for PKCS11 RSA key"); if ((r = sshkey_from_private(priv, &ret)) != 0) fatal_fr(r, "copy key"); if ((rsa_cert = EVP_PKEY_get1_RSA(ret->pkey)) == NULL) fatal_f("no RSA cert pkey"); if (RSA_set_method(rsa_cert, helper->rsa_meth) != 1) fatal_f("RSA_set_method failed"); if (helper->nrsa++ >= INT_MAX) fatal_f("RSA refcount error"); if (EVP_PKEY_set1_RSA(ret->pkey, rsa_cert) != 1) fatal_f("EVP_PKEY_set1_RSA failed"); RSA_free(rsa_priv); RSA_free(rsa_cert); #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) } else if (priv->type == KEY_ECDSA) { if ((ec_priv = EVP_PKEY_get1_EC_KEY(priv->pkey)) == NULL) fatal_f("no EC pkey"); if ((helper = helper_by_ec(ec_priv)) == NULL || helper->fd == -1) fatal_f("no helper for PKCS11 EC key"); if ((r = sshkey_from_private(priv, &ret)) != 0) fatal_fr(r, "copy key"); if ((ec_cert = EVP_PKEY_get1_EC_KEY(ret->pkey)) == NULL) fatal_f("no EC cert pkey"); if (EC_KEY_set_method(ec_cert, helper->ec_meth) != 1) fatal_f("EC_KEY_set_method failed"); if (helper->nec++ >= INT_MAX) fatal_f("EC refcount error"); if (EVP_PKEY_set1_EC_KEY(ret->pkey, ec_cert) != 1) fatal_f("EVP_PKEY_set1_EC_KEY failed"); EC_KEY_free(ec_priv); EC_KEY_free(ec_cert); #endif } else fatal_f("unknown key type %s", sshkey_type(priv)); ret->flags |= SSHKEY_FLAG_EXT; if ((r = sshkey_to_certified(ret)) != 0 || (r = sshkey_cert_copy(certpub, ret)) != 0) fatal_fr(r, "graft certificate"); debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); /* success */ *certprivp = ret; return 0; } static int pkcs11_start_helper_methods(struct helper *helper) { RSA_METHOD *rsa_meth = NULL; EC_KEY_METHOD *ec_meth = NULL; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) int (*ec_init)(EC_KEY *key); int (*ec_copy)(EC_KEY *dest, const EC_KEY *src); int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp); int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key); int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key); int (*ec_sign)(int, const unsigned char *, int, unsigned char *, unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL) return -1; EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL); EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign); EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish, &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public); EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish, ec_copy, ec_set_group, ec_set_private, ec_set_public); #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL) fatal_f("RSA_meth_dup failed"); helper->rsa_finish = RSA_meth_get_finish(rsa_meth); if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") || !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) || !RSA_meth_set_finish(rsa_meth, rsa_finish)) fatal_f("failed to prepare method"); helper->ec_meth = ec_meth; helper->rsa_meth = rsa_meth; return 0; } static struct helper * pkcs11_start_helper(const char *path) { int pair[2]; char *prog, *verbosity = NULL; struct helper *helper; pid_t pid; if (nhelpers >= INT_MAX) fatal_f("too many helpers"); debug3_f("start helper for %s", path); if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { error_f("socketpair: %s", strerror(errno)); return NULL; } helper = xcalloc(1, sizeof(*helper)); if (pkcs11_start_helper_methods(helper) == -1) { error_f("pkcs11_start_helper_methods failed"); goto fail; } if ((pid = fork()) == -1) { error_f("fork: %s", strerror(errno)); fail: close(pair[0]); close(pair[1]); RSA_meth_free(helper->rsa_meth); #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) EC_KEY_METHOD_free(helper->ec_meth); #endif free(helper); return NULL; } else if (pid == 0) { if ((dup2(pair[1], STDIN_FILENO) == -1) || (dup2(pair[1], STDOUT_FILENO) == -1)) { fprintf(stderr, "dup2: %s\n", strerror(errno)); _exit(1); } close(pair[0]); close(pair[1]); prog = getenv("SSH_PKCS11_HELPER"); if (prog == NULL || strlen(prog) == 0) prog = _PATH_SSH_PKCS11_HELPER; if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) verbosity = "-vvv"; debug_f("starting %s %s", prog, verbosity == NULL ? "" : verbosity); execlp(prog, prog, verbosity, (char *)NULL); fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno)); _exit(1); } close(pair[1]); helper->fd = pair[0]; helper->path = xstrdup(path); helper->pid = pid; debug3_f("helper %zu for \"%s\" on fd %d pid %ld", nhelpers, helper->path, helper->fd, (long)helper->pid); helpers = xrecallocarray(helpers, nhelpers, nhelpers + 1, sizeof(*helpers)); helpers[nhelpers++] = helper; return helper; } int pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, char ***labelsp) { struct sshkey *k; int r, type; u_char *blob; char *label; size_t blen; u_int nkeys, i; struct sshbuf *msg; struct helper *helper; if ((helper = helper_by_provider(name)) == NULL && (helper = pkcs11_start_helper(name)) == NULL) return -1; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 || (r = sshbuf_put_cstring(msg, name)) != 0 || (r = sshbuf_put_cstring(msg, pin)) != 0) fatal_fr(r, "compose"); send_msg(helper->fd, msg); sshbuf_reset(msg); type = recv_msg(helper->fd, msg); if (type == SSH2_AGENT_IDENTITIES_ANSWER) { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) fatal_fr(r, "parse nkeys"); *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); if (labelsp) *labelsp = xcalloc(nkeys, sizeof(char *)); for (i = 0; i < nkeys; i++) { /* XXX clean up properly instead of fatal() */ if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || (r = sshbuf_get_cstring(msg, &label, NULL)) != 0) fatal_fr(r, "parse key"); if ((r = sshkey_from_blob(blob, blen, &k)) != 0) fatal_fr(r, "decode key"); wrap_key(helper, k); (*keysp)[i] = k; if (labelsp) (*labelsp)[i] = label; else free(label); free(blob); } } else if (type == SSH2_AGENT_FAILURE) { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) nkeys = -1; } else { nkeys = -1; } sshbuf_free(msg); return (nkeys); } int pkcs11_del_provider(char *name) { struct helper *helper; /* * ssh-agent deletes keys before calling this, so the helper entry * should be gone before we get here. */ debug3_f("delete %s", name); if ((helper = helper_by_provider(name)) != NULL) helper_terminate(helper); return 0; } #endif /* ENABLE_PKCS11 */ openssh-10.0p1/PaxHeaders.10889/ssh-pkcs11-helper.0100644 001750 001750 0000000003614775415623 0016407xustar0030 atime=1744182234.844557134 openssh-10.0p1/ssh-pkcs11-helper.0010064400017500001750000000021511477541562300147710ustar00djmdjmSSH-PKCS11-HELPER(8) System Manager's Manual SSH-PKCS11-HELPER(8) NAME ssh-pkcs11-helper M-bM-^@M-^S OpenSSH helper for PKCS#11 support SYNOPSIS ssh-pkcs11-helper [-v] DESCRIPTION ssh-pkcs11-helper is used by ssh(1), ssh-agent(1), and ssh-keygen(1) to access keys provided by a PKCS#11 token. ssh-pkcs11-helper is not intended to be invoked directly by the user. A single option is supported: -v Verbose mode. Causes ssh-pkcs11-helper to print debugging messages about its progress. This is helpful in debugging problems. Multiple -v options increase the verbosity. The maximum is 3. Note that ssh(1), ssh-agent(1), and ssh-keygen(1) will automatically pass the -v flag to ssh-pkcs11-helper when they have themselves been placed in debug mode. SEE ALSO ssh(1), ssh-agent(1), ssh-keygen(1) HISTORY ssh-pkcs11-helper first appeared in OpenBSD 4.7. AUTHORS Markus Friedl OpenBSD 7.6 April 29, 2022 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh-pkcs11-helper.8100644 001750 001750 0000000003614775415623 0016417xustar0030 atime=1744182234.844557134 openssh-10.0p1/ssh-pkcs11-helper.8010064400017500001750000000033721477541562300150070ustar00djmdjm.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.7 2022/04/29 03:24:30 djm Exp $ .\" .\" Copyright (c) 2010 Markus Friedl. All rights reserved. .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: April 29 2022 $ .Dt SSH-PKCS11-HELPER 8 .Os .Sh NAME .Nm ssh-pkcs11-helper .Nd OpenSSH helper for PKCS#11 support .Sh SYNOPSIS .Nm .Op Fl v .Sh DESCRIPTION .Nm is used by .Xr ssh 1 , .Xr ssh-agent 1 , and .Xr ssh-keygen 1 to access keys provided by a PKCS#11 token. .Pp .Nm is not intended to be invoked directly by the user. .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 1 , .Xr ssh-agent 1 , and .Xr ssh-keygen 1 will automatically pass the .Fl v flag to .Nm when they have themselves been placed in debug mode. .El .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 .Sh HISTORY .Nm first appeared in .Ox 4.7 . .Sh AUTHORS .An Markus Friedl Aq Mt markus@openbsd.org openssh-10.0p1/PaxHeaders.10889/ssh-pkcs11-helper.c100644 001750 001750 0000000003614775415623 0016472xustar0030 atime=1744182234.844557134 openssh-10.0p1/ssh-pkcs11-helper.c010064400017500001750000000260341477541562300150620ustar00djmdjm/* $OpenBSD: ssh-pkcs11-helper.c,v 1.27 2024/08/15 00:51:51 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #ifdef HAVE_SYS_TIME_H # include #endif #include "openbsd-compat/sys-queue.h" #include #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include "xmalloc.h" #include "sshbuf.h" #include "log.h" #include "misc.h" #include "sshkey.h" #include "authfd.h" #include "ssh-pkcs11.h" #include "ssherr.h" #ifdef ENABLE_PKCS11 #ifdef WITH_OPENSSL #include #include #include /* borrows code from sftp-server and ssh-agent */ struct pkcs11_keyinfo { struct sshkey *key; char *providername, *label; TAILQ_ENTRY(pkcs11_keyinfo) next; }; TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist; #define MAX_MSG_LENGTH 10240 /*XXX*/ /* input and output queue */ struct sshbuf *iqueue; struct sshbuf *oqueue; static void add_key(struct sshkey *k, char *name, char *label) { struct pkcs11_keyinfo *ki; ki = xcalloc(1, sizeof(*ki)); ki->providername = xstrdup(name); ki->key = k; ki->label = xstrdup(label); TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next); } static void del_keys_by_name(char *name) { struct pkcs11_keyinfo *ki, *nxt; for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) { nxt = TAILQ_NEXT(ki, next); if (!strcmp(ki->providername, name)) { TAILQ_REMOVE(&pkcs11_keylist, ki, next); free(ki->providername); free(ki->label); sshkey_free(ki->key); free(ki); } } } /* lookup matching 'private' key */ static struct sshkey * lookup_key(struct sshkey *k) { struct pkcs11_keyinfo *ki; TAILQ_FOREACH(ki, &pkcs11_keylist, next) { debug("check %s %s %s", sshkey_type(ki->key), ki->providername, ki->label); if (sshkey_equal(k, ki->key)) return (ki->key); } return (NULL); } static void send_msg(struct sshbuf *m) { int r; if ((r = sshbuf_put_stringb(oqueue, m)) != 0) fatal_fr(r, "enqueue"); } static void process_add(void) { char *name, *pin; struct sshkey **keys = NULL; int r, i, nkeys; u_char *blob; size_t blen; struct sshbuf *msg; char **labels = NULL; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0) fatal_fr(r, "parse"); if ((nkeys = pkcs11_add_provider(name, pin, &keys, &labels)) > 0) { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || (r = sshbuf_put_u32(msg, nkeys)) != 0) fatal_fr(r, "compose"); for (i = 0; i < nkeys; i++) { if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) { debug_fr(r, "encode key"); continue; } if ((r = sshbuf_put_string(msg, blob, blen)) != 0 || (r = sshbuf_put_cstring(msg, labels[i])) != 0) fatal_fr(r, "compose key"); free(blob); add_key(keys[i], name, labels[i]); free(labels[i]); } } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0 || (r = sshbuf_put_u32(msg, -nkeys)) != 0) fatal_fr(r, "compose"); free(labels); free(keys); /* keys themselves are transferred to pkcs11_keylist */ free(pin); free(name); send_msg(msg); sshbuf_free(msg); } static void process_del(void) { char *name, *pin; struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0) fatal_fr(r, "parse"); del_keys_by_name(name); if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) fatal_fr(r, "compose"); free(pin); free(name); send_msg(msg); sshbuf_free(msg); } static void process_sign(void) { u_char *blob, *data, *signature = NULL; size_t blen, dlen; u_int slen = 0; int len, r, ok = -1; struct sshkey *key = NULL, *found; struct sshbuf *msg; #ifdef WITH_OPENSSL RSA *rsa = NULL; #ifdef OPENSSL_HAS_ECC EC_KEY *ecdsa = NULL; #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ /* XXX support SHA2 signature flags */ if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 || (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 || (r = sshbuf_get_u32(iqueue, NULL)) != 0) fatal_fr(r, "parse"); if ((r = sshkey_from_blob(blob, blen, &key)) != 0) fatal_fr(r, "decode key"); if ((found = lookup_key(key)) == NULL) goto reply; /* XXX use pkey API properly for signing */ switch (key->type) { #ifdef WITH_OPENSSL case KEY_RSA: if ((rsa = EVP_PKEY_get1_RSA(found->pkey)) == NULL) fatal_f("no RSA in pkey"); if ((len = RSA_size(rsa)) < 0) fatal_f("bad RSA length"); signature = xmalloc(len); if ((len = RSA_private_encrypt(dlen, data, signature, rsa, RSA_PKCS1_PADDING)) < 0) { error_f("RSA_private_encrypt failed"); goto reply; } slen = (u_int)len; break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if ((ecdsa = EVP_PKEY_get1_EC_KEY(found->pkey)) == NULL) fatal_f("no ECDSA in pkey"); if ((len = ECDSA_size(ecdsa)) < 0) fatal_f("bad ECDSA length"); slen = (u_int)len; signature = xmalloc(slen); /* "The parameter type is ignored." */ if (!ECDSA_sign(-1, data, dlen, signature, &slen, ecdsa)) { error_f("ECDSA_sign failed"); goto reply; } break; #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ default: fatal_f("unsupported key type %d", key->type); } /* success */ ok = 0; reply: if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (ok == 0) { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || (r = sshbuf_put_string(msg, signature, slen)) != 0) fatal_fr(r, "compose response"); } else { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0) fatal_fr(r, "compose failure response"); } sshkey_free(key); RSA_free(rsa); #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) EC_KEY_free(ecdsa); #endif free(data); free(blob); free(signature); send_msg(msg); sshbuf_free(msg); } static void process(void) { u_int msg_len; u_int buf_len; u_int consumed; u_char type; const u_char *cp; int r; buf_len = sshbuf_len(iqueue); if (buf_len < 5) return; /* Incomplete message. */ cp = sshbuf_ptr(iqueue); msg_len = get_u32(cp); if (msg_len > MAX_MSG_LENGTH) { error("bad message len %d", msg_len); cleanup_exit(11); } if (buf_len < msg_len + 4) return; if ((r = sshbuf_consume(iqueue, 4)) != 0 || (r = sshbuf_get_u8(iqueue, &type)) != 0) fatal_fr(r, "parse type/len"); buf_len -= 4; switch (type) { case SSH_AGENTC_ADD_SMARTCARD_KEY: debug("process_add"); process_add(); break; case SSH_AGENTC_REMOVE_SMARTCARD_KEY: debug("process_del"); process_del(); break; case SSH2_AGENTC_SIGN_REQUEST: debug("process_sign"); process_sign(); break; default: error("Unknown message %d", type); break; } /* discard the remaining bytes from the current packet */ if (buf_len < sshbuf_len(iqueue)) { error("iqueue grew unexpectedly"); cleanup_exit(255); } 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) { if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) fatal_fr(r, "consume"); } } void cleanup_exit(int i) { /* XXX */ _exit(i); } int main(int argc, char **argv) { 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); 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; if ((iqueue = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((oqueue = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); 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 ((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_fr(r, "reserve"); if (sshbuf_len(oqueue) > 0) pfd[1].events = POLLOUT; if ((r = poll(pfd, 2, -1 /* INFTIM */)) <= 0) { if (r == 0 || errno == EINTR) continue; fatal("poll: %s", strerror(errno)); } /* copy stdin to iqueue */ if ((pfd[0].revents & (POLLIN|POLLHUP|POLLERR)) != 0) { len = read(in, buf, sizeof buf); if (len == 0) { debug("read eof"); cleanup_exit(0); } else if (len < 0) { error("read: %s", strerror(errno)); cleanup_exit(1); } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) fatal_fr(r, "sshbuf_put"); } /* send oqueue to stdout */ if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) { len = write(out, sshbuf_ptr(oqueue), sshbuf_len(oqueue)); if (len < 0) { error("write: %s", strerror(errno)); cleanup_exit(1); } else if ((r = sshbuf_consume(oqueue, len)) != 0) fatal_fr(r, "consume"); } /* * Process requests from client if we can fit the results * into the output buffer, otherwise stop processing input * and let the output queue drain. */ if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0) process(); else if (r != SSH_ERR_NO_BUFFER_SPACE) fatal_fr(r, "reserve"); } } #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) { extern char *__progname; __progname = ssh_get_progname(argv[0]); log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0); fatal("PKCS#11 support disabled at compile time"); } #endif /* ENABLE_PKCS11 */ openssh-10.0p1/PaxHeaders.10889/ssh-pkcs11.c100644 001750 001750 0000000003614775415623 0015215xustar0030 atime=1744182234.849438587 openssh-10.0p1/ssh-pkcs11.c010064400017500001750000001403171477541562300136060ustar00djmdjm/* $OpenBSD: ssh-pkcs11.c,v 1.64 2024/09/20 02:00:46 jsg Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef ENABLE_PKCS11 #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "openbsd-compat/openssl-compat.h" #include #include #include #define CRYPTOKI_COMPAT #include "pkcs11.h" #include "log.h" #include "misc.h" #include "sshkey.h" #include "ssh-pkcs11.h" #include "digest.h" #include "xmalloc.h" struct pkcs11_slotinfo { CK_TOKEN_INFO token; CK_SESSION_HANDLE session; int logged_in; }; struct pkcs11_provider { char *name; void *handle; CK_FUNCTION_LIST *function_list; CK_INFO info; CK_ULONG nslots; CK_SLOT_ID *slotlist; struct pkcs11_slotinfo *slotinfo; int valid; int refcount; TAILQ_ENTRY(pkcs11_provider) next; }; TAILQ_HEAD(, pkcs11_provider) pkcs11_providers; struct pkcs11_key { struct pkcs11_provider *provider; CK_ULONG slotidx; char *keyid; int keyid_len; }; int pkcs11_interactive = 0; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) static void ossl_error(const char *msg) { unsigned long e; error_f("%s", msg); while ((e = ERR_get_error()) != 0) error_f("libcrypto error: %s", ERR_error_string(e, NULL)); } #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ int pkcs11_init(int interactive) { pkcs11_interactive = interactive; TAILQ_INIT(&pkcs11_providers); return (0); } /* * finalize a provider shared library, it's no longer usable. * however, there might still be keys referencing this provider, * so the actual freeing of memory is handled by pkcs11_provider_unref(). * this is called when a provider gets unregistered. */ static void pkcs11_provider_finalize(struct pkcs11_provider *p) { CK_RV rv; CK_ULONG i; debug_f("provider \"%s\" refcount %d valid %d", p->name, p->refcount, p->valid); if (!p->valid) return; for (i = 0; i < p->nslots; i++) { if (p->slotinfo[i].session && (rv = p->function_list->C_CloseSession( p->slotinfo[i].session)) != CKR_OK) error("C_CloseSession failed: %lu", rv); } if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK) error("C_Finalize failed: %lu", rv); p->valid = 0; p->function_list = NULL; dlclose(p->handle); } /* * remove a reference to the provider. * called when a key gets destroyed or when the provider is unregistered. */ static void pkcs11_provider_unref(struct pkcs11_provider *p) { debug_f("provider \"%s\" refcount %d", p->name, p->refcount); if (--p->refcount <= 0) { if (p->valid) error_f("provider \"%s\" still valid", p->name); free(p->name); free(p->slotlist); free(p->slotinfo); free(p); } } /* unregister all providers, keys might still point to the providers */ void pkcs11_terminate(void) { struct pkcs11_provider *p; while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) { TAILQ_REMOVE(&pkcs11_providers, p, next); pkcs11_provider_finalize(p); pkcs11_provider_unref(p); } } /* lookup provider by name */ static struct pkcs11_provider * pkcs11_provider_lookup(char *provider_id) { struct pkcs11_provider *p; TAILQ_FOREACH(p, &pkcs11_providers, next) { debug("check provider \"%s\"", p->name); if (!strcmp(provider_id, p->name)) return (p); } return (NULL); } /* unregister provider by name */ int pkcs11_del_provider(char *provider_id) { struct pkcs11_provider *p; if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { TAILQ_REMOVE(&pkcs11_providers, p, next); pkcs11_provider_finalize(p); pkcs11_provider_unref(p); return (0); } return (-1); } static RSA_METHOD *rsa_method; static int rsa_idx = 0; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) static EC_KEY_METHOD *ec_key_method; static int ec_key_idx = 0; #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ /* release a wrapped object */ static void pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp) { struct pkcs11_key *k11 = ptr; debug_f("parent %p ptr %p idx %d", parent, ptr, idx); if (k11 == NULL) return; if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); free(k11); } /* find a single 'obj' for given attributes */ static int pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, CK_ULONG nattr, CK_OBJECT_HANDLE *obj) { CK_FUNCTION_LIST *f; CK_SESSION_HANDLE session; CK_ULONG nfound = 0; CK_RV rv; int ret = -1; f = p->function_list; session = p->slotinfo[slotidx].session; if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); } if ((rv = f->C_FindObjects(session, obj, 1, &nfound)) != CKR_OK || nfound != 1) { debug("C_FindObjects failed (nfound %lu nattr %lu): %lu", nfound, nattr, rv); } else ret = 0; if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK) error("C_FindObjectsFinal failed: %lu", rv); return (ret); } static int 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_f("no pin specified"); 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_slotinfo *si; CK_FUNCTION_LIST *f; CK_BBOOL flag = 0; CK_ATTRIBUTE attr; CK_RV rv; *val = 0; 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_f("provider \"%s\" slot %lu object %lu: attrib %lu = %d", k11->provider->name, 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 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_login(k11, CKU_USER) < 0) { error("login failed"); return (-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"); 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); return (-1); } pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE, &always_auth); /* ignore errors here */ if (always_auth && !did_login) { debug_f("always-auth key"); 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"); 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); } static int pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) { 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_f("setup pkcs11 method failed"); 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; if (pkcs11_rsa_start_wrapper() == -1) return (-1); k11 = xcalloc(1, sizeof(*k11)); k11->provider = provider; provider->refcount++; /* provider referenced by RSA key */ k11->slotidx = slotidx; /* identify key object on smartcard */ k11->keyid_len = keyid_attrib->ulValueLen; if (k11->keyid_len > 0) { k11->keyid = xmalloc(k11->keyid_len); memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } if (RSA_set_method(rsa, rsa_method) != 1) fatal_f("RSA_set_method failed"); if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1) fatal_f("RSA_set_ex_data failed"); return (0); } #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) /* openssl callback doing the actual signing operation */ static ECDSA_SIG * ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, const BIGNUM *rp, EC_KEY *ec) { 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_ex_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) { error_f("bad signature length: %lu", (u_long)siglen); goto done; } bnlen = siglen/2; if ((ret = ECDSA_SIG_new()) == NULL) { error("ECDSA_SIG_new failed"); goto done; } if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL || (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) { ossl_error("BN_bin2bn failed"); ECDSA_SIG_free(ret); ret = NULL; goto done; } if (!ECDSA_SIG_set0(ret, r, s)) { error_f("ECDSA_SIG_set0 failed"); ECDSA_SIG_free(ret); ret = NULL; goto done; } r = s = NULL; /* now owned by ret */ /* 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; if (k11->keyid_len > 0) { k11->keyid = xmalloc(k11->keyid_len); memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } if (EC_KEY_set_method(ec, ec_key_method) != 1) fatal_f("EC_KEY_set_method failed"); if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1) fatal_f("EC_KEY_set_ex_data failed"); return (0); } #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ /* remove trailing spaces */ static char * rmspace(u_char *buf, size_t len) { size_t i; if (len == 0) return buf; for (i = len - 1; i > 0; i--) if (buf[i] == ' ') buf[i] = '\0'; else break; return buf; } /* Used to printf fixed-width, space-padded, unterminated strings using %.*s */ #define RMSPACE(s) (int)sizeof(s), rmspace(s, sizeof(s)) /* * open a pkcs11 session and login if required. * if pin == NULL we delay login until key use */ static int pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, CK_ULONG user) { struct pkcs11_slotinfo *si; CK_FUNCTION_LIST *f; CK_RV rv; CK_SESSION_HANDLE session; int login_required, ret; f = p->function_list; 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 (-SSH_PKCS11_ERR_PIN_REQUIRED); } if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { error("C_OpenSession failed: %lu", rv); return (-1); } 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 (ret); } si->logged_in = 1; } si->session = session; return (0); } static int pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) { int i; for (i = 0; i < *nkeys; i++) if (sshkey_equal(key, (*keysp)[i])) return (1); return (0); } #if defined(OPENSSL_HAS_ECC) && defined(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; } EVP_PKEY_free(key->pkey); if ((key->pkey = EVP_PKEY_new()) == NULL) fatal("EVP_PKEY_new failed"); if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) fatal("EVP_PKEY_set1_EC_KEY failed"); key->ecdsa_nid = nid; key->type = KEY_ECDSA; key->flags |= SSHKEY_FLAG_EXT; 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 /* OPENSSL_HAS_ECC && 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_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) goto fail; key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error("sshkey_new failed"); goto fail; } EVP_PKEY_free(key->pkey); if ((key->pkey = EVP_PKEY_new()) == NULL) fatal("EVP_PKEY_new failed"); if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) fatal("EVP_PKEY_set1_RSA failed"); key->type = KEY_RSA; key->flags |= SSHKEY_FLAG_EXT; fail: for (i = 0; i < 3; i++) free(key_attr[i].pValue); RSA_free(rsa); return (key); } static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { CK_ATTRIBUTE cert_attr[3]; CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; X509 *x509 = NULL; X509_NAME *x509_name = NULL; EVP_PKEY *evp; RSA *rsa = NULL; #ifdef OPENSSL_HAS_ECC EC_KEY *ec = NULL; #endif struct sshkey *key = NULL; int i; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) int nid; #endif const u_char *cp; 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[1].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; } EVP_PKEY_free(key->pkey); if ((key->pkey = EVP_PKEY_new()) == NULL) fatal("EVP_PKEY_new failed"); if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) fatal("EVP_PKEY_set1_RSA failed"); key->type = KEY_RSA; key->flags |= SSHKEY_FLAG_EXT; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) } 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; } EVP_PKEY_free(key->pkey); if ((key->pkey = EVP_PKEY_new()) == NULL) fatal("EVP_PKEY_new failed"); if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) fatal("EVP_PKEY_set1_EC_KEY failed"); key->ecdsa_nid = nid; key->type = KEY_ECDSA; key->flags |= SSHKEY_FLAG_EXT; #endif /* OPENSSL_HAS_ECC && 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 static void note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, struct sshkey *key) { char *fp; if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) { error_f("sshkey_fingerprint failed"); return; } debug2("%s: provider %s slot %lu: %s %s", context, p->name, (u_long)slotidx, sshkey_type(key), fp); free(fp); } /* * lookup certificates for token in slot identified by slotidx, * add 'wrapped' public keys to the 'keysp' array and increment nkeys. * 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; 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_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 (n == 0) break; 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); goto fail; } 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; } note_key(p, slotidx, __func__, key); if (pkcs11_key_included(keysp, nkeys, key)) { debug2_f("key already included"); sshkey_free(key); } else { /* expand key array and add key */ *keysp = xrecallocarray(*keysp, *nkeys, *nkeys + 1, sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; if (labelsp != NULL) { *labelsp = xrecallocarray(*labelsp, *nkeys, *nkeys + 1, sizeof(char *)); (*labelsp)[*nkeys] = xstrdup((char *)label); } *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); } } 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; } label[key_attr[1].ulValueLen] = '\0'; switch (ck_key_type) { case CKK_RSA: key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); break; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) case CKK_ECDSA: key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); break; #endif /* OPENSSL_HAS_ECC && 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; } note_key(p, slotidx, __func__, key); if (pkcs11_key_included(keysp, nkeys, key)) { debug2_f("key already included"); sshkey_free(key); } else { /* expand key array and add key */ *keysp = xrecallocarray(*keysp, *nkeys, *nkeys + 1, sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; if (labelsp != NULL) { *labelsp = xrecallocarray(*labelsp, *nkeys, *nkeys + 1, sizeof(char *)); (*labelsp)[*nkeys] = xstrdup((char *)label); } *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); } } ret = 0; fail: rv = f->C_FindObjectsFinal(session); if (rv != CKR_OK) { error("C_FindObjectsFinal failed: %lu", rv); ret = -1; } return (ret); } #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_f("key generation failed: error 0x%lx", rv); *err = rv; return NULL; } return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey); } static int h2i(char c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'a' && c <= 'f') return c - 'a' + 10; else if (c >= 'A' && c <= 'F') return c - 'A' + 10; else return -1; } static int pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen) { size_t i, len; if (dest) *dest = NULL; if (rlen) *rlen = 0; if ((len = strlen(hex)) % 2) return -1; len /= 2; *dest = xmalloc(len); for (i = 0; i < len; i++) { int hi, low; hi = h2i(hex[2 * i]); lo = h2i(hex[(2 * i) + 1]); if (hi == -1 || lo == -1) return -1; (*dest)[i] = (hi << 4) | lo; } 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_f("invalid key size %lu", bits); return NULL; } if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams, &ecparams_size) == -1) { error_f("invalid oid"); 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_f("key generation failed: error 0x%lx", 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 **); CK_RV rv; CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; if (providerp == NULL) goto fail; *providerp = NULL; if (keyp != NULL) *keyp = NULL; if (labelsp != NULL) *labelsp = NULL; if (pkcs11_provider_lookup(provider_id) != NULL) { debug_f("provider already registered: %s", provider_id); goto fail; } if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { error("provider %s is not a PKCS11 library", provider_id); goto fail; } /* open shared pkcs11-library */ if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { error("dlopen %s failed: %s", provider_id, dlerror()); goto fail; } if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); p = xcalloc(1, sizeof(*p)); p->name = xstrdup(provider_id); p->handle = handle; /* setup the pkcs11 callbacks */ if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { 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 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 for provider %s failed: %lu", provider_id, rv); goto fail; } debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" " libraryDescription <%.*s> libraryVersion %d.%d", provider_id, RMSPACE(p->info.manufacturerID), p->info.cryptokiVersion.major, p->info.cryptokiVersion.minor, RMSPACE(p->info.libraryDescription), p->info.libraryVersion.major, p->info.libraryVersion.minor); if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { error("C_GetSlotList failed: %lu", rv); goto fail; } if (p->nslots == 0) { debug_f("provider %s returned no slots", 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 for provider %s failed: %lu", provider_id, rv); goto fail; } p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); p->valid = 1; nkeys = 0; for (i = 0; i < p->nslots; i++) { token = &p->slotinfo[i].token; if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) != CKR_OK) { error("C_GetTokenInfo for provider %s slot %lu " "failed: %lu", provider_id, (u_long)i, rv); continue; } if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { debug2_f("ignoring uninitialised token in " "provider %s slot %lu", provider_id, (u_long)i); continue; } debug("provider %s slot %lu: label <%.*s> " "manufacturerID <%.*s> model <%.*s> serial <%.*s> " "flags 0x%lx", provider_id, (unsigned long)i, RMSPACE(token->label), RMSPACE(token->manufacturerID), RMSPACE(token->model), RMSPACE(token->serialNumber), token->flags); /* * 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); } } /* 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 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); 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_f("provider %s returned no keys", 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_f("provider \"%s\" available", provider_id); else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL, &p, CKU_SO)) < 0) { debug_f("could not register provider %s", provider_id); goto out; } else reset_provider = 1; 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_f("could not supply SO pin: %lu", 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_f("failed to generate RSA key"); goto out; } break; case KEY_ECDSA: if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label, bits, keyid, err)) == NULL) { debug_f("failed to generate ECDSA key"); goto out; } break; default: *err = SSH_PKCS11_ERR_GENERIC; debug_f("unknown type %d", 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_f("using provider \"%s\"", provider_id); } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p, CKU_SO) < 0) { debug_f("could not register provider %s", provider_id); goto out; } else reset_provider = 1; 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_f("could not supply SO pin: %lu", 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_f("could not destroy private key 0x%hhx", 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_f("could not get key type of public key 0x%hhx", 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_f("could not destroy public key 0x%hhx", 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 */ #include #include #include #include "log.h" #include "sshkey.h" int pkcs11_init(int interactive) { error("%s: dlopen() not supported", __func__); return (-1); } int pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, char ***labelsp) { error("%s: dlopen() not supported", __func__); return (-1); } void pkcs11_terminate(void) { error("%s: dlopen() not supported", __func__); } #endif /* ENABLE_PKCS11 */ openssh-10.0p1/PaxHeaders.10889/ssh-pkcs11.h100644 001750 001750 0000000003614775415623 0015222xustar0030 atime=1744182234.849438587 openssh-10.0p1/ssh-pkcs11.h010064400017500001750000000033011477541562300136020ustar00djmdjm/* $OpenBSD: ssh-pkcs11.h,v 1.7 2023/12/18 14:46:56 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Errors for pkcs11_add_provider() */ #define SSH_PKCS11_ERR_GENERIC 1 #define SSH_PKCS11_ERR_LOGIN_FAIL 2 #define SSH_PKCS11_ERR_NO_SLOTS 3 #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 int pkcs11_init(int); void pkcs11_terminate(void); int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); int pkcs11_del_provider(char *); #ifdef WITH_PKCS11_KEYGEN struct sshkey * pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, unsigned int, unsigned char, u_int32_t *); struct sshkey * pkcs11_destroy_keypair(char *, char *, unsigned long, unsigned char, u_int32_t *); #endif /* Only available in ssh-pkcs11-client.c so far */ int pkcs11_make_cert(const struct sshkey *, const struct sshkey *, struct sshkey **); #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) #undef ENABLE_PKCS11 #endif openssh-10.0p1/PaxHeaders.10889/ssh-rsa.c100644 001750 001750 0000000003614775415623 0014700xustar0030 atime=1744182234.850415515 openssh-10.0p1/ssh-rsa.c010064400017500001750000000400021477541562300132570ustar00djmdjm/* $OpenBSD: ssh-rsa.c,v 1.80 2024/08/15 00:51:51 djm Exp $ */ /* * Copyright (c) 2000, 2003 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_OPENSSL #include #include #include #include #include #include "sshbuf.h" #include "ssherr.h" #define SSHKEY_INTERNAL #include "sshkey.h" #include "digest.h" #include "log.h" #include "openbsd-compat/openssl-compat.h" static u_int ssh_rsa_size(const struct sshkey *k) { if (k->pkey == NULL) return 0; return EVP_PKEY_bits(k->pkey); } static int ssh_rsa_alloc(struct sshkey *k) { if ((k->pkey = EVP_PKEY_new()) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } static void ssh_rsa_cleanup(struct sshkey *k) { EVP_PKEY_free(k->pkey); k->pkey = NULL; } static int ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b) { if (a->pkey == NULL || b->pkey == NULL) return 0; return EVP_PKEY_cmp(a->pkey, b->pkey) == 1; } static int ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; const BIGNUM *rsa_n, *rsa_e; const RSA *rsa; if (key->pkey == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL) return SSH_ERR_LIBCRYPTO_ERROR; RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 || (r = sshbuf_put_bignum2(b, rsa_n)) != 0) return r; return 0; } static int ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q; const RSA *rsa; if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL) return SSH_ERR_LIBCRYPTO_ERROR; RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); RSA_get0_factors(rsa, &rsa_p, &rsa_q); RSA_get0_crt_params(rsa, NULL, NULL, &rsa_iqmp); if (!sshkey_is_cert(key)) { /* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */ if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 || (r = sshbuf_put_bignum2(b, rsa_e)) != 0) return r; } if ((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) return r; return 0; } static int ssh_rsa_generate(struct sshkey *k, int bits) { EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *res = NULL; int ret = SSH_ERR_INTERNAL_ERROR; if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || bits > SSHBUF_MAX_BIGNUM * 8) return SSH_ERR_KEY_LENGTH; if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (EVP_PKEY_keygen_init(ctx) <= 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) { ret = SSH_ERR_KEY_LENGTH; goto out; } if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* success */ k->pkey = res; ret = 0; out: EVP_PKEY_CTX_free(ctx); return ret; } static int ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to) { const BIGNUM *rsa_n, *rsa_e; BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL; int r = SSH_ERR_INTERNAL_ERROR; const RSA *rsa_from; RSA *rsa_to = NULL; if ((rsa_from = EVP_PKEY_get0_RSA(from->pkey)) == NULL || (rsa_to = RSA_new()) == NULL) return SSH_ERR_LIBCRYPTO_ERROR; RSA_get0_key(rsa_from, &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(rsa_to, rsa_n_dup, rsa_e_dup, NULL)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } rsa_n_dup = rsa_e_dup = NULL; /* transferred */ if (EVP_PKEY_set1_RSA(to->pkey, rsa_to) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* success */ r = 0; out: RSA_free(rsa_to); BN_clear_free(rsa_n_dup); BN_clear_free(rsa_e_dup); return r; } static int ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b, struct sshkey *key) { int ret = SSH_ERR_INTERNAL_ERROR; BIGNUM *rsa_n = NULL, *rsa_e = NULL; RSA *rsa = NULL; if ((rsa = RSA_new()) == NULL) return SSH_ERR_LIBCRYPTO_ERROR; 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(rsa, rsa_n, rsa_e, NULL)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } rsa_n = rsa_e = NULL; /* transferred */ if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((ret = sshkey_check_rsa_length(key, 0)) != 0) goto out; #ifdef DEBUG_PK RSA_print_fp(stderr, rsa, 8); #endif /* success */ ret = 0; out: RSA_free(rsa); BN_clear_free(rsa_n); BN_clear_free(rsa_e); return ret; } static int ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL; BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL; RSA *rsa = NULL; if (sshkey_is_cert(key)) { /* sshkey_private_deserialize already has pubkey from cert */ if ((rsa = EVP_PKEY_get1_RSA(key->pkey)) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } } else { if ((rsa = RSA_new()) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* Note: can't reuse ssh_rsa_deserialize_public: e,n vs. n,e */ if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 || (r = sshbuf_get_bignum2(b, &rsa_e)) != 0) goto out; if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } rsa_n = rsa_e = NULL; /* transferred */ } if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 || (r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 || (r = sshbuf_get_bignum2(b, &rsa_p)) != 0 || (r = sshbuf_get_bignum2(b, &rsa_q)) != 0) goto out; if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q, rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0) goto out; if (!RSA_set0_key(rsa, NULL, NULL, rsa_d)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } rsa_d = NULL; /* transferred */ if (!RSA_set0_factors(rsa, rsa_p, rsa_q)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } rsa_p = rsa_q = NULL; /* transferred */ if (!RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; if (RSA_blinding_on(rsa, NULL) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((r = sshkey_check_rsa_length(key, 0)) != 0) goto out; /* success */ r = 0; out: RSA_free(rsa); 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); BN_clear_free(rsa_dmp1); BN_clear_free(rsa_dmq1); return r; } 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; } int ssh_rsa_complete_crt_parameters(const BIGNUM *rsa_d, const BIGNUM *rsa_p, const BIGNUM *rsa_q, const BIGNUM *rsa_iqmp, BIGNUM **rsa_dmp1, BIGNUM **rsa_dmq1) { BIGNUM *aux = NULL, *d_consttime = NULL; BN_CTX *ctx = NULL; int r; *rsa_dmq1 = *rsa_dmp1 = NULL; 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) { r = SSH_ERR_ALLOC_FAIL; goto out; } BN_set_flags(aux, BN_FLG_CONSTTIME); BN_set_flags(d_consttime, BN_FLG_CONSTTIME); 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; } /* success */ r = 0; out: BN_clear_free(aux); BN_clear_free(d_consttime); BN_CTX_free(ctx); return r; } /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ static int ssh_rsa_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { u_char *sig = NULL; size_t diff, len = 0; int slen = 0; int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (alg == NULL || strlen(alg) == 0) hash_alg = SSH_DIGEST_SHA1; else hash_alg = rsa_hash_id_from_keyname(alg); if (key == NULL || key->pkey == NULL || hash_alg == -1 || sshkey_type_plain(key->type) != KEY_RSA) return SSH_ERR_INVALID_ARGUMENT; slen = EVP_PKEY_size(key->pkey); if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) return SSH_ERR_INVALID_ARGUMENT; if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE) return SSH_ERR_KEY_LENGTH; if ((ret = sshkey_pkey_digest_sign(key->pkey, hash_alg, &sig, &len, data, datalen)) < 0) goto out; if (len < (size_t)slen) { diff = slen - len; memmove(sig + diff, sig, len); explicit_bzero(sig, diff); } else if (len > (size_t)slen) { ret = SSH_ERR_INTERNAL_ERROR; goto out; } /* encode signature */ if ((b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || (ret = sshbuf_put_string(b, sig, slen)) != 0) goto out; len = sshbuf_len(b); if (sigp != NULL) { if ((*sigp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sshbuf_ptr(b), len); } if (lenp != NULL) *lenp = len; ret = 0; out: freezero(sig, slen); sshbuf_free(b); return ret; } static int ssh_rsa_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { char *sigtype = NULL; int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; size_t len = 0, diff, modlen, rsasize; struct sshbuf *b = NULL; u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; if (key == NULL || key->pkey == NULL || sshkey_type_plain(key->type) != KEY_RSA || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE) return SSH_ERR_KEY_LENGTH; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } 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; } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } /* RSA_verify expects a signature of RSA_size */ modlen = EVP_PKEY_size(key->pkey); if (len > modlen) { ret = SSH_ERR_KEY_BITS_MISMATCH; goto out; } else if (len < modlen) { diff = modlen - len; osigblob = sigblob; if ((sigblob = realloc(sigblob, modlen)) == NULL) { sigblob = osigblob; /* put it back for clear/free */ ret = SSH_ERR_ALLOC_FAIL; goto out; } memmove(sigblob + diff, sigblob, len); explicit_bzero(sigblob, diff); len = modlen; } rsasize = EVP_PKEY_size(key->pkey); if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || len == 0 || len > rsasize) { ret = SSH_ERR_INVALID_ARGUMENT; goto out; } ret = sshkey_pkey_digest_verify(key->pkey, hash_alg, data, dlen, sigblob, len); out: freezero(sigblob, len); free(sigtype); sshbuf_free(b); explicit_bzero(digest, sizeof(digest)); return ret; } static const struct sshkey_impl_funcs sshkey_rsa_funcs = { /* .size = */ ssh_rsa_size, /* .alloc = */ ssh_rsa_alloc, /* .cleanup = */ ssh_rsa_cleanup, /* .equal = */ ssh_rsa_equal, /* .ssh_serialize_public = */ ssh_rsa_serialize_public, /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public, /* .ssh_serialize_private = */ ssh_rsa_serialize_private, /* .ssh_deserialize_private = */ ssh_rsa_deserialize_private, /* .generate = */ ssh_rsa_generate, /* .copy_public = */ ssh_rsa_copy_public, /* .sign = */ ssh_rsa_sign, /* .verify = */ ssh_rsa_verify, }; const struct sshkey_impl sshkey_rsa_impl = { /* .name = */ "ssh-rsa", /* .shortname = */ "RSA", /* .sigalg = */ NULL, /* .type = */ KEY_RSA, /* .nid = */ 0, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_rsa_funcs, }; const struct sshkey_impl sshkey_rsa_cert_impl = { /* .name = */ "ssh-rsa-cert-v01@openssh.com", /* .shortname = */ "RSA-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_RSA_CERT, /* .nid = */ 0, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, /* .funcs = */ &sshkey_rsa_funcs, }; /* SHA2 signature algorithms */ const struct sshkey_impl sshkey_rsa_sha256_impl = { /* .name = */ "rsa-sha2-256", /* .shortname = */ "RSA", /* .sigalg = */ NULL, /* .type = */ KEY_RSA, /* .nid = */ 0, /* .cert = */ 0, /* .sigonly = */ 1, /* .keybits = */ 0, /* .funcs = */ &sshkey_rsa_funcs, }; const struct sshkey_impl sshkey_rsa_sha512_impl = { /* .name = */ "rsa-sha2-512", /* .shortname = */ "RSA", /* .sigalg = */ NULL, /* .type = */ KEY_RSA, /* .nid = */ 0, /* .cert = */ 0, /* .sigonly = */ 1, /* .keybits = */ 0, /* .funcs = */ &sshkey_rsa_funcs, }; const struct sshkey_impl sshkey_rsa_sha256_cert_impl = { /* .name = */ "rsa-sha2-256-cert-v01@openssh.com", /* .shortname = */ "RSA-CERT", /* .sigalg = */ "rsa-sha2-256", /* .type = */ KEY_RSA_CERT, /* .nid = */ 0, /* .cert = */ 1, /* .sigonly = */ 1, /* .keybits = */ 0, /* .funcs = */ &sshkey_rsa_funcs, }; const struct sshkey_impl sshkey_rsa_sha512_cert_impl = { /* .name = */ "rsa-sha2-512-cert-v01@openssh.com", /* .shortname = */ "RSA-CERT", /* .sigalg = */ "rsa-sha2-512", /* .type = */ KEY_RSA_CERT, /* .nid = */ 0, /* .cert = */ 1, /* .sigonly = */ 1, /* .keybits = */ 0, /* .funcs = */ &sshkey_rsa_funcs, }; #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/ssh-sandbox.h100644 001750 001750 0000000003614775415623 0015556xustar0030 atime=1744182234.850415515 openssh-10.0p1/ssh-sandbox.h010064400017500001750000000017441477541562300141470ustar00djmdjm/* $OpenBSD: ssh-sandbox.h,v 1.1 2011/06/23 09:34:13 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. */ struct monitor; struct ssh_sandbox; struct ssh_sandbox *ssh_sandbox_init(struct monitor *); void ssh_sandbox_child(struct ssh_sandbox *); openssh-10.0p1/PaxHeaders.10889/ssh-sk-client.c100644 001750 001750 0000000003614775415623 0016004xustar0030 atime=1744182234.850415515 openssh-10.0p1/ssh-sk-client.c010064400017500001750000000264371477541562300144030ustar00djmdjm/* $OpenBSD: ssh-sk-client.c,v 1.13 2025/02/18 08:02:48 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "ssherr.h" #include "sshbuf.h" #include "sshkey.h" #include "msg.h" #include "digest.h" #include "pathnames.h" #include "ssh-sk.h" #include "misc.h" /* #define DEBUG_SK 1 */ static int start_helper(int *fdp, pid_t *pidp, void (**osigchldp)(int)) { void (*osigchld)(int); int oerrno, pair[2]; pid_t pid; char *helper, *verbosity = NULL; *fdp = -1; *pidp = 0; *osigchldp = SIG_DFL; helper = getenv("SSH_SK_HELPER"); if (helper == NULL || strlen(helper) == 0) helper = _PATH_SSH_SK_HELPER; if (access(helper, X_OK) != 0) { oerrno = errno; error_f("helper \"%s\" unusable: %s", helper, strerror(errno)); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } #ifdef DEBUG_SK verbosity = "-vvv"; #endif /* Start helper */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { error("socketpair: %s", strerror(errno)); return SSH_ERR_SYSTEM_ERROR; } osigchld = ssh_signal(SIGCHLD, SIG_DFL); if ((pid = fork()) == -1) { oerrno = errno; error("fork: %s", strerror(errno)); close(pair[0]); close(pair[1]); ssh_signal(SIGCHLD, osigchld); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } if (pid == 0) { if ((dup2(pair[1], STDIN_FILENO) == -1) || (dup2(pair[1], STDOUT_FILENO) == -1)) { error_f("dup2: %s", strerror(errno)); _exit(1); } close(pair[0]); close(pair[1]); closefrom(STDERR_FILENO + 1); debug_f("starting %s %s", helper, verbosity == NULL ? "" : verbosity); execlp(helper, helper, verbosity, (char *)NULL); error_f("execlp: %s", strerror(errno)); _exit(1); } close(pair[1]); /* success */ debug3_f("started pid=%ld", (long)pid); *fdp = pair[0]; *pidp = pid; *osigchldp = osigchld; return 0; } static int reap_helper(pid_t pid) { int status, oerrno; debug3_f("pid=%ld", (long)pid); errno = 0; while (waitpid(pid, &status, 0) == -1) { if (errno == EINTR) { errno = 0; continue; } oerrno = errno; error_f("waitpid: %s", strerror(errno)); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } if (!WIFEXITED(status)) { error_f("helper exited abnormally"); return SSH_ERR_AGENT_FAILURE; } else if (WEXITSTATUS(status) != 0) { error_f("helper exited with non-zero exit status"); return SSH_ERR_AGENT_FAILURE; } return 0; } static int client_converse(struct sshbuf *msg, struct sshbuf **respp, u_int type) { int oerrno, fd, r2, ll, r = SSH_ERR_INTERNAL_ERROR; u_int rtype, rerr; pid_t pid; u_char version; void (*osigchld)(int); struct sshbuf *req = NULL, *resp = NULL; *respp = NULL; if ((r = start_helper(&fd, &pid, &osigchld)) != 0) return r; if ((req = sshbuf_new()) == NULL || (resp = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* Request preamble: type, log_on_stderr, log_level */ ll = log_level_get(); if ((r = sshbuf_put_u32(req, type)) != 0 || (r = sshbuf_put_u8(req, log_is_on_stderr() != 0)) != 0 || (r = sshbuf_put_u32(req, ll < 0 ? 0 : ll)) != 0 || (r = sshbuf_putb(req, msg)) != 0) { error_fr(r, "compose"); goto out; } if ((r = ssh_msg_send(fd, SSH_SK_HELPER_VERSION, req)) != 0) { error_fr(r, "send"); goto out; } if ((r = ssh_msg_recv(fd, resp)) != 0) { error_fr(r, "receive"); goto out; } if ((r = sshbuf_get_u8(resp, &version)) != 0) { error_fr(r, "parse version"); goto out; } if (version != SSH_SK_HELPER_VERSION) { error_f("unsupported version: got %u, expected %u", version, SSH_SK_HELPER_VERSION); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_u32(resp, &rtype)) != 0) { error_fr(r, "parse message type"); goto out; } if (rtype == SSH_SK_HELPER_ERROR) { if ((r = sshbuf_get_u32(resp, &rerr)) != 0) { error_fr(r, "parse"); goto out; } debug_f("helper returned error -%u", rerr); /* OpenSSH error values are negative; encoded as -err on wire */ if (rerr == 0 || rerr >= INT_MAX) r = SSH_ERR_INTERNAL_ERROR; else r = -(int)rerr; goto out; } else if (rtype != type) { error_f("helper returned incorrect message type %u, " "expecting %u", rtype, type); r = SSH_ERR_INTERNAL_ERROR; goto out; } /* success */ r = 0; out: oerrno = errno; close(fd); if ((r2 = reap_helper(pid)) != 0) { if (r == 0) { r = r2; oerrno = errno; } } if (r == 0) { *respp = resp; resp = NULL; } sshbuf_free(req); sshbuf_free(resp); ssh_signal(SIGCHLD, osigchld); errno = oerrno; return r; } int sshsk_sign(const char *provider, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat, const char *pin) { int oerrno, r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL; *sigp = NULL; *lenp = 0; #ifndef ENABLE_SK return SSH_ERR_KEY_TYPE_UNKNOWN; #endif if ((kbuf = sshbuf_new()) == NULL || (req = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshkey_private_serialize(key, kbuf)) != 0) { error_fr(r, "encode key"); goto out; } if ((r = sshbuf_put_stringb(req, kbuf)) != 0 || (r = sshbuf_put_cstring(req, provider)) != 0 || (r = sshbuf_put_string(req, data, datalen)) != 0 || (r = sshbuf_put_cstring(req, NULL)) != 0 || /* alg */ (r = sshbuf_put_u32(req, compat)) != 0 || (r = sshbuf_put_cstring(req, pin)) != 0) { error_fr(r, "compose"); goto out; } if ((r = client_converse(req, &resp, SSH_SK_HELPER_SIGN)) != 0) goto out; if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) { error_fr(r, "parse signature"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(resp) != 0) { error_f("trailing data in response"); r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ r = 0; out: oerrno = errno; if (r != 0) { freezero(*sigp, *lenp); *sigp = NULL; *lenp = 0; } sshbuf_free(kbuf); sshbuf_free(req); sshbuf_free(resp); errno = oerrno; return r; } int sshsk_enroll(int type, const char *provider_path, const char *device, const char *application, const char *userid, uint8_t flags, const char *pin, struct sshbuf *challenge_buf, struct sshkey **keyp, struct sshbuf *attest) { int oerrno, r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *kbuf = NULL, *abuf = NULL, *req = NULL, *resp = NULL; struct sshkey *key = NULL; *keyp = NULL; if (attest != NULL) sshbuf_reset(attest); #ifndef ENABLE_SK return SSH_ERR_KEY_TYPE_UNKNOWN; #endif if (type < 0) return SSH_ERR_INVALID_ARGUMENT; if ((abuf = sshbuf_new()) == NULL || (kbuf = sshbuf_new()) == NULL || (req = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put_u32(req, (u_int)type)) != 0 || (r = sshbuf_put_cstring(req, provider_path)) != 0 || (r = sshbuf_put_cstring(req, device)) != 0 || (r = sshbuf_put_cstring(req, application)) != 0 || (r = sshbuf_put_cstring(req, userid)) != 0 || (r = sshbuf_put_u8(req, flags)) != 0 || (r = sshbuf_put_cstring(req, pin)) != 0 || (r = sshbuf_put_stringb(req, challenge_buf)) != 0) { error_fr(r, "compose"); goto out; } if ((r = client_converse(req, &resp, SSH_SK_HELPER_ENROLL)) != 0) goto out; if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 || (r = sshbuf_get_stringb(resp, abuf)) != 0) { error_fr(r, "parse"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(resp) != 0) { error_f("trailing data in response"); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) { error_fr(r, "encode"); goto out; } if (attest != NULL && (r = sshbuf_putb(attest, abuf)) != 0) { error_fr(r, "encode attestation information"); goto out; } /* success */ r = 0; *keyp = key; key = NULL; out: oerrno = errno; sshkey_free(key); sshbuf_free(kbuf); sshbuf_free(abuf); sshbuf_free(req); sshbuf_free(resp); errno = oerrno; return r; } static void sshsk_free_resident_key(struct sshsk_resident_key *srk) { if (srk == NULL) return; sshkey_free(srk->key); freezero(srk->user_id, srk->user_id_len); free(srk); } void sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks) { size_t i; if (srks == NULL || nsrks == 0) return; for (i = 0; i < nsrks; i++) sshsk_free_resident_key(srks[i]); free(srks); } int sshsk_load_resident(const char *provider_path, const char *device, const char *pin, u_int flags, struct sshsk_resident_key ***srksp, size_t *nsrksp) { int oerrno, r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL; struct sshkey *key = NULL; struct sshsk_resident_key *srk = NULL, **srks = NULL, **tmp; u_char *userid = NULL; size_t userid_len = 0, nsrks = 0; *srksp = NULL; *nsrksp = 0; if ((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 || (r = sshbuf_put_u32(req, flags)) != 0) { error_fr(r, "compose"); goto out; } if ((r = client_converse(req, &resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0) goto out; while (sshbuf_len(resp) != 0) { /* key, comment, user_id */ if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 || (r = sshbuf_get_cstring(resp, NULL, NULL)) != 0 || (r = sshbuf_get_string(resp, &userid, &userid_len)) != 0) { error_fr(r, "parse"); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) { error_fr(r, "decode key"); goto out; } if ((srk = calloc(1, sizeof(*srk))) == NULL) { error_f("calloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } srk->key = key; key = NULL; srk->user_id = userid; srk->user_id_len = userid_len; userid = NULL; userid_len = 0; if ((tmp = recallocarray(srks, nsrks, nsrks + 1, sizeof(*srks))) == NULL) { error_f("recallocarray keys failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } debug_f("srks[%zu]: %s %s uidlen %zu", nsrks, sshkey_type(srk->key), srk->key->sk_application, srk->user_id_len); srks = tmp; srks[nsrks++] = srk; srk = NULL; } /* success */ r = 0; *srksp = srks; *nsrksp = nsrks; srks = NULL; nsrks = 0; out: oerrno = errno; sshsk_free_resident_key(srk); sshsk_free_resident_keys(srks, nsrks); freezero(userid, userid_len); sshkey_free(key); sshbuf_free(kbuf); sshbuf_free(req); sshbuf_free(resp); errno = oerrno; return r; } openssh-10.0p1/PaxHeaders.10889/ssh-sk-helper.0100644 001750 001750 0000000003614775415623 0015722xustar0030 atime=1744182234.851391882 openssh-10.0p1/ssh-sk-helper.0010064400017500001750000000021141477541562300143030ustar00djmdjmSSH-SK-HELPER(8) System Manager's Manual SSH-SK-HELPER(8) NAME ssh-sk-helper M-bM-^@M-^S OpenSSH helper for FIDO authenticator support SYNOPSIS ssh-sk-helper [-v] DESCRIPTION ssh-sk-helper is used by ssh(1), ssh-agent(1), and ssh-keygen(1) to access keys provided by a FIDO authenticator. ssh-sk-helper is not intended to be invoked directly by the user. A single option is supported: -v Verbose mode. Causes ssh-sk-helper to print debugging messages about its progress. This is helpful in debugging problems. Multiple -v options increase the verbosity. The maximum is 3. Note that ssh(1), ssh-agent(1), and ssh-keygen(1) will automatically pass the -v flag to ssh-sk-helper when they have themselves been placed in debug mode. SEE ALSO ssh(1), ssh-agent(1), ssh-keygen(1) HISTORY ssh-sk-helper first appeared in OpenBSD 6.7. AUTHORS Damien Miller OpenBSD 7.6 April 29, 2022 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh-sk-helper.8100644 001750 001750 0000000003614775415623 0015732xustar0030 atime=1744182234.851391882 openssh-10.0p1/ssh-sk-helper.8010064400017500001750000000033731477541562300143230ustar00djmdjm.\" $OpenBSD: ssh-sk-helper.8,v 1.4 2022/04/29 03:24:30 djm Exp $ .\" .\" Copyright (c) 2010 Markus Friedl. All rights reserved. .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: April 29 2022 $ .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 1 , .Xr ssh-agent 1 , and .Xr ssh-keygen 1 to access keys provided by a FIDO authenticator. .Pp .Nm is not intended to be invoked directly by the user. .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 1 , .Xr ssh-agent 1 , and .Xr ssh-keygen 1 will automatically pass the .Fl v flag to .Nm when they have themselves been placed in debug mode. .El .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 .Sh HISTORY .Nm first appeared in .Ox 6.7 . .Sh AUTHORS .An Damien Miller Aq Mt djm@openbsd.org openssh-10.0p1/PaxHeaders.10889/ssh-sk-helper.c100644 001750 001750 0000000003614775415623 0016005xustar0030 atime=1744182234.851391882 openssh-10.0p1/ssh-sk-helper.c010064400017500001750000000240361477541562300143750ustar00djmdjm/* $OpenBSD: ssh-sk-helper.c,v 1.14 2022/12/04 11:03:11 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. */ /* * This is a tiny program used to isolate the address space used for * security key middleware signing operations from ssh-agent. It is similar * to ssh-pkcs11-helper.c but considerably simpler as the operations for * security keys are stateless. * * Please crank SSH_SK_HELPER_VERSION in sshkey.h for any incompatible * protocol changes. */ #include "includes.h" #include #include #include #include #include #include #include #include "xmalloc.h" #include "log.h" #include "sshkey.h" #include "authfd.h" #include "misc.h" #include "sshbuf.h" #include "msg.h" #include "uidswap.h" #include "ssherr.h" #include "ssh-sk.h" #ifdef ENABLE_SK extern char *__progname; static struct sshbuf *reply_error(int r, char *fmt, ...) __attribute__((__format__ (printf, 2, 3))); static struct sshbuf * reply_error(int r, char *fmt, ...) { char *msg; va_list ap; struct sshbuf *resp; va_start(ap, fmt); xvasprintf(&msg, fmt, ap); va_end(ap); debug("%s: %s", __progname, msg); free(msg); if (r >= 0) fatal_f("invalid error code %d", r); if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if (sshbuf_put_u32(resp, SSH_SK_HELPER_ERROR) != 0 || sshbuf_put_u32(resp, (u_int)-r) != 0) fatal("%s: buffer error", __progname); return resp; } /* If the specified string is zero length, then free it and replace with NULL */ static void null_empty(char **s) { if (s == NULL || *s == NULL || **s != '\0') return; free(*s); *s = NULL; } static struct sshbuf * process_sign(struct sshbuf *req) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *resp, *kbuf; struct sshkey *key = NULL; uint32_t compat; const u_char *message; u_char *sig = NULL; size_t msglen, siglen = 0; char *provider = NULL, *pin = NULL; if ((r = sshbuf_froms(req, &kbuf)) != 0 || (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || (r = sshbuf_get_string_direct(req, &message, &msglen)) != 0 || (r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */ (r = sshbuf_get_u32(req, &compat)) != 0 || (r = sshbuf_get_cstring(req, &pin, NULL)) != 0) fatal_r(r, "%s: parse", __progname); if (sshbuf_len(req) != 0) fatal("%s: trailing data in request", __progname); if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) fatal_r(r, "%s: Unable to parse private key", __progname); if (!sshkey_is_sk(key)) { fatal("%s: Unsupported key type %s", __progname, sshkey_ssh_name(key)); } debug_f("ready to sign with key %s, provider %s: " "msg len %zu, compat 0x%lx", sshkey_type(key), provider, msglen, (u_long)compat); null_empty(&pin); if ((r = sshsk_sign(provider, key, &sig, &siglen, message, msglen, compat, pin)) != 0) { resp = reply_error(r, "Signing failed: %s", ssh_err(r)); goto out; } if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_SIGN)) != 0 || (r = sshbuf_put_string(resp, sig, siglen)) != 0) fatal_r(r, "%s: compose", __progname); out: sshkey_free(key); sshbuf_free(kbuf); free(provider); if (sig != NULL) freezero(sig, siglen); if (pin != NULL) freezero(pin, strlen(pin)); return resp; } static struct sshbuf * process_enroll(struct sshbuf *req) { int r; u_int type; char *provider, *application, *pin, *device, *userid; uint8_t flags; struct sshbuf *challenge, *attest, *kbuf, *resp; struct sshkey *key; if ((attest = sshbuf_new()) == NULL || (kbuf = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if ((r = sshbuf_get_u32(req, &type)) != 0 || (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(req, &device, NULL)) != 0 || (r = sshbuf_get_cstring(req, &application, NULL)) != 0 || (r = sshbuf_get_cstring(req, &userid, NULL)) != 0 || (r = sshbuf_get_u8(req, &flags)) != 0 || (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 || (r = sshbuf_froms(req, &challenge)) != 0) fatal_r(r, "%s: parse", __progname); if (sshbuf_len(req) != 0) fatal("%s: trailing data in request", __progname); if (type > INT_MAX) fatal("%s: bad type %u", __progname, type); if (sshbuf_len(challenge) == 0) { sshbuf_free(challenge); challenge = NULL; } null_empty(&device); null_empty(&userid); null_empty(&pin); if ((r = sshsk_enroll((int)type, provider, device, application, userid, flags, pin, challenge, &key, attest)) != 0) { resp = reply_error(r, "Enrollment failed: %s", ssh_err(r)); goto out; } if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if ((r = sshkey_private_serialize(key, kbuf)) != 0) fatal_r(r, "%s: encode key", __progname); if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_ENROLL)) != 0 || (r = sshbuf_put_stringb(resp, kbuf)) != 0 || (r = sshbuf_put_stringb(resp, attest)) != 0) fatal_r(r, "%s: compose", __progname); out: sshkey_free(key); sshbuf_free(kbuf); sshbuf_free(attest); sshbuf_free(challenge); free(provider); free(application); if (pin != NULL) freezero(pin, strlen(pin)); return resp; } static struct sshbuf * process_load_resident(struct sshbuf *req) { int r; char *provider, *pin, *device; struct sshbuf *kbuf, *resp; struct sshsk_resident_key **srks = NULL; size_t nsrks = 0, i; u_int flags; 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 || (r = sshbuf_get_u32(req, &flags)) != 0) fatal_r(r, "%s: parse", __progname); if (sshbuf_len(req) != 0) fatal("%s: trailing data in request", __progname); null_empty(&device); null_empty(&pin); if ((r = sshsk_load_resident(provider, device, pin, flags, &srks, &nsrks)) != 0) { resp = reply_error(r, "sshsk_load_resident failed: %s", ssh_err(r)); goto out; } if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0) fatal_r(r, "%s: compose", __progname); for (i = 0; i < nsrks; i++) { debug_f("key %zu %s %s uidlen %zu", i, sshkey_type(srks[i]->key), srks[i]->key->sk_application, srks[i]->user_id_len); sshbuf_reset(kbuf); if ((r = sshkey_private_serialize(srks[i]->key, kbuf)) != 0) fatal_r(r, "%s: encode key", __progname); if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 || (r = sshbuf_put_cstring(resp, "")) != 0 || /* comment */ (r = sshbuf_put_string(resp, srks[i]->user_id, srks[i]->user_id_len)) != 0) fatal_r(r, "%s: compose key", __progname); } out: sshsk_free_resident_keys(srks, nsrks); sshbuf_free(kbuf); free(provider); free(device); if (pin != NULL) freezero(pin, strlen(pin)); return resp; } int main(int argc, char **argv) { SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; LogLevel log_level = SYSLOG_LEVEL_ERROR; struct sshbuf *req, *resp; int in, out, ch, r, vflag = 0; u_int rtype, ll = 0; uint8_t version, log_stderr = 0; sanitise_stdfd(); log_init(__progname, log_level, log_facility, log_stderr); while ((ch = getopt(argc, argv, "v")) != -1) { switch (ch) { case 'v': vflag = 1; if (log_level == SYSLOG_LEVEL_ERROR) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; break; default: fprintf(stderr, "usage: %s [-v]\n", __progname); exit(1); } } log_init(__progname, log_level, log_facility, vflag); /* * Rearrange our file descriptors a little; we don't trust the * providers not to fiddle with stdin/out. */ closefrom(STDERR_FILENO + 1); if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) fatal("%s: dup: %s", __progname, strerror(errno)); close(STDIN_FILENO); close(STDOUT_FILENO); sanitise_stdfd(); /* resets to /dev/null */ if ((req = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if (ssh_msg_recv(in, req) < 0) fatal("ssh_msg_recv failed"); close(in); debug_f("received message len %zu", sshbuf_len(req)); if ((r = sshbuf_get_u8(req, &version)) != 0) fatal_r(r, "%s: parse version", __progname); if (version != SSH_SK_HELPER_VERSION) { fatal("unsupported version: received %d, expected %d", version, SSH_SK_HELPER_VERSION); } if ((r = sshbuf_get_u32(req, &rtype)) != 0 || (r = sshbuf_get_u8(req, &log_stderr)) != 0 || (r = sshbuf_get_u32(req, &ll)) != 0) fatal_r(r, "%s: parse", __progname); if (!vflag && log_level_name((LogLevel)ll) != NULL) log_init(__progname, (LogLevel)ll, log_facility, log_stderr); switch (rtype) { case SSH_SK_HELPER_SIGN: resp = process_sign(req); break; case SSH_SK_HELPER_ENROLL: resp = process_enroll(req); break; case SSH_SK_HELPER_LOAD_RESIDENT: resp = process_load_resident(req); break; default: fatal("%s: unsupported request type %u", __progname, rtype); } sshbuf_free(req); debug_f("reply len %zu", sshbuf_len(resp)); if (ssh_msg_send(out, SSH_SK_HELPER_VERSION, resp) == -1) fatal("ssh_msg_send failed"); sshbuf_free(resp); close(out); return (0); } #else /* ENABLE_SK */ #include int main(int argc, char **argv) { fprintf(stderr, "ssh-sk-helper: disabled at compile time\n"); return -1; } #endif /* ENABLE_SK */ openssh-10.0p1/PaxHeaders.10889/ssh-sk.c100644 001750 001750 0000000003614775415623 0014530xustar0030 atime=1744182234.852367347 openssh-10.0p1/ssh-sk.c010064400017500001750000000555011477541562300131210ustar00djmdjm/* $OpenBSD: ssh-sk.c,v 1.41 2024/08/15 00:51:51 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* #define DEBUG_SK 1 */ #include "includes.h" #ifdef ENABLE_SK #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) #include #include #include #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ #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" /* * Almost every use of OpenSSL in this file is for ECDSA-NISTP256. * This is strictly a larger hammer than necessary, but it reduces changes * with upstream. */ #ifndef OPENSSL_HAS_ECC # undef WITH_OPENSSL #endif struct sshsk_provider { char *path; void *dlhandle; /* Return the version of the middleware API */ uint32_t (*sk_api_version)(void); /* Enroll a U2F key (private key generation) */ int (*sk_enroll)(int alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **opts, struct sk_enroll_response **enroll_response); /* Sign a challenge */ int (*sk_sign)(int alg, const uint8_t *message, size_t message_len, const char *application, const uint8_t *key_handle, size_t key_handle_len, uint8_t flags, const char *pin, struct sk_option **opts, struct sk_sign_response **sign_response); /* Enumerate resident keys */ int (*sk_load_resident_keys)(const char *pin, struct sk_option **opts, struct sk_resident_key ***rks, size_t *nrks); }; /* Built-in version */ int ssh_sk_enroll(int alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **opts, struct sk_enroll_response **enroll_response); int ssh_sk_sign(int alg, const uint8_t *message, size_t message_len, const char *application, const uint8_t *key_handle, size_t key_handle_len, uint8_t flags, const char *pin, struct sk_option **opts, struct sk_sign_response **sign_response); int ssh_sk_load_resident_keys(const char *pin, struct sk_option **opts, struct sk_resident_key ***rks, size_t *nrks); static void sshsk_free(struct sshsk_provider *p) { if (p == NULL) return; free(p->path); if (p->dlhandle != NULL) dlclose(p->dlhandle); free(p); } static struct sshsk_provider * sshsk_open(const char *path) { struct sshsk_provider *ret = NULL; uint32_t version; if (path == NULL || *path == '\0') { error("No FIDO SecurityKeyProvider specified"); return NULL; } if ((ret = calloc(1, sizeof(*ret))) == NULL) { error_f("calloc failed"); return NULL; } if ((ret->path = strdup(path)) == NULL) { error_f("strdup failed"); goto fail; } /* Skip the rest if we're using the linked in middleware */ if (strcasecmp(ret->path, "internal") == 0) { #ifdef ENABLE_SK_INTERNAL ret->sk_enroll = ssh_sk_enroll; ret->sk_sign = ssh_sk_sign; ret->sk_load_resident_keys = ssh_sk_load_resident_keys; return ret; #else error("internal security key support not enabled"); goto fail; #endif } if (lib_contains_symbol(path, "sk_api_version") != 0) { error("provider %s is not an OpenSSH FIDO library", path); goto fail; } if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) fatal("Provider \"%s\" dlopen failed: %s", path, dlerror()); if ((ret->sk_api_version = dlsym(ret->dlhandle, "sk_api_version")) == NULL) { error("Provider \"%s\" dlsym(sk_api_version) failed: %s", path, dlerror()); goto fail; } version = ret->sk_api_version(); debug_f("provider %s implements version 0x%08lx", ret->path, (u_long)version); if ((version & SSH_SK_VERSION_MAJOR_MASK) != SSH_SK_VERSION_MAJOR) { error("Provider \"%s\" implements unsupported " "version 0x%08lx (supported: 0x%08lx)", path, (u_long)version, (u_long)SSH_SK_VERSION_MAJOR); goto fail; } if ((ret->sk_enroll = dlsym(ret->dlhandle, "sk_enroll")) == NULL) { error("Provider %s dlsym(sk_enroll) failed: %s", path, dlerror()); goto fail; } if ((ret->sk_sign = dlsym(ret->dlhandle, "sk_sign")) == NULL) { error("Provider \"%s\" dlsym(sk_sign) failed: %s", path, dlerror()); goto fail; } if ((ret->sk_load_resident_keys = dlsym(ret->dlhandle, "sk_load_resident_keys")) == NULL) { error("Provider \"%s\" dlsym(sk_load_resident_keys) " "failed: %s", path, dlerror()); goto fail; } /* success */ return ret; fail: sshsk_free(ret); return NULL; } static void sshsk_free_enroll_response(struct sk_enroll_response *r) { if (r == NULL) return; freezero(r->key_handle, r->key_handle_len); freezero(r->public_key, r->public_key_len); freezero(r->signature, r->signature_len); freezero(r->attestation_cert, r->attestation_cert_len); freezero(r->authdata, r->authdata_len); freezero(r, sizeof(*r)); } static void sshsk_free_sign_response(struct sk_sign_response *r) { if (r == NULL) return; freezero(r->sig_r, r->sig_r_len); freezero(r->sig_s, r->sig_s_len); freezero(r, sizeof(*r)); } #ifdef WITH_OPENSSL /* Assemble key from response */ static int sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) { struct sshkey *key = NULL; struct sshbuf *b = NULL; EC_KEY *ecdsa = NULL; EC_POINT *q = NULL; const EC_GROUP *g = NULL; int r; *keyp = NULL; if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) { error_f("sshkey_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } key->ecdsa_nid = NID_X9_62_prime256v1; if ((ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL || (g = EC_KEY_get0_group(ecdsa)) == NULL || (q = EC_POINT_new(g)) == NULL || (b = sshbuf_new()) == NULL) { error_f("allocation failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put_string(b, resp->public_key, resp->public_key_len)) != 0) { error_fr(r, "sshbuf_put_string"); goto out; } if ((r = sshbuf_get_ec(b, q, g)) != 0) { error_fr(r, "parse"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (sshkey_ec_validate_public(g, q) != 0) { error("Authenticator returned invalid ECDSA key"); r = SSH_ERR_KEY_INVALID_EC_VALUE; goto out; } if (EC_KEY_set_public_key(ecdsa, q) != 1) { /* XXX assume it is a allocation error */ error_f("allocation failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((key->pkey = EVP_PKEY_new()) == NULL) { error_f("allocation failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if (EVP_PKEY_set1_EC_KEY(key->pkey, ecdsa) != 1) { error_f("Assigning EC_KEY failed"); r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* success */ *keyp = key; key = NULL; /* transferred */ r = 0; out: sshkey_free(key); sshbuf_free(b); EC_KEY_free(ecdsa); EC_POINT_free(q); return r; } #endif /* WITH_OPENSSL */ static int sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) { struct sshkey *key = NULL; int r; *keyp = NULL; if (resp->public_key_len != ED25519_PK_SZ) { error_f("invalid size: %zu", resp->public_key_len); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) { error_f("sshkey_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { error_f("malloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(key->ed25519_pk, resp->public_key, ED25519_PK_SZ); /* success */ *keyp = key; key = NULL; /* transferred */ r = 0; out: sshkey_free(key); return r; } static int sshsk_key_from_response(int alg, const char *application, uint8_t flags, struct sk_enroll_response *resp, struct sshkey **keyp) { struct sshkey *key = NULL; int r = SSH_ERR_INTERNAL_ERROR; *keyp = NULL; /* Check response validity */ if (resp->public_key == NULL || resp->key_handle == NULL) { error_f("sk_enroll response invalid"); r = SSH_ERR_INVALID_FORMAT; goto out; } switch (alg) { #ifdef WITH_OPENSSL case SSH_SK_ECDSA: if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0) goto out; break; #endif /* WITH_OPENSSL */ case SSH_SK_ED25519: if ((r = sshsk_ed25519_assemble(resp, &key)) != 0) goto out; break; default: error_f("unsupported algorithm %d", alg); r = SSH_ERR_INVALID_ARGUMENT; goto out; } key->sk_flags = flags; if ((key->sk_key_handle = sshbuf_new()) == NULL || (key->sk_reserved = sshbuf_new()) == NULL) { error_f("allocation failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((key->sk_application = strdup(application)) == NULL) { error_f("strdup application failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle, resp->key_handle_len)) != 0) { error_fr(r, "put key handle"); goto out; } /* success */ r = 0; *keyp = key; key = NULL; out: sshkey_free(key); return r; } static int skerr_to_ssherr(int skerr) { switch (skerr) { case SSH_SK_ERR_UNSUPPORTED: return SSH_ERR_FEATURE_UNSUPPORTED; case SSH_SK_ERR_PIN_REQUIRED: return SSH_ERR_KEY_WRONG_PASSPHRASE; case SSH_SK_ERR_DEVICE_NOT_FOUND: return SSH_ERR_DEVICE_NOT_FOUND; case SSH_SK_ERR_CREDENTIAL_EXISTS: return SSH_ERR_KEY_BAD_PERMISSIONS; case SSH_SK_ERR_GENERAL: default: return SSH_ERR_INVALID_FORMAT; } } static void sshsk_free_options(struct sk_option **opts) { size_t i; if (opts == NULL) return; for (i = 0; opts[i] != NULL; i++) { free(opts[i]->name); free(opts[i]->value); free(opts[i]); } free(opts); } static int sshsk_add_option(struct sk_option ***optsp, size_t *noptsp, const char *name, const char *value, uint8_t required) { struct sk_option **opts = *optsp; size_t nopts = *noptsp; if ((opts = recallocarray(opts, nopts, nopts + 2, /* extra for NULL */ sizeof(*opts))) == NULL) { error_f("array alloc failed"); return SSH_ERR_ALLOC_FAIL; } *optsp = opts; *noptsp = nopts + 1; if ((opts[nopts] = calloc(1, sizeof(**opts))) == NULL) { error_f("alloc failed"); return SSH_ERR_ALLOC_FAIL; } if ((opts[nopts]->name = strdup(name)) == NULL || (opts[nopts]->value = strdup(value)) == NULL) { error_f("alloc failed"); return SSH_ERR_ALLOC_FAIL; } opts[nopts]->required = required; return 0; } static int make_options(const char *device, const char *user_id, struct sk_option ***optsp) { struct sk_option **opts = NULL; size_t nopts = 0; int r, ret = SSH_ERR_INTERNAL_ERROR; if (device != NULL && (r = sshsk_add_option(&opts, &nopts, "device", device, 0)) != 0) { ret = r; goto out; } if (user_id != NULL && (r = sshsk_add_option(&opts, &nopts, "user", user_id, 0)) != 0) { ret = r; goto out; } /* success */ *optsp = opts; opts = NULL; nopts = 0; ret = 0; out: sshsk_free_options(opts); return ret; } static int fill_attestation_blob(const struct sk_enroll_response *resp, struct sshbuf *attest) { int r; if (attest == NULL) return 0; /* nothing to do */ if ((r = sshbuf_put_cstring(attest, "ssh-sk-attest-v01")) != 0 || (r = sshbuf_put_string(attest, resp->attestation_cert, resp->attestation_cert_len)) != 0 || (r = sshbuf_put_string(attest, resp->signature, resp->signature_len)) != 0 || (r = sshbuf_put_string(attest, resp->authdata, resp->authdata_len)) != 0 || (r = sshbuf_put_u32(attest, 0)) != 0 || /* resvd flags */ (r = sshbuf_put_string(attest, NULL, 0)) != 0 /* resvd */) { error_fr(r, "compose"); return r; } /* success */ return 0; } int sshsk_enroll(int type, const char *provider_path, const char *device, const char *application, const char *userid, uint8_t flags, const char *pin, struct sshbuf *challenge_buf, struct sshkey **keyp, struct sshbuf *attest) { struct sshsk_provider *skp = NULL; struct sshkey *key = NULL; u_char randchall[32]; const u_char *challenge; size_t challenge_len; struct sk_enroll_response *resp = NULL; struct sk_option **opts = NULL; int r = SSH_ERR_INTERNAL_ERROR; int alg; debug_f("provider \"%s\", device \"%s\", application \"%s\", " "userid \"%s\", flags 0x%02x, challenge len %zu%s", provider_path, device, application, userid, flags, challenge_buf == NULL ? 0 : sshbuf_len(challenge_buf), (pin != NULL && *pin != '\0') ? " with-pin" : ""); *keyp = NULL; if (attest) sshbuf_reset(attest); if ((r = make_options(device, userid, &opts)) != 0) goto out; switch (type) { #ifdef WITH_OPENSSL case KEY_ECDSA_SK: alg = SSH_SK_ECDSA; break; #endif /* WITH_OPENSSL */ case KEY_ED25519_SK: alg = SSH_SK_ED25519; break; default: error_f("unsupported key type"); r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (provider_path == NULL) { error_f("missing provider"); r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (application == NULL || *application == '\0') { error_f("missing application"); r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (challenge_buf == NULL) { debug_f("using random challenge"); arc4random_buf(randchall, sizeof(randchall)); challenge = randchall; challenge_len = sizeof(randchall); } else if (sshbuf_len(challenge_buf) == 0) { error("Missing enrollment challenge"); r = SSH_ERR_INVALID_ARGUMENT; goto out; } else { challenge = sshbuf_ptr(challenge_buf); challenge_len = sshbuf_len(challenge_buf); debug3_f("using explicit challenge len=%zd", challenge_len); } if ((skp = sshsk_open(provider_path)) == NULL) { r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ goto out; } /* XXX validate flags? */ /* enroll key */ if ((r = skp->sk_enroll(alg, challenge, challenge_len, application, flags, pin, opts, &resp)) != 0) { debug_f("provider \"%s\" failure %d", provider_path, r); r = skerr_to_ssherr(r); goto out; } if ((r = sshsk_key_from_response(alg, application, resp->flags, resp, &key)) != 0) goto out; /* Optionally fill in the attestation information */ if ((r = fill_attestation_blob(resp, attest)) != 0) goto out; /* success */ *keyp = key; key = NULL; /* transferred */ r = 0; out: sshsk_free_options(opts); sshsk_free(skp); sshkey_free(key); sshsk_free_enroll_response(resp); explicit_bzero(randchall, sizeof(randchall)); return r; } #ifdef WITH_OPENSSL static int sshsk_ecdsa_sig(struct sk_sign_response *resp, struct sshbuf *sig) { struct sshbuf *inner_sig = NULL; int r = SSH_ERR_INTERNAL_ERROR; /* Check response validity */ if (resp->sig_r == NULL || resp->sig_s == NULL) { error_f("sk_sign response invalid"); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((inner_sig = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* Prepare and append inner signature object */ if ((r = sshbuf_put_bignum2_bytes(inner_sig, resp->sig_r, resp->sig_r_len)) != 0 || (r = sshbuf_put_bignum2_bytes(inner_sig, resp->sig_s, resp->sig_s_len)) != 0) { error_fr(r, "compose inner"); goto out; } if ((r = sshbuf_put_stringb(sig, inner_sig)) != 0 || (r = sshbuf_put_u8(sig, resp->flags)) != 0 || (r = sshbuf_put_u32(sig, resp->counter)) != 0) { error_fr(r, "compose"); goto out; } #ifdef DEBUG_SK fprintf(stderr, "%s: sig_r:\n", __func__); sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr); fprintf(stderr, "%s: sig_s:\n", __func__); sshbuf_dump_data(resp->sig_s, resp->sig_s_len, stderr); fprintf(stderr, "%s: inner:\n", __func__); sshbuf_dump(inner_sig, stderr); #endif r = 0; out: sshbuf_free(inner_sig); return r; } #endif /* WITH_OPENSSL */ static int sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig) { int r = SSH_ERR_INTERNAL_ERROR; /* Check response validity */ if (resp->sig_r == NULL) { error_f("sk_sign response invalid"); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_put_string(sig, resp->sig_r, resp->sig_r_len)) != 0 || (r = sshbuf_put_u8(sig, resp->flags)) != 0 || (r = sshbuf_put_u32(sig, resp->counter)) != 0) { error_fr(r, "compose"); goto out; } #ifdef DEBUG_SK fprintf(stderr, "%s: sig_r:\n", __func__); sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr); #endif r = 0; out: return r; } int sshsk_sign(const char *provider_path, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat, const char *pin) { struct sshsk_provider *skp = NULL; int r = SSH_ERR_INTERNAL_ERROR; int type, alg; struct sk_sign_response *resp = NULL; struct sshbuf *inner_sig = NULL, *sig = NULL; struct sk_option **opts = NULL; debug_f("provider \"%s\", key %s, flags 0x%02x%s", provider_path, sshkey_type(key), key->sk_flags, (pin != NULL && *pin != '\0') ? " with-pin" : ""); if (sigp != NULL) *sigp = NULL; if (lenp != NULL) *lenp = 0; type = sshkey_type_plain(key->type); switch (type) { #ifdef WITH_OPENSSL case KEY_ECDSA_SK: alg = SSH_SK_ECDSA; break; #endif /* WITH_OPENSSL */ case KEY_ED25519_SK: alg = SSH_SK_ED25519; break; default: return SSH_ERR_INVALID_ARGUMENT; } if (provider_path == NULL || key->sk_key_handle == NULL || key->sk_application == NULL || *key->sk_application == '\0') { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((skp = sshsk_open(provider_path)) == NULL) { r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ goto out; } #ifdef DEBUG_SK fprintf(stderr, "%s: sk_flags = 0x%02x, sk_application = \"%s\"\n", __func__, key->sk_flags, key->sk_application); fprintf(stderr, "%s: sk_key_handle:\n", __func__); sshbuf_dump(key->sk_key_handle, stderr); #endif if ((r = skp->sk_sign(alg, data, datalen, key->sk_application, sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle), key->sk_flags, pin, opts, &resp)) != 0) { debug_f("sk_sign failed with code %d", r); r = skerr_to_ssherr(r); goto out; } /* Assemble signature */ if ((sig = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put_cstring(sig, sshkey_ssh_name_plain(key))) != 0) { error_fr(r, "compose outer"); goto out; } switch (type) { #ifdef WITH_OPENSSL case KEY_ECDSA_SK: if ((r = sshsk_ecdsa_sig(resp, sig)) != 0) goto out; break; #endif /* WITH_OPENSSL */ case KEY_ED25519_SK: if ((r = sshsk_ed25519_sig(resp, sig)) != 0) goto out; break; } #ifdef DEBUG_SK fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", __func__, resp->flags, resp->counter); fprintf(stderr, "%s: data to sign:\n", __func__); sshbuf_dump_data(data, datalen, stderr); fprintf(stderr, "%s: sigbuf:\n", __func__); sshbuf_dump(sig, stderr); #endif if (sigp != NULL) { if ((*sigp = malloc(sshbuf_len(sig))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sshbuf_ptr(sig), sshbuf_len(sig)); } if (lenp != NULL) *lenp = sshbuf_len(sig); /* success */ r = 0; out: sshsk_free_options(opts); sshsk_free(skp); sshsk_free_sign_response(resp); sshbuf_free(sig); sshbuf_free(inner_sig); return r; } static void sshsk_free_sk_resident_keys(struct sk_resident_key **rks, size_t nrks) { size_t i; if (nrks == 0 || rks == NULL) return; for (i = 0; i < nrks; i++) { free(rks[i]->application); freezero(rks[i]->user_id, rks[i]->user_id_len); 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); } static void sshsk_free_resident_key(struct sshsk_resident_key *srk) { if (srk == NULL) return; sshkey_free(srk->key); freezero(srk->user_id, srk->user_id_len); free(srk); } void sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks) { size_t i; if (srks == NULL || nsrks == 0) return; for (i = 0; i < nsrks; i++) sshsk_free_resident_key(srks[i]); free(srks); } int sshsk_load_resident(const char *provider_path, const char *device, const char *pin, u_int flags, struct sshsk_resident_key ***srksp, size_t *nsrksp) { struct sshsk_provider *skp = NULL; int r = SSH_ERR_INTERNAL_ERROR; struct sk_resident_key **rks = NULL; size_t i, nrks = 0, nsrks = 0; struct sshkey *key = NULL; struct sshsk_resident_key *srk = NULL, **srks = NULL, **tmp; uint8_t sk_flags; struct sk_option **opts = NULL; debug_f("provider \"%s\"%s", provider_path, (pin != NULL && *pin != '\0') ? ", have-pin": ""); if (srksp == NULL || nsrksp == NULL) return SSH_ERR_INVALID_ARGUMENT; *srksp = NULL; *nsrksp = 0; if ((r = make_options(device, NULL, &opts)) != 0) goto out; if ((skp = sshsk_open(provider_path)) == NULL) { r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ goto out; } if ((r = skp->sk_load_resident_keys(pin, opts, &rks, &nrks)) != 0) { error("Provider \"%s\" returned failure %d", provider_path, r); r = skerr_to_ssherr(r); goto out; } for (i = 0; i < nrks; i++) { debug3_f("rk %zu: slot %zu, alg %d, app \"%s\", uidlen %zu", i, rks[i]->slot, rks[i]->alg, rks[i]->application, rks[i]->user_id_len); /* 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; } sk_flags = SSH_SK_USER_PRESENCE_REQD|SSH_SK_RESIDENT_KEY; if ((rks[i]->flags & SSH_SK_USER_VERIFICATION_REQD)) sk_flags |= SSH_SK_USER_VERIFICATION_REQD; if ((r = sshsk_key_from_response(rks[i]->alg, rks[i]->application, sk_flags, &rks[i]->key, &key)) != 0) goto out; if ((srk = calloc(1, sizeof(*srk))) == NULL) { error_f("calloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } srk->key = key; key = NULL; /* transferred */ if ((srk->user_id = calloc(1, rks[i]->user_id_len)) == NULL) { error_f("calloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(srk->user_id, rks[i]->user_id, rks[i]->user_id_len); srk->user_id_len = rks[i]->user_id_len; if ((tmp = recallocarray(srks, nsrks, nsrks + 1, sizeof(*tmp))) == NULL) { error_f("recallocarray failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } srks = tmp; srks[nsrks++] = srk; srk = NULL; /* XXX synthesise comment */ } /* success */ *srksp = srks; *nsrksp = nsrks; srks = NULL; nsrks = 0; r = 0; out: sshsk_free_options(opts); sshsk_free(skp); sshsk_free_sk_resident_keys(rks, nrks); sshkey_free(key); sshsk_free_resident_key(srk); sshsk_free_resident_keys(srks, nsrks); return r; } #endif /* ENABLE_SK */ openssh-10.0p1/PaxHeaders.10889/ssh-sk.h100644 001750 001750 0000000003614775415623 0014535xustar0030 atime=1744182234.852367347 openssh-10.0p1/ssh-sk.h010064400017500001750000000052541477541562300131260ustar00djmdjm/* $OpenBSD: ssh-sk.h,v 1.11 2021/10/28 02:54:18 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 struct sshsk_resident_key { struct sshkey *key; uint8_t *user_id; size_t user_id_len; }; /* * 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, u_int flags, struct sshsk_resident_key ***srksp, size_t *nsrksp); /* Free an array of sshsk_resident_key (as returned from sshsk_load_resident) */ void sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks); #endif /* _SSH_SK_H */ openssh-10.0p1/PaxHeaders.10889/ssh-xmss.c100644 001750 001750 0000000003614775415623 0015105xustar0030 atime=1744182234.853343754 openssh-10.0p1/ssh-xmss.c010064400017500001750000000241311477541562300134710ustar00djmdjm/* $OpenBSD: ssh-xmss.c,v 1.14 2022/10/28 00:44:44 djm Exp $*/ /* * Copyright (c) 2017 Stefan-Lukas Gazdag. * Copyright (c) 2017 Markus Friedl. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef WITH_XMSS #define SSHKEY_INTERNAL #include #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include "log.h" #include "sshbuf.h" #include "sshkey.h" #include "sshkey-xmss.h" #include "ssherr.h" #include "ssh.h" #include "xmss_fast.h" static void ssh_xmss_cleanup(struct sshkey *k) { freezero(k->xmss_pk, sshkey_xmss_pklen(k)); freezero(k->xmss_sk, sshkey_xmss_sklen(k)); sshkey_xmss_free_state(k); free(k->xmss_name); free(k->xmss_filename); k->xmss_pk = NULL; k->xmss_sk = NULL; k->xmss_name = NULL; k->xmss_filename = NULL; } static int ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b) { if (a->xmss_pk == NULL || b->xmss_pk == NULL) return 0; if (sshkey_xmss_pklen(a) != sshkey_xmss_pklen(b)) return 0; if (memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) != 0) return 0; return 1; } static int ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if (key->xmss_name == NULL || key->xmss_pk == NULL || sshkey_xmss_pklen(key) == 0) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 || (r = sshbuf_put_string(b, key->xmss_pk, sshkey_xmss_pklen(key))) != 0 || (r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0) return r; return 0; } static int ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { int r; if (key->xmss_name == NULL) return SSH_ERR_INVALID_ARGUMENT; /* Note: can't reuse ssh_xmss_serialize_public because of sk order */ if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 || (r = sshbuf_put_string(b, key->xmss_pk, sshkey_xmss_pklen(key))) != 0 || (r = sshbuf_put_string(b, key->xmss_sk, sshkey_xmss_sklen(key))) != 0 || (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0) return r; return 0; } static int ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to) { int r = SSH_ERR_INTERNAL_ERROR; u_int32_t left; size_t pklen; if ((r = sshkey_xmss_init(to, from->xmss_name)) != 0) return r; if (from->xmss_pk == NULL) return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */ if ((pklen = sshkey_xmss_pklen(from)) == 0 || sshkey_xmss_pklen(to) != pklen) return SSH_ERR_INTERNAL_ERROR; if ((to->xmss_pk = malloc(pklen)) == NULL) return SSH_ERR_ALLOC_FAIL; memcpy(to->xmss_pk, from->xmss_pk, pklen); /* simulate number of signatures left on pubkey */ left = sshkey_xmss_signatures_left(from); if (left) sshkey_xmss_enable_maxsign(to, left); return 0; } static int ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b, struct sshkey *key) { size_t len = 0; char *xmss_name = NULL; u_char *pk = NULL; int ret = SSH_ERR_INTERNAL_ERROR; if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0) goto out; if ((ret = sshkey_xmss_init(key, xmss_name)) != 0) goto out; if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) goto out; if (len == 0 || len != sshkey_xmss_pklen(key)) { ret = SSH_ERR_INVALID_FORMAT; goto out; } key->xmss_pk = pk; pk = NULL; if (!sshkey_is_cert(key) && (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0) goto out; /* success */ ret = 0; out: free(xmss_name); freezero(pk, len); return ret; } static int ssh_xmss_deserialize_private(const char *ktype, struct sshbuf *b, struct sshkey *key) { int r; char *xmss_name = NULL; size_t pklen = 0, sklen = 0; u_char *xmss_pk = NULL, *xmss_sk = NULL; /* Note: can't reuse ssh_xmss_deserialize_public because of sk order */ if ((r = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0 || (r = sshbuf_get_string(b, &xmss_pk, &pklen)) != 0 || (r = sshbuf_get_string(b, &xmss_sk, &sklen)) != 0) goto out; if (!sshkey_is_cert(key) && (r = sshkey_xmss_init(key, xmss_name)) != 0) goto out; if (pklen != sshkey_xmss_pklen(key) || sklen != sshkey_xmss_sklen(key)) { r = SSH_ERR_INVALID_FORMAT; goto out; } key->xmss_pk = xmss_pk; key->xmss_sk = xmss_sk; xmss_pk = xmss_sk = NULL; /* optional internal state */ if ((r = sshkey_xmss_deserialize_state_opt(key, b)) != 0) goto out; /* success */ r = 0; out: free(xmss_name); freezero(xmss_pk, pklen); freezero(xmss_sk, sklen); return r; } static int ssh_xmss_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { u_char *sig = NULL; size_t slen = 0, len = 0, required_siglen; unsigned long long smlen; int r, ret; struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (key == NULL || sshkey_type_plain(key->type) != KEY_XMSS || key->xmss_sk == NULL || sshkey_xmss_params(key) == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0) return r; if (datalen >= INT_MAX - required_siglen) return SSH_ERR_INVALID_ARGUMENT; smlen = slen = datalen + required_siglen; if ((sig = malloc(slen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_xmss_get_state(key, 1)) != 0) goto out; if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen, data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) { r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ goto out; } /* encode signature */ if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put_cstring(b, "ssh-xmss@openssh.com")) != 0 || (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) goto out; len = sshbuf_len(b); if (sigp != NULL) { if ((*sigp = malloc(len)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sshbuf_ptr(b), len); } if (lenp != NULL) *lenp = len; /* success */ r = 0; out: if ((ret = sshkey_xmss_update_state(key, 1)) != 0) { /* discard signature since we cannot update the state */ if (r == 0 && sigp != NULL && *sigp != NULL) { explicit_bzero(*sigp, len); free(*sigp); } if (sigp != NULL) *sigp = NULL; if (lenp != NULL) *lenp = 0; r = ret; } sshbuf_free(b); if (sig != NULL) freezero(sig, slen); return r; } static int ssh_xmss_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { struct sshbuf *b = NULL; char *ktype = NULL; const u_char *sigblob; u_char *sm = NULL, *m = NULL; size_t len, required_siglen; unsigned long long smlen = 0, mlen = 0; int r, ret; if (key == NULL || sshkey_type_plain(key->type) != KEY_XMSS || key->xmss_pk == NULL || sshkey_xmss_params(key) == NULL || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0) return r; if (dlen >= INT_MAX - required_siglen) return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0) goto out; if (strcmp("ssh-xmss@openssh.com", ktype) != 0) { r = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } if (sshbuf_len(b) != 0) { r = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } if (len != required_siglen) { r = SSH_ERR_INVALID_FORMAT; goto out; } if (dlen >= SIZE_MAX - len) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } smlen = len + dlen; mlen = smlen; if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(sm, sigblob, len); memcpy(sm+len, data, dlen); if ((ret = xmss_sign_open(m, &mlen, sm, smlen, key->xmss_pk, sshkey_xmss_params(key))) != 0) { debug2_f("xmss_sign_open failed: %d", ret); } if (ret != 0 || mlen != dlen) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } /* XXX compare 'm' and 'data' ? */ /* success */ r = 0; out: if (sm != NULL) freezero(sm, smlen); if (m != NULL) freezero(m, smlen); sshbuf_free(b); free(ktype); return r; } static const struct sshkey_impl_funcs sshkey_xmss_funcs = { /* .size = */ NULL, /* .alloc = */ NULL, /* .cleanup = */ ssh_xmss_cleanup, /* .equal = */ ssh_xmss_equal, /* .ssh_serialize_public = */ ssh_xmss_serialize_public, /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public, /* .ssh_serialize_private = */ ssh_xmss_serialize_private, /* .ssh_deserialize_private = */ ssh_xmss_deserialize_private, /* .generate = */ sshkey_xmss_generate_private_key, /* .copy_public = */ ssh_xmss_copy_public, /* .sign = */ ssh_xmss_sign, /* .verify = */ ssh_xmss_verify, }; const struct sshkey_impl sshkey_xmss_impl = { /* .name = */ "ssh-xmss@openssh.com", /* .shortname = */ "XMSS", /* .sigalg = */ NULL, /* .type = */ KEY_XMSS, /* .nid = */ 0, /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_xmss_funcs, }; const struct sshkey_impl sshkey_xmss_cert_impl = { /* .name = */ "ssh-xmss-cert-v01@openssh.com", /* .shortname = */ "XMSS-CERT", /* .sigalg = */ NULL, /* .type = */ KEY_XMSS_CERT, /* .nid = */ 0, /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 256, /* .funcs = */ &sshkey_xmss_funcs, }; #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/ssh.0100644 001750 001750 0000000003614775415623 0014032xustar0030 atime=1744182234.854320852 openssh-10.0p1/ssh.0010064400017500001750000001457211477541562300124270ustar00djmdjmSSH(1) General Commands Manual SSH(1) NAME ssh M-bM-^@M-^S OpenSSH remote login client SYNOPSIS ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-J destination] [-L address] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-P tag] [-p port] [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] destination [command [argument ...]] ssh [-Q query_option] 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 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 destination, which may be specified as either [user@]hostname or a URI of the form ssh://[user@]hostname[:port]. The user must prove their identity to the remote machine using one of several methods (see below). If a command is specified, it will be executed on the remote host instead of a login shell. A complete command line may be specified as command, or it may have additional arguments. If supplied, the arguments will be appended to the command, separated by spaces, before it is sent to the server to be executed. The options are as follows: -4 Forces ssh to use IPv4 addresses only. -6 Forces ssh to use IPv6 addresses only. -A Enables forwarding of connections from an authentication agent such as ssh-agent(1). 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 safer alternative may be to use a jump host (see -J). -a Disables forwarding of the authentication agent connection. -B bind_interface Bind to the address of bind_interface before attempting to connect to the destination host. This is only useful on systems with more than one address. -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). 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 in ssh_config(5). -c cipher_spec Selects the cipher specification for encrypting the session. 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. If set to M-bM-^@M-^\noneM-bM-^@M-^], no configuration files will be read. -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. Refer to the description of ForkAfterAuthentication in ssh_config(5) for details. -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 keys for user authentication. -i identity_file Selects a file from which the identity (private key) for public key authentication is read. You can also specify a public key file to use the corresponding private key that is loaded in ssh-agent(1) when the private key file is not present locally. The default is ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519_sk. 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). If no certificates have been explicitly specified by the CertificateFile directive, ssh will also try to load certificate information from the filename obtained by appending -cert.pub to identity filenames. -J destination Connect to the target host by first making an ssh connection to the jump host described by destination and then establishing a TCP forwarding to the ultimate destination from there. Multiple jump hops may be specified separated by comma characters. IPv6 addresses can be specified by enclosing the address in square brackets. This is a shortcut to specify a 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 ~/.ssh/config to specify configuration for jump hosts. -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 -L [bind_address:]port:remote_socket -L local_socket:host:hostport -L local_socket:remote_socket 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 port on the local side, optionally bound to the specified bind_address, or to a Unix socket. Whenever a connection is made to the local port or socket, the connection is forwarded over the secure channel, and a connection is made to either host port hostport, or the Unix socket remote_socket, from the remote machine. Port forwardings can also be specified in the configuration file. Only the superuser can forward privileged ports. IPv6 addresses can be specified by enclosing the address in square brackets. 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 but with confirmation required using ssh-askpass(1) before each operation that changes the multiplexing state (e.g. opening a new session). Refer to the description of ControlMaster in ssh_config(5) for details. -m mac_spec A comma-separated list of MAC (message authentication code) algorithms, specified in order of preference. See the MACs keyword in ssh_config(5) for more information. -N Do not execute a remote command. This is useful for just forwarding ports. Refer to the description of SessionType in ssh_config(5) for details. -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.) Refer to the description of StdinNull in ssh_config(5) for details. -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-^\proxyM-bM-^@M-^] (connect to a running multiplexing master in proxy mode), 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). AddKeysToAgent AddressFamily BatchMode BindAddress BindInterface CASignatureAlgorithms CanonicalDomains CanonicalizeFallbackLocal CanonicalizeHostname CanonicalizeMaxDots CanonicalizePermittedCNAMEs CertificateFile ChannelTimeout CheckHostIP Ciphers ClearAllForwardings Compression ConnectTimeout ConnectionAttempts ControlMaster ControlPath ControlPersist DynamicForward EnableEscapeCommandline EnableSSHKeysign EscapeChar ExitOnForwardFailure FingerprintHash ForkAfterAuthentication ForwardAgent ForwardX11 ForwardX11Timeout ForwardX11Trusted GSSAPIAuthentication GSSAPIDelegateCredentials GatewayPorts GlobalKnownHostsFile HashKnownHosts Host HostKeyAlgorithms HostKeyAlias HostbasedAcceptedAlgorithms HostbasedAuthentication Hostname IPQoS IdentitiesOnly IdentityAgent IdentityFile IgnoreUnknown Include KbdInteractiveAuthentication KbdInteractiveDevices KexAlgorithms KnownHostsCommand LocalCommand LocalForward LogLevel LogVerbose MACs NoHostAuthenticationForLocalhost NumberOfPasswordPrompts ObscureKeystrokeTiming PKCS11Provider PasswordAuthentication PermitLocalCommand PermitRemoteOpen Port PreferredAuthentications ProxyCommand ProxyJump ProxyUseFdpass PubkeyAcceptedAlgorithms PubkeyAuthentication RekeyLimit RemoteCommand RemoteForward RequestTTY RequiredRSASize RevokedHostKeys SecurityKeyProvider SendEnv ServerAliveCountMax ServerAliveInterval SessionType SetEnv StdinNull StreamLocalBindMask StreamLocalBindUnlink StrictHostKeyChecking SyslogFacility TCPKeepAlive Tag Tunnel TunnelDevice UpdateHostKeys User UserKnownHostsFile VerifyHostKeyDNS VisualHostKey XAuthLocation -P tag Specify a tag name that may be used to select configuration in ssh_config(5). Refer to the Tag and Match keywords in ssh_config(5) for more information. -p port Port to connect to on the remote host. This can be specified on a per-host basis in the configuration file. -Q query_option Queries for the algorithms supported by one of the following features: cipher (supported symmetric ciphers), cipher-auth (supported symmetric ciphers that support authenticated encryption), help (supported query terms for use with the -Q flag), mac (supported message integrity codes), kex (key exchange algorithms), key (key types), key-ca-sign (valid CA signature algorithms for certificates), key-cert (certificate key types), key-plain (non-certificate key types), key-sig (all key types and signature algorithms), protocol-version (supported SSH protocol versions), and sig (supported signature algorithms). Alternatively, any keyword from ssh_config(5) or sshd_config(5) that takes an algorithm list may be used as an alias for the corresponding query_option. -q Quiet mode. Causes most warning and diagnostic messages to be suppressed. -R [bind_address:]port:host:hostport -R [bind_address:]port:local_socket -R remote_socket:host:hostport -R remote_socket:local_socket -R [bind_address:]port Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side. This works by allocating a socket to listen to either a TCP 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 host port hostport, or local_socket, or, if no explicit destination was specified, ssh will act as a SOCKS 4/5 proxy and forward connections to the destinations requested by the remote SOCKS client. 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, TCP listening sockets 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 facilitate the use of SSH as a secure transport for other applications (e.g. sftp(1)). The subsystem is specified as the remote command. Refer to the description of SessionType in ssh_config(5) for details. -T Disable pseudo-terminal allocation. -t Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -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, though these can be overridden in the configuration file or using -o command line options. -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 will be set to the default tunnel mode, which is M-bM-^@M-^\point-to-pointM-bM-^@M-^]. If a different Tunnel forwarding mode it desired, then it should be specified before -w. -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. 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 protocol 2. The methods available for authentication are: GSSAPI-based authentication, host-based authentication, public key authentication, keyboard-interactive authentication, and password authentication. Authentication methods are tried in the order specified above, though PreferredAuthentications can be used to change the default order. 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, the user is non-root 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 ECDSA, Ed25519 or 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 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 LogLevel to DEBUG or higher (e.g. by using the -v flag). The user creates their key pair by running ssh-keygen(1). This stores the private key in ~/.ssh/id_ecdsa (ECDSA), ~/.ssh/id_ecdsa_sk (authenticator-hosted ECDSA), ~/.ssh/id_ed25519 (Ed25519), ~/.ssh/id_ed25519_sk (authenticator-hosted Ed25519), or ~/.ssh/id_rsa (RSA) and stores the public key in ~/.ssh/id_ecdsa.pub (ECDSA), ~/.ssh/id_ecdsa_sk.pub (authenticator-hosted ECDSA), ~/.ssh/id_ed25519.pub (Ed25519), ~/.ssh/id_ed25519_sk.pub (authenticator- hosted Ed25519), or ~/.ssh/id_rsa.pub (RSA) in the user's home directory. The user should then copy the public key to ~/.ssh/authorized_keys in their 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) and (optionally) the AddKeysToAgent directive in ssh_config(5) for more information. Keyboard-interactive authentication works as follows: The server sends an arbitrary "challenge" text and prompts for a response, possibly multiple times. Examples of keyboard-interactive 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 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. If an interactive session is requested, ssh by default will only request a pseudo-terminal (pty) for interactive sessions when the client has one. The flags -T and -t can be used to override this behaviour. If a pseudo-terminal has been allocated, the user may use the escape characters noted below. 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 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 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 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 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. 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 ssh, specifying the ports to be used to forward the connection. After that it is possible to start the program locally, and ssh will encrypt and forward the connection to the remote server. The following example tunnels an IRC session from the client to an IRC server at M-bM-^@M-^\server.example.comM-bM-^@M-^], joining channel M-bM-^@M-^\#usersM-bM-^@M-^], nickname M-bM-^@M-^\pinkyM-bM-^@M-^], using the standard IRC port, 6667: $ ssh -f -L 6667:localhost:6667 server.example.com sleep 10 $ irc -c '#users' pinky IRC/127.0.0.1 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 program which is going to use the tunnel. 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. If only legacy (MD5) fingerprints for the server are available, the ssh-keygen(1) -E option may be used to downgrade the fingerprint algorithm to match. 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_ASKPASS_REQUIRE Allows further control over the use of an askpass program. If this variable is set to M-bM-^@M-^\neverM-bM-^@M-^] then ssh will never attempt to use one. If it is set to M-bM-^@M-^\preferM-bM-^@M-^], then ssh will prefer to use the askpass program instead of the TTY when requesting passwords. Finally, if the variable is set to M-bM-^@M-^\forceM-bM-^@M-^], then the askpass program will be used for all passphrase input regardless of whether DISPLAY is set. 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. SSH_TUNNEL Optionally set by sshd(8) to contain the interface names assigned if tunnel forwarding was requested by the client. SSH_USER_AUTH Optionally set by 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. 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 (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/id_ecdsa ~/.ssh/id_ecdsa_sk ~/.ssh/id_ed25519 ~/.ssh/id_ed25519_sk ~/.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 AES-128. ~/.ssh/id_ecdsa.pub ~/.ssh/id_ecdsa_sk.pub ~/.ssh/id_ed25519.pub ~/.ssh/id_ed25519_sk.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_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. /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 7.6 December 4, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh.1100644 001750 001750 0000000003614775415623 0014033xustar0030 atime=1744182234.854320852 openssh-10.0p1/ssh.1010064400017500001750000001346121477541562300124250ustar00djmdjm.\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $OpenBSD: ssh.1,v 1.444 2024/12/04 14:37:55 djm Exp $ .Dd $Mdocdate: December 4 2024 $ .Dt SSH 1 .Os .Sh NAME .Nm ssh .Nd OpenSSH remote login client .Sh SYNOPSIS .Nm ssh .Op Fl 46AaCfGgKkMNnqsTtVvXxYy .Op Fl B Ar bind_interface .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec .Op Fl D Oo Ar bind_address : Oc Ns Ar port .Op Fl E Ar log_file .Op Fl e Ar escape_char .Op Fl F Ar configfile .Op Fl I Ar pkcs11 .Op Fl i Ar identity_file .Op Fl J Ar destination .Op Fl L Ar address .Op Fl l Ar login_name .Op Fl m Ar mac_spec .Op Fl O Ar ctl_cmd .Op Fl o Ar option .Op Fl P Ar tag .Op Fl p Ar port .Op Fl R Ar address .Op Fl S Ar ctl_path .Op Fl W Ar host : Ns Ar port .Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun .Ar destination .Op Ar command Op Ar argument ... .Nm .Op Fl Q Ar query_option .Sh DESCRIPTION .Nm (SSH client) is a program for logging into a remote machine and for executing commands on a remote machine. It is intended to provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections, arbitrary TCP ports and .Ux Ns -domain sockets can also be forwarded over the secure channel. .Pp .Nm connects and logs into the specified .Ar destination , which may be specified as either .Sm off .Oo user @ Oc hostname .Sm on or a URI of the form .Sm off .No ssh:// Oo user @ Oc hostname Op : port . .Sm on The user must prove their identity to the remote machine using one of several methods (see below). .Pp If a .Ar command is specified, it will be executed on the remote host instead of a login shell. A complete command line may be specified as .Ar command , or it may have additional arguments. If supplied, the arguments will be appended to the command, separated by spaces, before it is sent to the server to be executed. .Pp The options are as follows: .Pp .Bl -tag -width Ds -compact .It Fl 4 Forces .Nm to use IPv4 addresses only. .Pp .It Fl 6 Forces .Nm to use IPv6 addresses only. .Pp .It Fl A Enables forwarding of connections from an authentication agent such as .Xr ssh-agent 1 . This can also be specified on a per-host basis in a configuration file. .Pp Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent's .Ux Ns -domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. A safer alternative may be to use a jump host (see .Fl J ) . .Pp .It Fl a Disables forwarding of the authentication agent connection. .Pp .It Fl B Ar bind_interface Bind to the address of .Ar bind_interface before attempting to connect to the destination host. This is only useful on systems with more than one address. .Pp .It Fl b Ar bind_address Use .Ar bind_address on the local machine as the source address of the connection. Only useful on systems with more than one address. .Pp .It Fl C Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11, TCP and .Ux Ns -domain connections). The compression algorithm is the same used by .Xr gzip 1 . Compression is desirable on modem lines and other slow connections, but will only slow down things on fast networks. The default value can be set on a host-by-host basis in the configuration files; see the .Cm Compression option in .Xr ssh_config 5 . .Pp .It Fl c Ar cipher_spec Selects the cipher specification for encrypting the session. .Ar cipher_spec is a comma-separated list of ciphers listed in order of preference. See the .Cm Ciphers keyword in .Xr ssh_config 5 for more information. .Pp .It Fl D Xo .Sm off .Oo Ar bind_address : Oc .Ar port .Sm on .Xc Specifies a local .Dq dynamic application-level port forwarding. This works by allocating a socket to listen to .Ar port on the local side, optionally bound to the specified .Ar bind_address . Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, and .Nm will act as a SOCKS server. Only root can forward privileged ports. Dynamic port forwardings can also be specified in the configuration file. .Pp IPv6 addresses can be specified by enclosing the address in square brackets. Only the superuser can forward privileged ports. By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Dq localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. .Pp .It Fl E Ar log_file Append debug logs to .Ar log_file instead of standard error. .Pp .It Fl e Ar escape_char Sets the escape character for sessions with a pty (default: .Ql ~ ) . The escape character is only recognized at the beginning of a line. The escape character followed by a dot .Pq Ql \&. closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once. Setting the character to .Dq none disables any escapes and makes the session fully transparent. .Pp .It Fl F Ar configfile Specifies an alternative per-user configuration file. If a configuration file is given on the command line, the system-wide configuration file .Pq Pa /etc/ssh/ssh_config will be ignored. The default for the per-user configuration file is .Pa ~/.ssh/config . If set to .Dq none , no configuration files will be read. .Pp .It Fl f Requests .Nm to go to background just before command execution. This is useful if .Nm is going to ask for passwords or passphrases, but the user wants it in the background. This implies .Fl n . The recommended way to start X11 programs at a remote site is with something like .Ic ssh -f host xterm . .Pp If the .Cm ExitOnForwardFailure configuration option is set to .Dq yes , then a client started with .Fl f will wait for all remote port forwards to be successfully established before placing itself in the background. Refer to the description of .Cm ForkAfterAuthentication in .Xr ssh_config 5 for details. .Pp .It Fl G Causes .Nm to print its configuration after evaluating .Cm Host and .Cm Match blocks and exit. .Pp .It Fl g Allows remote hosts to connect to local forwarded ports. If used on a multiplexed connection, then this option must be specified on the master process. .Pp .It Fl I Ar pkcs11 Specify the PKCS#11 shared library .Nm should use to communicate with a PKCS#11 token providing keys for user authentication. .Pp .It Fl i Ar identity_file Selects a file from which the identity (private key) for public key authentication is read. You can also specify a public key file to use the corresponding private key that is loaded in .Xr ssh-agent 1 when the private key file is not present locally. The default is .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ecdsa_sk , .Pa ~/.ssh/id_ed25519 and .Pa ~/.ssh/id_ed25519_sk . Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple .Fl i options (and multiple identities specified in configuration files). If no certificates have been explicitly specified by the .Cm CertificateFile directive, .Nm will also try to load certificate information from the filename obtained by appending .Pa -cert.pub to identity filenames. .Pp .It Fl J Ar destination Connect to the target host by first making an .Nm connection to the jump host described by .Ar destination and then establishing a TCP forwarding to the ultimate destination from there. Multiple jump hops may be specified separated by comma characters. IPv6 addresses can be specified by enclosing the address in square brackets. This is a shortcut to specify a .Cm ProxyJump configuration directive. Note that configuration directives supplied on the command-line generally apply to the destination host and not any specified jump hosts. Use .Pa ~/.ssh/config to specify configuration for jump hosts. .Pp .It Fl K Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI credentials to the server. .Pp .It Fl k Disables forwarding (delegation) of GSSAPI credentials to the server. .Pp .It Fl L Xo .Sm off .Oo Ar bind_address : Oc .Ar port : host : hostport .Sm on .Xc .It Fl L Xo .Sm off .Oo Ar bind_address : Oc .Ar port : remote_socket .Sm on .Xc .It Fl L Xo .Sm off .Ar local_socket : host : hostport .Sm on .Xc .It Fl L Xo .Sm off .Ar local_socket : remote_socket .Sm on .Xc Specifies that connections to the given TCP port or Unix socket on the local (client) host are to be forwarded to the given host and port, or Unix socket, on the remote side. This works by allocating a socket to listen to either a TCP .Ar port on the local side, optionally bound to the specified .Ar bind_address , or to a Unix socket. Whenever a connection is made to the local port or socket, the connection is forwarded over the secure channel, and a connection is made to either .Ar host port .Ar hostport , or the Unix socket .Ar remote_socket , from the remote machine. .Pp Port forwardings can also be specified in the configuration file. Only the superuser can forward privileged ports. IPv6 addresses can be specified by enclosing the address in square brackets. .Pp By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Dq localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. .Pp .It Fl l Ar login_name Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file. .Pp .It Fl M Places the .Nm client into .Dq master mode for connection sharing. Multiple .Fl M options places .Nm into .Dq master mode but with confirmation required using .Xr ssh-askpass 1 before each operation that changes the multiplexing state (e.g. opening a new session). Refer to the description of .Cm ControlMaster in .Xr ssh_config 5 for details. .Pp .It Fl m Ar mac_spec A comma-separated list of MAC (message authentication code) algorithms, specified in order of preference. See the .Cm MACs keyword in .Xr ssh_config 5 for more information. .Pp .It Fl N Do not execute a remote command. This is useful for just forwarding ports. Refer to the description of .Cm SessionType in .Xr ssh_config 5 for details. .Pp .It Fl n Redirects stdin from .Pa /dev/null (actually, prevents reading from stdin). This must be used when .Nm is run in the background. A common trick is to use this to run X11 programs on a remote machine. For example, .Ic ssh -n shadows.cs.hut.fi emacs & will start an emacs on shadows.cs.hut.fi, and the X11 connection will be automatically forwarded over an encrypted channel. The .Nm program will be put in the background. (This does not work if .Nm needs to ask for a password or passphrase; see also the .Fl f option.) Refer to the description of .Cm StdinNull in .Xr ssh_config 5 for details. .Pp .It Fl O Ar ctl_cmd Control an active connection multiplexing master process. When the .Fl O option is specified, the .Ar ctl_cmd argument is interpreted and passed to the master process. Valid commands are: .Dq check (check that the master process is running), .Dq forward (request forwardings without command execution), .Dq cancel (cancel forwardings), .Dq proxy (connect to a running multiplexing master in proxy mode), .Dq exit (request the master to exit), and .Dq stop (request the master to stop accepting further multiplexing requests). .Pp .It Fl o Ar option Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate command-line flag. For full details of the options listed below, and their possible values, see .Xr ssh_config 5 . .Pp .Bl -tag -width Ds -offset indent -compact .It AddKeysToAgent .It AddressFamily .It BatchMode .It BindAddress .It BindInterface .It CASignatureAlgorithms .It CanonicalDomains .It CanonicalizeFallbackLocal .It CanonicalizeHostname .It CanonicalizeMaxDots .It CanonicalizePermittedCNAMEs .It CertificateFile .It ChannelTimeout .It CheckHostIP .It Ciphers .It ClearAllForwardings .It Compression .It ConnectTimeout .It ConnectionAttempts .It ControlMaster .It ControlPath .It ControlPersist .It DynamicForward .It EnableEscapeCommandline .It EnableSSHKeysign .It EscapeChar .It ExitOnForwardFailure .It FingerprintHash .It ForkAfterAuthentication .It ForwardAgent .It ForwardX11 .It ForwardX11Timeout .It ForwardX11Trusted .It GSSAPIAuthentication .It GSSAPIDelegateCredentials .It GatewayPorts .It GlobalKnownHostsFile .It HashKnownHosts .It Host .It HostKeyAlgorithms .It HostKeyAlias .It HostbasedAcceptedAlgorithms .It HostbasedAuthentication .It Hostname .It IPQoS .It IdentitiesOnly .It IdentityAgent .It IdentityFile .It IgnoreUnknown .It Include .It KbdInteractiveAuthentication .It KbdInteractiveDevices .It KexAlgorithms .It KnownHostsCommand .It LocalCommand .It LocalForward .It LogLevel .It LogVerbose .It MACs .It NoHostAuthenticationForLocalhost .It NumberOfPasswordPrompts .It ObscureKeystrokeTiming .It PKCS11Provider .It PasswordAuthentication .It PermitLocalCommand .It PermitRemoteOpen .It Port .It PreferredAuthentications .It ProxyCommand .It ProxyJump .It ProxyUseFdpass .It PubkeyAcceptedAlgorithms .It PubkeyAuthentication .It RekeyLimit .It RemoteCommand .It RemoteForward .It RequestTTY .It RequiredRSASize .It RevokedHostKeys .It SecurityKeyProvider .It SendEnv .It ServerAliveCountMax .It ServerAliveInterval .It SessionType .It SetEnv .It StdinNull .It StreamLocalBindMask .It StreamLocalBindUnlink .It StrictHostKeyChecking .It SyslogFacility .It TCPKeepAlive .It Tag .It Tunnel .It TunnelDevice .It UpdateHostKeys .It User .It UserKnownHostsFile .It VerifyHostKeyDNS .It VisualHostKey .It XAuthLocation .El .Pp .It Fl P Ar tag Specify a tag name that may be used to select configuration in .Xr ssh_config 5 . Refer to the .Cm Tag and .Cm Match keywords in .Xr ssh_config 5 for more information. .It Fl p Ar port Port to connect to on the remote host. This can be specified on a per-host basis in the configuration file. .Pp .It Fl Q Ar query_option Queries for the algorithms supported by one of the following features: .Ar cipher (supported symmetric ciphers), .Ar cipher-auth (supported symmetric ciphers that support authenticated encryption), .Ar help (supported query terms for use with the .Fl Q flag), .Ar mac (supported message integrity codes), .Ar kex (key exchange algorithms), .Ar key (key types), .Ar key-ca-sign (valid CA signature algorithms for certificates), .Ar key-cert (certificate key types), .Ar key-plain (non-certificate key types), .Ar key-sig (all key types and signature algorithms), .Ar protocol-version (supported SSH protocol versions), and .Ar sig (supported signature algorithms). Alternatively, any keyword from .Xr ssh_config 5 or .Xr sshd_config 5 that takes an algorithm list may be used as an alias for the corresponding query_option. .Pp .It Fl q Quiet mode. Causes most warning and diagnostic messages to be suppressed. .Pp .It Fl R Xo .Sm off .Oo Ar bind_address : Oc .Ar port : host : hostport .Sm on .Xc .It Fl R Xo .Sm off .Oo Ar bind_address : Oc .Ar port : local_socket .Sm on .Xc .It Fl R Xo .Sm off .Ar remote_socket : host : hostport .Sm on .Xc .It Fl R Xo .Sm off .Ar remote_socket : local_socket .Sm on .Xc .It Fl R Xo .Sm off .Oo Ar bind_address : Oc .Ar port .Sm on .Xc Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side. .Pp This works by allocating a socket to listen to either a TCP .Ar port or to a Unix socket on the remote side. Whenever a connection is made to this port or Unix socket, the connection is forwarded over the secure channel, and a connection is made from the local machine to either an explicit destination specified by .Ar host port .Ar hostport , or .Ar local_socket , or, if no explicit destination was specified, .Nm will act as a SOCKS 4/5 proxy and forward connections to the destinations requested by the remote SOCKS client. .Pp Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on the remote machine. IPv6 addresses can be specified by enclosing the address in square brackets. .Pp By default, TCP listening sockets on the server will be bound to the loopback interface only. This may be overridden by specifying a .Ar bind_address . An empty .Ar bind_address , or the address .Ql * , indicates that the remote socket should listen on all interfaces. Specifying a remote .Ar bind_address will only succeed if the server's .Cm GatewayPorts option is enabled (see .Xr sshd_config 5 ) . .Pp If the .Ar port argument is .Ql 0 , the listen port will be dynamically allocated on the server and reported to the client at run time. When used together with .Ic -O forward , the allocated port will be printed to the standard output. .Pp .It Fl S Ar ctl_path Specifies the location of a control socket for connection sharing, or the string .Dq none to disable connection sharing. Refer to the description of .Cm ControlPath and .Cm ControlMaster in .Xr ssh_config 5 for details. .Pp .It Fl s May be used to request invocation of a subsystem on the remote system. Subsystems facilitate the use of SSH as a secure transport for other applications (e.g.\& .Xr sftp 1 ) . The subsystem is specified as the remote command. Refer to the description of .Cm SessionType in .Xr ssh_config 5 for details. .Pp .It Fl T Disable pseudo-terminal allocation. .Pp .It Fl t Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple .Fl t options force tty allocation, even if .Nm has no local tty. .Pp .It Fl V Display the version number and exit. .Pp .It Fl v Verbose mode. Causes .Nm to print debugging messages about its progress. This is helpful in debugging connection, authentication, and configuration problems. Multiple .Fl v options increase the verbosity. The maximum is 3. .Pp .It Fl W Ar host : Ns Ar port Requests that standard input and output on the client be forwarded to .Ar host on .Ar port over the secure channel. Implies .Fl N , .Fl T , .Cm ExitOnForwardFailure and .Cm ClearAllForwardings , though these can be overridden in the configuration file or using .Fl o command line options. .Pp .It Fl w Xo .Ar local_tun Ns Op : Ns Ar remote_tun .Xc Requests tunnel device forwarding with the specified .Xr tun 4 devices between the client .Pq Ar local_tun and the server .Pq Ar remote_tun . .Pp The devices may be specified by numerical ID or the keyword .Dq any , which uses the next available tunnel device. If .Ar remote_tun is not specified, it defaults to .Dq any . See also the .Cm Tunnel and .Cm TunnelDevice directives in .Xr ssh_config 5 . .Pp If the .Cm Tunnel directive is unset, it will be set to the default tunnel mode, which is .Dq point-to-point . If a different .Cm Tunnel forwarding mode it desired, then it should be specified before .Fl w . .Pp .It Fl X Enables X11 forwarding. This can also be specified on a per-host basis in a configuration file. .Pp X11 forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the user's X authorization database) can access the local X11 display through the forwarded connection. An attacker may then be able to perform activities such as keystroke monitoring. .Pp For this reason, X11 forwarding is subjected to X11 SECURITY extension restrictions by default. Refer to the .Nm .Fl Y option and the .Cm ForwardX11Trusted directive in .Xr ssh_config 5 for more information. .Pp .It Fl x Disables X11 forwarding. .Pp .It Fl Y Enables trusted X11 forwarding. Trusted X11 forwardings are not subjected to the X11 SECURITY extension controls. .Pp .It Fl y Send log information using the .Xr syslog 3 system module. By default this information is sent to stderr. .El .Pp .Nm may additionally obtain configuration data from a per-user configuration file and a system-wide configuration file. The file format and configuration options are described in .Xr ssh_config 5 . .Sh AUTHENTICATION The OpenSSH SSH client supports SSH protocol 2. .Pp The methods available for authentication are: GSSAPI-based authentication, host-based authentication, public key authentication, keyboard-interactive authentication, and password authentication. Authentication methods are tried in the order specified above, though .Cm PreferredAuthentications can be used to change the default order. .Pp Host-based authentication works as follows: If the machine the user logs in from is listed in .Pa /etc/hosts.equiv or .Pa /etc/shosts.equiv on the remote machine, the user is non-root and the user names are the same on both sides, or if the files .Pa ~/.rhosts or .Pa ~/.shosts exist in the user's home directory on the remote machine and contain a line containing the name of the client machine and the name of the user on that machine, the user is considered for login. Additionally, the server .Em must be able to verify the client's host key (see the description of .Pa /etc/ssh/ssh_known_hosts and .Pa ~/.ssh/known_hosts , below) for login to be permitted. This authentication method closes security holes due to IP spoofing, DNS spoofing, and routing spoofing. [Note to the administrator: .Pa /etc/hosts.equiv , .Pa ~/.rhosts , and the rlogin/rsh protocol in general, are inherently insecure and should be disabled if security is desired.] .Pp Public key authentication works as follows: The scheme is based on public-key cryptography, using cryptosystems where encryption and decryption are done using separate keys, and it is unfeasible to derive the decryption key from the encryption key. The idea is that each user creates a public/private key pair for authentication purposes. The server knows the public key, and only the user knows the private key. .Nm implements public key authentication protocol automatically, using one of the ECDSA, Ed25519 or RSA algorithms. .Pp The file .Pa ~/.ssh/authorized_keys lists the public keys that are permitted for logging in. When the user logs in, the .Nm program tells the server which key pair it would like to use for authentication. The client proves that it has access to the private key and the server checks that the corresponding public key is authorized to accept the account. .Pp The server may inform the client of errors that prevented public key authentication from succeeding after authentication completes using a different method. These may be viewed by increasing the .Cm LogLevel to .Cm DEBUG or higher (e.g. by using the .Fl v flag). .Pp The user creates their key pair by running .Xr ssh-keygen 1 . This stores the private key in .Pa ~/.ssh/id_ecdsa (ECDSA), .Pa ~/.ssh/id_ecdsa_sk (authenticator-hosted ECDSA), .Pa ~/.ssh/id_ed25519 (Ed25519), .Pa ~/.ssh/id_ed25519_sk (authenticator-hosted Ed25519), or .Pa ~/.ssh/id_rsa (RSA) and stores the public key in .Pa ~/.ssh/id_ecdsa.pub (ECDSA), .Pa ~/.ssh/id_ecdsa_sk.pub (authenticator-hosted ECDSA), .Pa ~/.ssh/id_ed25519.pub (Ed25519), .Pa ~/.ssh/id_ed25519_sk.pub (authenticator-hosted Ed25519), or .Pa ~/.ssh/id_rsa.pub (RSA) in the user's home directory. The user should then copy the public key to .Pa ~/.ssh/authorized_keys in their home directory on the remote machine. The .Pa authorized_keys file corresponds to the conventional .Pa ~/.rhosts file, and has one key per line, though the lines can be very long. After this, the user can log in without giving the password. .Pp A variation on public key authentication is available in the form of certificate authentication: instead of a set of public/private keys, signed certificates are used. This has the advantage that a single trusted certification authority can be used in place of many public/private keys. See the CERTIFICATES section of .Xr ssh-keygen 1 for more information. .Pp The most convenient way to use public key or certificate authentication may be with an authentication agent. See .Xr ssh-agent 1 and (optionally) the .Cm AddKeysToAgent directive in .Xr ssh_config 5 for more information. .Pp Keyboard-interactive authentication works as follows: The server sends an arbitrary .Qq challenge text and prompts for a response, possibly multiple times. Examples of keyboard-interactive authentication include .Bx Authentication (see .Xr login.conf 5 ) and PAM (some .Pf non- Ox systems). .Pp Finally, if other authentication methods fail, .Nm prompts the user for a password. The password is sent to the remote host for checking; however, since all communications are encrypted, the password cannot be seen by someone listening on the network. .Pp .Nm automatically maintains and checks a database containing identification for all hosts it has ever been used with. Host keys are stored in .Pa ~/.ssh/known_hosts in the user's home directory. Additionally, the file .Pa /etc/ssh/ssh_known_hosts is automatically checked for known hosts. Any new hosts are automatically added to the user's file. If a host's identification ever changes, .Nm warns about this and disables password authentication to prevent server spoofing or man-in-the-middle attacks, which could otherwise be used to circumvent the encryption. The .Cm StrictHostKeyChecking option can be used to control logins to machines whose host key is not known or has changed. .Pp When the user's identity has been accepted by the server, the server either executes the given command in a non-interactive session or, if no command has been specified, logs into the machine and gives the user a normal shell as an interactive session. All communication with the remote command or shell will be automatically encrypted. .Pp If an interactive session is requested, .Nm by default will only request a pseudo-terminal (pty) for interactive sessions when the client has one. The flags .Fl T and .Fl t can be used to override this behaviour. .Pp If a pseudo-terminal has been allocated, the user may use the escape characters noted below. .Pp If no pseudo-terminal has been allocated, the session is transparent and can be used to reliably transfer binary data. On most systems, setting the escape character to .Dq none will also make the session transparent even if a tty is used. .Pp The session terminates when the command or shell on the remote machine exits and all X11 and TCP connections have been closed. .Sh ESCAPE CHARACTERS When a pseudo-terminal has been requested, .Nm supports a number of functions through the use of an escape character. .Pp A single tilde character can be sent as .Ic ~~ or by following the tilde by a character other than those described below. The escape character must always follow a newline to be interpreted as special. The escape character can be changed in configuration files using the .Cm EscapeChar configuration directive or on the command line by the .Fl e option. .Pp The supported escapes (assuming the default .Ql ~ ) are: .Bl -tag -width Ds .It Cm ~. Disconnect. .It Cm ~^Z Background .Nm . .It Cm ~# List forwarded connections. .It Cm ~& Background .Nm at logout when waiting for forwarded connection / X11 sessions to terminate. .It Cm ~? Display a list of escape characters. .It Cm ~B Send a BREAK to the remote system (only useful if the peer supports it). .It Cm ~C Open command line. Currently this allows the addition of port forwardings using the .Fl L , .Fl R and .Fl D options (see above). It also allows the cancellation of existing port-forwardings with .Sm off .Fl KL Oo Ar bind_address : Oc Ar port .Sm on for local, .Sm off .Fl KR Oo Ar bind_address : Oc Ar port .Sm on for remote and .Sm off .Fl KD Oo Ar bind_address : Oc Ar port .Sm on for dynamic port-forwardings. .Ic !\& Ns Ar command allows the user to execute a local command if the .Ic PermitLocalCommand option is enabled in .Xr ssh_config 5 . Basic help is available, using the .Fl h option. .It Cm ~R Request rekeying of the connection (only useful if the peer supports it). .It Cm ~V Decrease the verbosity .Pq Ic LogLevel when errors are being written to stderr. .It Cm ~v Increase the verbosity .Pq Ic LogLevel when errors are being written to stderr. .El .Sh TCP FORWARDING Forwarding of arbitrary TCP connections over a secure channel can be specified either on the command line or in a configuration file. One possible application of TCP forwarding is a secure connection to a mail server; another is going through firewalls. .Pp In the example below, we look at encrypting communication for an IRC client, even though the IRC server it connects to does not directly support encrypted communication. This works as follows: the user connects to the remote host using .Nm , specifying the ports to be used to forward the connection. After that it is possible to start the program locally, and .Nm will encrypt and forward the connection to the remote server. .Pp The following example tunnels an IRC session from the client to an IRC server at .Dq server.example.com , joining channel .Dq #users , nickname .Dq pinky , using the standard IRC port, 6667: .Bd -literal -offset 4n $ ssh -f -L 6667:localhost:6667 server.example.com sleep 10 $ irc -c '#users' pinky IRC/127.0.0.1 .Ed .Pp The .Fl f option backgrounds .Nm and the remote command .Dq sleep 10 is specified to allow an amount of time (10 seconds, in the example) to start the program which is going to use the tunnel. If no connections are made within the time specified, .Nm will exit. .Sh X11 FORWARDING If the .Cm ForwardX11 variable is set to .Dq yes (or see the description of the .Fl X , .Fl x , and .Fl Y options above) and the user is using X11 (the .Ev DISPLAY environment variable is set), the connection to the X11 display is automatically forwarded to the remote side in such a way that any X11 programs started from the shell (or command) will go through the encrypted channel, and the connection to the real X server will be made from the local machine. The user should not manually set .Ev DISPLAY . Forwarding of X11 connections can be configured on the command line or in configuration files. .Pp The .Ev DISPLAY value set by .Nm will point to the server machine, but with a display number greater than zero. This is normal, and happens because .Nm creates a .Dq proxy X server on the server machine for forwarding the connections over the encrypted channel. .Pp .Nm will also automatically set up Xauthority data on the server machine. For this purpose, it will generate a random authorization cookie, store it in Xauthority on the server, and verify that any forwarded connections carry this cookie and replace it by the real cookie when the connection is opened. The real authentication cookie is never sent to the server machine (and no cookies are sent in the plain). .Pp If the .Cm ForwardAgent variable is set to .Dq yes (or see the description of the .Fl A and .Fl a options above) and the user is using an authentication agent, the connection to the agent is automatically forwarded to the remote side. .Sh VERIFYING HOST KEYS When connecting to a server for the first time, a fingerprint of the server's public key is presented to the user (unless the option .Cm StrictHostKeyChecking has been disabled). Fingerprints can be determined using .Xr ssh-keygen 1 : .Pp .Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key .Pp If the fingerprint is already known, it can be matched and the key can be accepted or rejected. If only legacy (MD5) fingerprints for the server are available, the .Xr ssh-keygen 1 .Fl E option may be used to downgrade the fingerprint algorithm to match. .Pp Because of the difficulty of comparing host keys just by looking at fingerprint strings, there is also support to compare host keys visually, using .Em random art . By setting the .Cm VisualHostKey option to .Dq yes , a small ASCII graphic gets displayed on every login to a server, no matter if the session itself is interactive or not. By learning the pattern a known server produces, a user can easily find out that the host key has changed when a completely different pattern is displayed. Because these patterns are not unambiguous however, a pattern that looks similar to the pattern remembered only gives a good probability that the host key is the same, not guaranteed proof. .Pp To get a listing of the fingerprints along with their random art for all known hosts, the following command line can be used: .Pp .Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts .Pp If the fingerprint is unknown, an alternative method of verification is available: SSH fingerprints verified by DNS. An additional resource record (RR), SSHFP, is added to a zonefile and the connecting client is able to match the fingerprint with that of the key presented. .Pp In this example, we are connecting a client to a server, .Dq host.example.com . The SSHFP resource records should first be added to the zonefile for host.example.com: .Bd -literal -offset indent $ ssh-keygen -r host.example.com. .Ed .Pp The output lines will have to be added to the zonefile. To check that the zone is answering fingerprint queries: .Pp .Dl $ dig -t SSHFP host.example.com .Pp Finally the client connects: .Bd -literal -offset indent $ ssh -o "VerifyHostKeyDNS ask" host.example.com [...] Matching host key fingerprint found in DNS. Are you sure you want to continue connecting (yes/no)? .Ed .Pp See the .Cm VerifyHostKeyDNS option in .Xr ssh_config 5 for more information. .Sh SSH-BASED VIRTUAL PRIVATE NETWORKS .Nm contains support for Virtual Private Network (VPN) tunnelling using the .Xr tun 4 network pseudo-device, allowing two networks to be joined securely. The .Xr sshd_config 5 configuration option .Cm PermitTunnel controls whether the server supports this, and at what level (layer 2 or 3 traffic). .Pp The following example would connect client network 10.0.50.0/24 with remote network 10.0.99.0/24 using a point-to-point connection from 10.1.1.1 to 10.1.1.2, provided that the SSH server running on the gateway to the remote network, at 192.168.1.15, allows it. .Pp On the client: .Bd -literal -offset indent # ssh -f -w 0:1 192.168.1.15 true # ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252 # route add 10.0.99.0/24 10.1.1.2 .Ed .Pp On the server: .Bd -literal -offset indent # ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252 # route add 10.0.50.0/24 10.1.1.1 .Ed .Pp Client access may be more finely tuned via the .Pa /root/.ssh/authorized_keys file (see below) and the .Cm PermitRootLogin server option. The following entry would permit connections on .Xr tun 4 device 1 from user .Dq jane and on tun device 2 from user .Dq john , if .Cm PermitRootLogin is set to .Dq forced-commands-only : .Bd -literal -offset 2n tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john .Ed .Pp Since an SSH-based setup entails a fair amount of overhead, it may be more suited to temporary setups, such as for wireless VPNs. More permanent VPNs are better provided by tools such as .Xr ipsecctl 8 and .Xr isakmpd 8 . .Sh ENVIRONMENT .Nm will normally set the following environment variables: .Bl -tag -width "SSH_ORIGINAL_COMMAND" .It Ev DISPLAY The .Ev DISPLAY variable indicates the location of the X11 server. It is automatically set by .Nm to point to a value of the form .Dq hostname:n , where .Dq hostname indicates the host where the shell runs, and .Sq n is an integer \*(Ge 1. .Nm uses this special value to forward X11 connections over the secure channel. The user should normally not set .Ev DISPLAY explicitly, as that will render the X11 connection insecure (and will require the user to manually copy any required authorization cookies). .It Ev HOME Set to the path of the user's home directory. .It Ev LOGNAME Synonym for .Ev USER ; set for compatibility with systems that use this variable. .It Ev MAIL Set to the path of the user's mailbox. .It Ev PATH Set to the default .Ev PATH , as specified when compiling .Nm . .It Ev SSH_ASKPASS If .Nm needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If .Nm does not have a terminal associated with it but .Ev DISPLAY and .Ev SSH_ASKPASS are set, it will execute the program specified by .Ev SSH_ASKPASS and open an X11 window to read the passphrase. This is particularly useful when calling .Nm from a .Pa .xsession or related script. (Note that on some machines it may be necessary to redirect the input from .Pa /dev/null to make this work.) .It Ev SSH_ASKPASS_REQUIRE Allows further control over the use of an askpass program. If this variable is set to .Dq never then .Nm will never attempt to use one. If it is set to .Dq prefer , then .Nm will prefer to use the askpass program instead of the TTY when requesting passwords. Finally, if the variable is set to .Dq force , then the askpass program will be used for all passphrase input regardless of whether .Ev DISPLAY is set. .It Ev SSH_AUTH_SOCK Identifies the path of a .Ux Ns -domain socket used to communicate with the agent. .It Ev SSH_CONNECTION Identifies the client and server ends of the connection. The variable contains four space-separated values: client IP address, client port number, server IP address, and server port number. .It Ev SSH_ORIGINAL_COMMAND This variable contains the original command line if a forced command is executed. It can be used to extract the original arguments. .It Ev SSH_TTY This is set to the name of the tty (path to the device) associated with the current shell or command. If the current session has no tty, this variable is not set. .It Ev SSH_TUNNEL Optionally set by .Xr sshd 8 to contain the interface names assigned if tunnel forwarding was requested by the client. .It Ev SSH_USER_AUTH Optionally set by .Xr sshd 8 , this variable may contain a pathname to a file that lists the authentication methods successfully used when the session was established, including any public keys that were used. .It Ev TZ This variable is set to indicate the present time zone if it was set when the daemon was started (i.e. the daemon passes the value on to new connections). .It Ev USER Set to the name of the user logging in. .El .Pp Additionally, .Nm reads .Pa ~/.ssh/environment , and adds lines of the format .Dq VARNAME=value to the environment if the file exists and users are allowed to change their environment. For more information, see the .Cm PermitUserEnvironment option in .Xr sshd_config 5 . .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.rhosts This file is used for host-based authentication (see above). On some machines this file may need to be world-readable if the user's home directory is on an NFS partition, because .Xr sshd 8 reads it as root. Additionally, this file must be owned by the user, and must not have write permissions for anyone else. The recommended permission for most machines is read/write for the user, and not accessible by others. .Pp .It Pa ~/.shosts This file is used in exactly the same way as .Pa .rhosts , but allows host-based authentication without permitting login with rlogin/rsh. .Pp .It Pa ~/.ssh/ This directory is the default location for all user-specific configuration and authentication information. There is no general requirement to keep the entire contents of this directory secret, but the recommended permissions are read/write/execute for the user, and not accessible by others. .Pp .It Pa ~/.ssh/authorized_keys Lists the public keys (ECDSA, Ed25519, RSA) that can be used for logging in as this user. The format of this file is described in the .Xr sshd 8 manual page. This file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. .Pp .It Pa ~/.ssh/config This is the per-user configuration file. The file format and configuration options are described in .Xr ssh_config 5 . Because of the potential for abuse, this file must have strict permissions: read/write for the user, and not writable by others. .Pp .It Pa ~/.ssh/environment Contains additional definitions for environment variables; see .Sx ENVIRONMENT , above. .Pp .It Pa ~/.ssh/id_ecdsa .It Pa ~/.ssh/id_ecdsa_sk .It Pa ~/.ssh/id_ed25519 .It Pa ~/.ssh/id_ed25519_sk .It Pa ~/.ssh/id_rsa Contains the private key for authentication. These files contain sensitive data and should be readable by the user but not accessible by others (read/write/execute). .Nm will simply ignore a private key file if it is accessible by others. It is possible to specify a passphrase when generating the key which will be used to encrypt the sensitive part of this file using AES-128. .Pp .It Pa ~/.ssh/id_ecdsa.pub .It Pa ~/.ssh/id_ecdsa_sk.pub .It Pa ~/.ssh/id_ed25519.pub .It Pa ~/.ssh/id_ed25519_sk.pub .It Pa ~/.ssh/id_rsa.pub Contains the public key for authentication. These files are not sensitive and can (but need not) be readable by anyone. .Pp .It Pa ~/.ssh/known_hosts Contains a list of host keys for all hosts the user has logged into that are not already in the systemwide list of known host keys. See .Xr sshd 8 for further details of the format of this file. .Pp .It Pa ~/.ssh/rc Commands in this file are executed by .Nm when the user logs in, just before the user's shell (or command) is started. See the .Xr sshd 8 manual page for more information. .Pp .It Pa /etc/hosts.equiv This file is for host-based authentication (see above). It should only be writable by root. .Pp .It Pa /etc/shosts.equiv This file is used in exactly the same way as .Pa hosts.equiv , but allows host-based authentication without permitting login with rlogin/rsh. .Pp .It Pa /etc/ssh/ssh_config Systemwide configuration file. The file format and configuration options are described in .Xr ssh_config 5 . .Pp .It Pa /etc/ssh/ssh_host_ecdsa_key .It Pa /etc/ssh/ssh_host_ed25519_key .It Pa /etc/ssh/ssh_host_rsa_key These files contain the private parts of the host keys and are used for host-based authentication. .Pp .It Pa /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared by the system administrator to contain the public host keys of all machines in the organization. It should be world-readable. See .Xr sshd 8 for further details of the format of this file. .Pp .It Pa /etc/ssh/sshrc Commands in this file are executed by .Nm when the user logs in, just before the user's shell (or command) is started. See the .Xr sshd 8 manual page for more information. .El .Sh EXIT STATUS .Nm exits with the exit status of the remote command or with 255 if an error occurred. .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 , .Xr ssh-keyscan 1 , .Xr tun 4 , .Xr ssh_config 5 , .Xr ssh-keysign 8 , .Xr sshd 8 .Sh STANDARDS .Rs .%A S. Lehtinen .%A C. Lonvick .%D January 2006 .%R RFC 4250 .%T The Secure Shell (SSH) Protocol Assigned Numbers .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4251 .%T The Secure Shell (SSH) Protocol Architecture .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4252 .%T The Secure Shell (SSH) Authentication Protocol .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4253 .%T The Secure Shell (SSH) Transport Layer Protocol .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4254 .%T The Secure Shell (SSH) Connection Protocol .Re .Pp .Rs .%A J. Schlyter .%A W. Griffin .%D January 2006 .%R RFC 4255 .%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints .Re .Pp .Rs .%A F. Cusack .%A M. Forssen .%D January 2006 .%R RFC 4256 .%T Generic Message Exchange Authentication for the Secure Shell Protocol (SSH) .Re .Pp .Rs .%A J. Galbraith .%A P. Remaker .%D January 2006 .%R RFC 4335 .%T The Secure Shell (SSH) Session Channel Break Extension .Re .Pp .Rs .%A M. Bellare .%A T. Kohno .%A C. Namprempre .%D January 2006 .%R RFC 4344 .%T The Secure Shell (SSH) Transport Layer Encryption Modes .Re .Pp .Rs .%A B. Harris .%D January 2006 .%R RFC 4345 .%T Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol .Re .Pp .Rs .%A M. Friedl .%A N. Provos .%A W. Simpson .%D March 2006 .%R RFC 4419 .%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol .Re .Pp .Rs .%A J. Galbraith .%A R. Thayer .%D November 2006 .%R RFC 4716 .%T The Secure Shell (SSH) Public Key File Format .Re .Pp .Rs .%A D. Stebila .%A J. Green .%D December 2009 .%R RFC 5656 .%T Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer .Re .Pp .Rs .%A A. Perrig .%A D. Song .%D 1999 .%O International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99) .%T Hash Visualization: a New Technique to improve Real-World Security .Re .Sh AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song removed many bugs, re-added newer features and created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. openssh-10.0p1/PaxHeaders.10889/ssh.c100644 001750 001750 0000000003614775415623 0014115xustar0030 atime=1744182234.856273586 openssh-10.0p1/ssh.c010064400017500001750000002234741477541562300125140ustar00djmdjm/* $OpenBSD: ssh.c,v 1.612 2025/04/09 01:24:40 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Ssh client program. This program can be used to log into a remote machine. * The software supports strong authentication, encryption, and forwarding * of X11, TCP/IP, and authentication connections. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 1999 Niels Provos. All rights reserved. * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved. * * Modified to work with SSLeay by Niels Provos * in Canada (German citizen). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #ifdef HAVE_SYS_STAT_H # include #endif #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #endif #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "canohost.h" #include "compat.h" #include "cipher.h" #include "packet.h" #include "sshbuf.h" #include "channels.h" #include "sshkey.h" #include "authfd.h" #include "authfile.h" #include "pathnames.h" #include "dispatch.h" #include "clientloop.h" #include "log.h" #include "misc.h" #include "readconf.h" #include "sshconnect.h" #include "kex.h" #include "mac.h" #include "sshpty.h" #include "match.h" #include "msg.h" #include "version.h" #include "ssherr.h" #include "myproposal.h" #include "utf8.h" #ifdef ENABLE_PKCS11 #include "ssh-pkcs11.h" #endif extern char *__progname; /* Saves a copy of argv for setproctitle emulation */ #ifndef HAVE_SETPROCTITLE static char **saved_av; #endif /* Flag indicating whether debug mode is on. May be set on the command line. */ int debug_flag = 0; /* Flag indicating whether a tty should be requested */ int tty_flag = 0; /* * Flag indicating that the current process should be backgrounded and * a new mux-client launched in the foreground for ControlPersist. */ static int need_controlpersist_detach = 0; /* Copies of flags for ControlPersist foreground mux-client */ static int ostdin_null_flag, osession_type, otty_flag, orequest_tty; static int ofork_after_authentication; /* * General data structure for command line options and options configurable * in configuration files. See readconf.h. */ Options options; /* optional user configfile */ char *config = NULL; /* * Name of the host we are connecting to. This is the name given on the * command line, or the Hostname specified for the user-supplied name in a * configuration file. */ char *host; /* * A config can specify a path to forward, overriding SSH_AUTH_SOCK. If this is * not NULL, forward the socket at this path instead. */ char *forward_agent_sock_path = NULL; /* socket address the host resolves to */ struct sockaddr_storage hostaddr; /* Private host keys. */ Sensitive sensitive_data; /* command to be executed */ struct sshbuf *command; /* # of replies received for global requests */ static int forward_confirms_pending = -1; /* mux.c */ extern int muxserver_sock; extern u_int muxclient_command; /* Prints a help message to the user. This function never returns. */ static void usage(void) { fprintf(stderr, "usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]\n" " [-c cipher_spec] [-D [bind_address:]port] [-E log_file]\n" " [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file]\n" " [-J destination] [-L address] [-l login_name] [-m mac_spec]\n" " [-O ctl_cmd] [-o option] [-P tag] [-p port] [-R address]\n" " [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n" " destination [command [argument ...]]\n" " ssh [-Q query_option]\n" ); exit(255); } static int ssh_session2(struct ssh *, const struct ssh_conn_info *); static void load_public_identity_files(const struct ssh_conn_info *); static void main_sigchld_handler(int); /* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */ static void tilde_expand_paths(char **paths, u_int num_paths) { u_int i; char *cp; for (i = 0; i < num_paths; i++) { cp = tilde_expand_filename(paths[i], getuid()); free(paths[i]); paths[i] = cp; } } /* * Expands the set of percent_expand options used by the majority of keywords * in the client that support percent expansion. * Caller must free returned string. */ static char * default_client_percent_expand(const char *str, const struct ssh_conn_info *cinfo) { return percent_expand(str, DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), (char *)NULL); } /* * Expands the set of percent_expand options used by the majority of keywords * AND perform environment variable substitution. * Caller must free returned string. */ static char * default_client_percent_dollar_expand(const char *str, const struct ssh_conn_info *cinfo) { char *ret; ret = percent_dollar_expand(str, DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), (char *)NULL); if (ret == NULL) fatal("invalid environment variable expansion"); return ret; } /* * Attempt to resolve a host name / port to a set of addresses and * optionally return any CNAMEs encountered along the way. * Returns NULL on failure. * NB. this function must operate with a options having undefined members. */ static struct addrinfo * resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) { char strport[NI_MAXSERV]; const char *errstr = NULL; struct addrinfo hints, *res; int gaierr; LogLevel loglevel = SYSLOG_LEVEL_DEBUG1; if (port <= 0) port = default_ssh_port(); if (cname != NULL) *cname = '\0'; debug3_f("lookup %s:%d", name, port); snprintf(strport, sizeof strport, "%d", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = options.address_family == -1 ? AF_UNSPEC : options.address_family; hints.ai_socktype = SOCK_STREAM; if (cname != NULL) hints.ai_flags = AI_CANONNAME; if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) { if (logerr || (gaierr != EAI_NONAME && gaierr != EAI_NODATA)) loglevel = SYSLOG_LEVEL_ERROR; do_log2(loglevel, "%s: Could not resolve hostname %.100s: %s", __progname, name, ssh_gai_strerror(gaierr)); return NULL; } if (cname != NULL && res->ai_canonname != NULL) { if (!valid_domain(res->ai_canonname, 0, &errstr)) { error("ignoring bad CNAME \"%s\" for host \"%s\": %s", res->ai_canonname, name, errstr); } else if (strlcpy(cname, res->ai_canonname, clen) >= clen) { error_f("host \"%s\" cname \"%s\" too long (max %lu)", name, res->ai_canonname, (u_long)clen); if (clen > 0) *cname = '\0'; } } return res; } /* Returns non-zero if name can only be an address and not a hostname */ static int is_addr_fast(const char *name) { return (strchr(name, '%') != NULL || strchr(name, ':') != NULL || strspn(name, "0123456789.") == strlen(name)); } /* Returns non-zero if name represents a valid, single address */ static int is_addr(const char *name) { char strport[NI_MAXSERV]; struct addrinfo hints, *res; if (is_addr_fast(name)) return 1; snprintf(strport, sizeof strport, "%u", default_ssh_port()); memset(&hints, 0, sizeof(hints)); hints.ai_family = options.address_family == -1 ? AF_UNSPEC : options.address_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; if (getaddrinfo(name, strport, &hints, &res) != 0) return 0; if (res == NULL || res->ai_next != NULL) { freeaddrinfo(res); return 0; } freeaddrinfo(res); return 1; } /* * Attempt to resolve a numeric host address / port to a single address. * Returns a canonical address string. * Returns NULL on failure. * NB. this function must operate with a options having undefined members. */ static struct addrinfo * resolve_addr(const char *name, int port, char *caddr, size_t clen) { char addr[NI_MAXHOST], strport[NI_MAXSERV]; struct addrinfo hints, *res; int gaierr; if (port <= 0) port = default_ssh_port(); snprintf(strport, sizeof strport, "%u", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = options.address_family == -1 ? AF_UNSPEC : options.address_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) { debug2_f("could not resolve name %.100s as address: %s", name, ssh_gai_strerror(gaierr)); return NULL; } if (res == NULL) { debug_f("getaddrinfo %.100s returned no addresses", name); return NULL; } if (res->ai_next != NULL) { debug_f("getaddrinfo %.100s returned multiple addresses", name); goto fail; } if ((gaierr = getnameinfo(res->ai_addr, res->ai_addrlen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) { debug_f("Could not format address for name %.100s: %s", name, ssh_gai_strerror(gaierr)); goto fail; } if (strlcpy(caddr, addr, clen) >= clen) { error_f("host \"%s\" addr \"%s\" too long (max %lu)", name, addr, (u_long)clen); if (clen > 0) *caddr = '\0'; fail: freeaddrinfo(res); return NULL; } return res; } /* * Check whether the cname is a permitted replacement for the hostname * and perform the replacement if it is. * NB. this function must operate with a options having undefined members. */ static int check_follow_cname(int direct, char **namep, const char *cname) { int i; struct allowed_cname *rule; if (*cname == '\0' || !config_has_permitted_cnames(&options) || strcmp(*namep, cname) == 0) return 0; if (options.canonicalize_hostname == SSH_CANONICALISE_NO) return 0; /* * Don't attempt to canonicalize names that will be interpreted by * a proxy or jump host unless the user specifically requests so. */ if (!direct && options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) return 0; debug3_f("check \"%s\" CNAME \"%s\"", *namep, cname); for (i = 0; i < options.num_permitted_cnames; i++) { rule = options.permitted_cnames + i; if (match_pattern_list(*namep, rule->source_list, 1) != 1 || match_pattern_list(cname, rule->target_list, 1) != 1) continue; verbose("Canonicalized DNS aliased hostname " "\"%s\" => \"%s\"", *namep, cname); free(*namep); *namep = xstrdup(cname); return 1; } return 0; } /* * Attempt to resolve the supplied hostname after applying the user's * canonicalization rules. Returns the address list for the host or NULL * if no name was found after canonicalization. * NB. this function must operate with a options having undefined members. */ static struct addrinfo * resolve_canonicalize(char **hostp, int port) { int i, direct, ndots; char *cp, *fullhost, newname[NI_MAXHOST]; struct addrinfo *addrs; /* * Attempt to canonicalise addresses, regardless of * whether hostname canonicalisation was requested */ if ((addrs = resolve_addr(*hostp, port, newname, sizeof(newname))) != NULL) { debug2_f("hostname %.100s is address", *hostp); if (strcasecmp(*hostp, newname) != 0) { debug2_f("canonicalised address \"%s\" => \"%s\"", *hostp, newname); free(*hostp); *hostp = xstrdup(newname); } return addrs; } /* * If this looks like an address but didn't parse as one, it might * be an address with an invalid interface scope. Skip further * attempts at canonicalisation. */ if (is_addr_fast(*hostp)) { debug_f("hostname %.100s is an unrecognised address", *hostp); return NULL; } if (options.canonicalize_hostname == SSH_CANONICALISE_NO) return NULL; /* * Don't attempt to canonicalize names that will be interpreted by * a proxy unless the user specifically requests so. */ direct = option_clear_or_none(options.proxy_command) && option_clear_or_none(options.jump_host); if (!direct && options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) return NULL; /* If domain name is anchored, then resolve it now */ if ((*hostp)[strlen(*hostp) - 1] == '.') { debug3_f("name is fully qualified"); fullhost = xstrdup(*hostp); if ((addrs = resolve_host(fullhost, port, 0, newname, sizeof(newname))) != NULL) goto found; free(fullhost); goto notfound; } /* Don't apply canonicalization to sufficiently-qualified hostnames */ ndots = 0; for (cp = *hostp; *cp != '\0'; cp++) { if (*cp == '.') ndots++; } if (ndots > options.canonicalize_max_dots) { debug3_f("not canonicalizing hostname \"%s\" (max dots %d)", *hostp, options.canonicalize_max_dots); return NULL; } /* Attempt each supplied suffix */ for (i = 0; i < options.num_canonical_domains; i++) { if (strcasecmp(options.canonical_domains[i], "none") == 0) break; xasprintf(&fullhost, "%s.%s.", *hostp, options.canonical_domains[i]); debug3_f("attempting \"%s\" => \"%s\"", *hostp, fullhost); if ((addrs = resolve_host(fullhost, port, 0, newname, sizeof(newname))) == NULL) { free(fullhost); continue; } found: /* Remove trailing '.' */ fullhost[strlen(fullhost) - 1] = '\0'; /* Follow CNAME if requested */ if (!check_follow_cname(direct, &fullhost, newname)) { debug("Canonicalized hostname \"%s\" => \"%s\"", *hostp, fullhost); } free(*hostp); *hostp = fullhost; return addrs; } notfound: if (!options.canonicalize_fallback_local) fatal("%s: Could not resolve host \"%s\"", __progname, *hostp); debug2_f("host %s not found in any suffix", *hostp); return NULL; } /* * Check the result of hostkey loading, ignoring some errors and either * discarding the key or fatal()ing for others. */ static void check_load(int r, struct sshkey **k, const char *path, const char *message) { switch (r) { case 0: /* Check RSA keys size and discard if undersized */ if (k != NULL && *k != NULL && (r = sshkey_check_rsa_length(*k, options.required_rsa_size)) != 0) { error_r(r, "load %s \"%s\"", message, path); free(*k); *k = NULL; } break; case SSH_ERR_INTERNAL_ERROR: case SSH_ERR_ALLOC_FAIL: fatal_r(r, "load %s \"%s\"", message, path); case SSH_ERR_SYSTEM_ERROR: /* Ignore missing files */ if (errno == ENOENT) break; /* FALLTHROUGH */ default: error_r(r, "load %s \"%s\"", message, path); break; } } /* * Read per-user configuration file. Ignore the system wide config * file if the user specifies a config file on the command line. */ static void process_config_files(const char *host_name, struct passwd *pw, int final_pass, int *want_final_pass) { char *cmd, buf[PATH_MAX]; int r; if ((cmd = sshbuf_dup_string(command)) == NULL) fatal_f("sshbuf_dup_string failed"); if (config != NULL) { if (strcasecmp(config, "none") != 0 && !read_config_file(config, pw, host, host_name, cmd, &options, SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0), want_final_pass)) fatal("Can't open user config file %.100s: " "%.100s", config, strerror(errno)); } else { r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); if (r > 0 && (size_t)r < sizeof(buf)) (void)read_config_file(buf, pw, host, host_name, cmd, &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0), want_final_pass); /* Read systemwide configuration file after user config. */ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host, host_name, cmd, &options, final_pass ? SSHCONF_FINAL : 0, want_final_pass); } free(cmd); } /* Rewrite the port number in an addrinfo list of addresses */ static void set_addrinfo_port(struct addrinfo *addrs, int port) { struct addrinfo *addr; for (addr = addrs; addr != NULL; addr = addr->ai_next) { switch (addr->ai_family) { case AF_INET: ((struct sockaddr_in *)addr->ai_addr)-> sin_port = htons(port); break; case AF_INET6: ((struct sockaddr_in6 *)addr->ai_addr)-> sin6_port = htons(port); break; } } } static void ssh_conn_info_free(struct ssh_conn_info *cinfo) { if (cinfo == NULL) return; free(cinfo->conn_hash_hex); free(cinfo->shorthost); free(cinfo->uidstr); free(cinfo->keyalias); free(cinfo->thishost); free(cinfo->host_arg); free(cinfo->portstr); free(cinfo->remhost); free(cinfo->remuser); free(cinfo->homedir); free(cinfo->locuser); free(cinfo->jmphost); free(cinfo); } static int valid_hostname(const char *s) { size_t i; if (*s == '-') return 0; for (i = 0; s[i] != 0; i++) { if (strchr("'`\"$\\;&<>|(){},", s[i]) != NULL || isspace((u_char)s[i]) || iscntrl((u_char)s[i])) return 0; } return 1; } static int valid_ruser(const char *s) { size_t i; if (*s == '-') return 0; for (i = 0; s[i] != 0; i++) { if (strchr("'`\";&<>|(){}", s[i]) != NULL) return 0; /* Disallow '-' after whitespace */ if (isspace((u_char)s[i]) && s[i + 1] == '-') return 0; /* Disallow \ in last position */ if (s[i] == '\\' && s[i + 1] == '\0') return 0; } return 1; } /* * Main program for the ssh client. */ int main(int ac, char **av) { struct ssh *ssh = NULL; int i, r, opt, exit_status, use_syslog, direct, timeout_ms; int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; char *p, *cp, *line, *argv0, *logfile, *args; char cname[NI_MAXHOST], thishost[NI_MAXHOST]; struct stat st; struct passwd *pw; extern int optind, optreset; extern char *optarg; struct Forward fwd; struct addrinfo *addrs = NULL; size_t n, len; u_int j; struct utsname utsname; struct ssh_conn_info *cinfo = NULL; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* * Discard other fds that are hanging around. These can cause problem * with backgrounded ssh processes started by ControlPersist. */ closefrom(STDERR_FILENO + 1); __progname = ssh_get_progname(av[0]); #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ /* Save argv so it isn't clobbered by setproctitle() emulation */ saved_av = xcalloc(ac + 1, sizeof(*saved_av)); for (i = 0; i < ac; i++) saved_av[i] = xstrdup(av[i]); saved_av[i] = NULL; compat_init_setproctitle(ac, av); av = saved_av; #endif seed_rng(); /* Get user data. */ pw = getpwuid(getuid()); if (!pw) { logit("No user exists for uid %lu", (u_long)getuid()); exit(255); } /* Take a copy of the returned structure. */ pw = pwcopy(pw); /* * Set our umask to something reasonable, as some files are created * with the default umask. This will make them world-readable but * writable only by the owner, which is ok for all files for which we * don't set the modes explicitly. */ umask(022 | umask(077)); msetlocale(); /* * Initialize option structure to indicate that no values have been * set. */ initialize_options(&options); /* * Prepare main ssh transport/connection structures */ if ((ssh = ssh_alloc_session_state()) == NULL) fatal("Couldn't allocate session state"); channel_init_channels(ssh); /* Parse command-line arguments. */ args = argv_assemble(ac, av); /* logged later */ host = NULL; use_syslog = 0; logfile = NULL; argv0 = av[0]; again: while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" "AB:CD:E:F:GI:J:KL:MNO:P:Q:R:S:TVw:W:XYy")) != -1) { /* HUZdhjruz */ switch (opt) { case '1': fatal("SSH protocol v.1 is no longer supported"); break; case '2': /* Ignored */ break; case '4': options.address_family = AF_INET; break; case '6': options.address_family = AF_INET6; break; case 'n': options.stdin_null = 1; break; case 'f': options.fork_after_authentication = 1; options.stdin_null = 1; break; case 'x': options.forward_x11 = 0; break; case 'X': options.forward_x11 = 1; break; case 'y': use_syslog = 1; break; case 'E': logfile = optarg; break; case 'G': config_test = 1; break; case 'Y': options.forward_x11 = 1; options.forward_x11_trusted = 1; break; case 'g': options.fwd_opts.gateway_ports = 1; break; case 'O': if (options.stdio_forward_host != NULL) fatal("Cannot specify multiplexing " "command with -W"); else if (muxclient_command != 0) fatal("Multiplexing command already specified"); if (strcmp(optarg, "check") == 0) muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK; else if (strcmp(optarg, "forward") == 0) muxclient_command = SSHMUX_COMMAND_FORWARD; else if (strcmp(optarg, "exit") == 0) muxclient_command = SSHMUX_COMMAND_TERMINATE; else if (strcmp(optarg, "stop") == 0) muxclient_command = SSHMUX_COMMAND_STOP; else if (strcmp(optarg, "cancel") == 0) muxclient_command = SSHMUX_COMMAND_CANCEL_FWD; else if (strcmp(optarg, "proxy") == 0) muxclient_command = SSHMUX_COMMAND_PROXY; else fatal("Invalid multiplex command."); break; case 'P': if (options.tag == NULL) options.tag = xstrdup(optarg); break; case 'Q': cp = NULL; if (strcmp(optarg, "cipher") == 0 || strcasecmp(optarg, "Ciphers") == 0) cp = cipher_alg_list('\n', 0); else if (strcmp(optarg, "cipher-auth") == 0) cp = cipher_alg_list('\n', 1); else if (strcmp(optarg, "mac") == 0 || strcasecmp(optarg, "MACs") == 0) cp = mac_alg_list('\n'); else if (strcmp(optarg, "kex") == 0 || strcasecmp(optarg, "KexAlgorithms") == 0) cp = kex_alg_list('\n'); else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); else if (strcmp(optarg, "key-cert") == 0) cp = sshkey_alg_list(1, 0, 0, '\n'); else if (strcmp(optarg, "key-plain") == 0) cp = sshkey_alg_list(0, 1, 0, '\n'); else if (strcmp(optarg, "key-ca-sign") == 0 || strcasecmp(optarg, "CASignatureAlgorithms") == 0) cp = sshkey_alg_list(0, 1, 1, '\n'); else if (strcmp(optarg, "key-sig") == 0 || strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 || /* deprecated name */ strcasecmp(optarg, "PubkeyAcceptedAlgorithms") == 0 || strcasecmp(optarg, "HostKeyAlgorithms") == 0 || strcasecmp(optarg, "HostbasedKeyTypes") == 0 || /* deprecated name */ strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0 || /* deprecated name */ strcasecmp(optarg, "HostbasedAcceptedAlgorithms") == 0) cp = sshkey_alg_list(0, 0, 1, '\n'); else if (strcmp(optarg, "sig") == 0) cp = sshkey_alg_list(0, 1, 1, '\n'); else if (strcmp(optarg, "protocol-version") == 0) cp = xstrdup("2"); else if (strcmp(optarg, "compression") == 0) { cp = xstrdup(compression_alg_list(0)); len = strlen(cp); for (n = 0; n < len; n++) if (cp[n] == ',') cp[n] = '\n'; } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( "cipher\ncipher-auth\ncompression\nkex\n" "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" "protocol-version\nsig"); } if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); printf("%s\n", cp); free(cp); exit(0); break; case 'a': options.forward_agent = 0; break; case 'A': options.forward_agent = 1; break; case 'k': options.gss_deleg_creds = 0; break; case 'K': options.gss_authentication = 1; options.gss_deleg_creds = 1; break; case 'i': p = tilde_expand_filename(optarg, getuid()); if (stat(p, &st) == -1) fprintf(stderr, "Warning: Identity file %s " "not accessible: %s.\n", p, strerror(errno)); else add_identity_file(&options, NULL, p, 1); free(p); break; case 'I': #ifdef ENABLE_PKCS11 free(options.pkcs11_provider); options.pkcs11_provider = xstrdup(optarg); #else fprintf(stderr, "no support for PKCS#11.\n"); #endif break; case 'J': if (options.jump_host != NULL) { fatal("Only a single -J option is permitted " "(use commas to separate multiple " "jump hops)"); } if (options.proxy_command != NULL) fatal("Cannot specify -J with ProxyCommand"); if (parse_jump(optarg, &options, 1) == -1) fatal("Invalid -J argument"); options.proxy_command = xstrdup("none"); break; case 't': if (options.request_tty == REQUEST_TTY_YES) options.request_tty = REQUEST_TTY_FORCE; else options.request_tty = REQUEST_TTY_YES; break; case 'v': if (debug_flag == 0) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else { if (options.log_level < SYSLOG_LEVEL_DEBUG3) { debug_flag++; options.log_level++; } } break; case 'V': fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); exit(0); break; case 'w': if (options.tun_open == -1) options.tun_open = SSH_TUNMODE_DEFAULT; options.tun_local = a2tun(optarg, &options.tun_remote); if (options.tun_local == SSH_TUNID_ERR) { fprintf(stderr, "Bad tun device '%s'\n", optarg); exit(255); } break; case 'W': if (options.stdio_forward_host != NULL) fatal("stdio forward already specified"); if (muxclient_command != 0) fatal("Cannot specify stdio forward with -O"); if (parse_forward(&fwd, optarg, 1, 0)) { options.stdio_forward_host = fwd.listen_port == PORT_STREAMLOCAL ? fwd.listen_path : fwd.listen_host; options.stdio_forward_port = fwd.listen_port; free(fwd.connect_host); } else { fprintf(stderr, "Bad stdio forwarding specification '%s'\n", optarg); exit(255); } options.request_tty = REQUEST_TTY_NO; options.session_type = SESSION_TYPE_NONE; break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'e': if (strlen(optarg) == 2 && optarg[0] == '^' && (u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128) options.escape_char = (u_char) optarg[1] & 31; else if (strlen(optarg) == 1) options.escape_char = (u_char) optarg[0]; else if (strcmp(optarg, "none") == 0) options.escape_char = SSH_ESCAPECHAR_NONE; else { fprintf(stderr, "Bad escape character '%s'.\n", optarg); exit(255); } break; case 'c': if (!ciphers_valid(*optarg == '+' || *optarg == '^' ? optarg + 1 : optarg)) { fprintf(stderr, "Unknown cipher type '%s'\n", optarg); exit(255); } free(options.ciphers); options.ciphers = xstrdup(optarg); break; case 'm': if (mac_valid(optarg)) { free(options.macs); options.macs = xstrdup(optarg); } else { fprintf(stderr, "Unknown mac type '%s'\n", optarg); exit(255); } break; case 'M': if (options.control_master == SSHCTL_MASTER_YES) options.control_master = SSHCTL_MASTER_ASK; else options.control_master = SSHCTL_MASTER_YES; break; case 'p': if (options.port == -1) { options.port = a2port(optarg); if (options.port <= 0) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(255); } } break; case 'l': if (options.user == NULL) options.user = xstrdup(optarg); break; case 'L': if (parse_forward(&fwd, optarg, 0, 0)) add_local_forward(&options, &fwd); else { fprintf(stderr, "Bad local forwarding specification '%s'\n", optarg); exit(255); } break; case 'R': if (parse_forward(&fwd, optarg, 0, 1) || parse_forward(&fwd, optarg, 1, 1)) { add_remote_forward(&options, &fwd); } else { fprintf(stderr, "Bad remote forwarding specification " "'%s'\n", optarg); exit(255); } break; case 'D': if (parse_forward(&fwd, optarg, 1, 0)) { add_local_forward(&options, &fwd); } else { fprintf(stderr, "Bad dynamic forwarding specification " "'%s'\n", optarg); exit(255); } break; case 'C': #ifdef WITH_ZLIB options.compression = 1; #else error("Compression not supported, disabling."); #endif break; case 'N': if (options.session_type != -1 && options.session_type != SESSION_TYPE_NONE) fatal("Cannot specify -N with -s/SessionType"); options.session_type = SESSION_TYPE_NONE; options.request_tty = REQUEST_TTY_NO; break; case 'T': options.request_tty = REQUEST_TTY_NO; break; case 'o': line = xstrdup(optarg); if (process_config_line(&options, pw, host ? host : "", host ? host : "", "", line, "command-line", 0, NULL, SSHCONF_USERCONF) != 0) exit(255); free(line); break; case 's': if (options.session_type != -1 && options.session_type != SESSION_TYPE_SUBSYSTEM) fatal("Cannot specify -s with -N/SessionType"); options.session_type = SESSION_TYPE_SUBSYSTEM; break; case 'S': free(options.control_path); options.control_path = xstrdup(optarg); break; case 'b': options.bind_address = optarg; break; case 'B': options.bind_interface = optarg; break; case 'F': config = optarg; break; default: usage(); } } if (optind > 1 && strcmp(av[optind - 1], "--") == 0) opt_terminated = 1; ac -= optind; av += optind; if (ac > 0 && !host) { int tport; char *tuser; switch (parse_ssh_uri(*av, &tuser, &host, &tport)) { case -1: usage(); break; case 0: if (options.user == NULL) { options.user = tuser; tuser = NULL; } free(tuser); if (options.port == -1 && tport != -1) options.port = tport; break; default: p = xstrdup(*av); cp = strrchr(p, '@'); if (cp != NULL) { if (cp == p) usage(); if (options.user == NULL) { options.user = p; p = NULL; } *cp++ = '\0'; host = xstrdup(cp); free(p); } else host = p; break; } if (ac > 1 && !opt_terminated) { optind = optreset = 1; goto again; } ac--, av++; } /* Check that we got a host name. */ if (!host) usage(); if (!valid_hostname(host)) fatal("hostname contains invalid characters"); options.host_arg = xstrdup(host); /* Initialize the command to execute on remote host. */ if ((command = sshbuf_new()) == NULL) fatal("sshbuf_new failed"); /* * Save the command to execute on the remote host in a buffer. There * is no limit on the length of the command, except by the maximum * packet size. Also sets the tty flag if there is no command. */ if (!ac) { /* No command specified - execute shell on a tty. */ if (options.session_type == SESSION_TYPE_SUBSYSTEM) { fprintf(stderr, "You must specify a subsystem to invoke.\n"); usage(); } } else { /* A command has been specified. Store it into the buffer. */ for (i = 0; i < ac; i++) { if ((r = sshbuf_putf(command, "%s%s", i ? " " : "", av[i])) != 0) fatal_fr(r, "buffer error"); } } ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ /* * Initialize "log" output. Since we are the client all output * goes to stderr unless otherwise specified by -y or -E. */ if (use_syslog && logfile != NULL) fatal("Can't specify both -y and -E"); if (logfile != NULL) log_redirect_stderr_to(logfile); log_init(argv0, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_USER : options.log_facility, !use_syslog); debug("%s, %s", SSH_RELEASE, SSH_OPENSSL_VERSION); if (uname(&utsname) != 0) { memset(&utsname, 0, sizeof(utsname)); strlcpy(utsname.sysname, "UNKNOWN", sizeof(utsname.sysname)); } debug3("Running on %s %s %s %s", utsname.sysname, utsname.release, utsname.version, utsname.machine); debug3("Started with: %s", args); free(args); /* Parse the configuration files */ process_config_files(options.host_arg, pw, 0, &want_final_pass); if (want_final_pass) debug("configuration requests final Match pass"); /* Hostname canonicalisation needs a few options filled. */ fill_default_options_for_canonicalization(&options); /* If the user has replaced the hostname then take it into use now */ if (options.hostname != NULL) { /* NB. Please keep in sync with readconf.c:match_cfg_line() */ cp = percent_expand(options.hostname, "h", host, (char *)NULL); free(host); host = cp; free(options.hostname); options.hostname = xstrdup(host); } /* Don't lowercase addresses, they will be explicitly canonicalised */ if ((was_addr = is_addr(host)) == 0) lowercase(host); /* * Try to canonicalize if requested by configuration or the * hostname is an address. */ if (options.canonicalize_hostname != SSH_CANONICALISE_NO || was_addr) addrs = resolve_canonicalize(&host, options.port); /* * If CanonicalizePermittedCNAMEs have been specified but * other canonicalization did not happen (by not being requested * or by failing with fallback) then the hostname may still be changed * as a result of CNAME following. * * Try to resolve the bare hostname name using the system resolver's * usual search rules and then apply the CNAME follow rules. * * Skip the lookup if a ProxyCommand is being used unless the user * has specifically requested canonicalisation for this case via * CanonicalizeHostname=always */ direct = option_clear_or_none(options.proxy_command) && option_clear_or_none(options.jump_host); if (addrs == NULL && config_has_permitted_cnames(&options) && (direct || options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { if ((addrs = resolve_host(host, options.port, direct, cname, sizeof(cname))) == NULL) { /* Don't fatal proxied host names not in the DNS */ if (direct) cleanup_exit(255); /* logged in resolve_host */ } else check_follow_cname(direct, &host, cname); } /* * If canonicalisation is enabled then re-parse the configuration * files as new stanzas may match. */ if (options.canonicalize_hostname != 0 && !want_final_pass) { debug("hostname canonicalisation enabled, " "will re-parse configuration"); want_final_pass = 1; } if (want_final_pass) { debug("re-parsing configuration"); free(options.hostname); options.hostname = xstrdup(host); process_config_files(options.host_arg, pw, 1, NULL); /* * Address resolution happens early with canonicalisation * enabled and the port number may have changed since, so * reset it in address list */ if (addrs != NULL && options.port > 0) set_addrinfo_port(addrs, options.port); } /* Fill configuration defaults. */ if (fill_default_options(&options) != 0) cleanup_exit(255); if (options.user == NULL) options.user = xstrdup(pw->pw_name); /* * If ProxyJump option specified, then construct a ProxyCommand now. */ if (options.jump_host != NULL) { char port_s[8]; const char *jumpuser = options.jump_user, *sshbin = argv0; int port = options.port, jumpport = options.jump_port; if (port <= 0) port = default_ssh_port(); if (jumpport <= 0) jumpport = default_ssh_port(); if (jumpuser == NULL) jumpuser = options.user; if (strcmp(options.jump_host, host) == 0 && port == jumpport && strcmp(options.user, jumpuser) == 0) fatal("jumphost loop via %s", options.jump_host); /* * Try to use SSH indicated by argv[0], but fall back to * "ssh" if it appears unavailable. */ if (strchr(argv0, '/') != NULL && access(argv0, X_OK) != 0) sshbin = "ssh"; /* Consistency check */ if (options.proxy_command != NULL) fatal("inconsistent options: ProxyCommand+ProxyJump"); /* Never use FD passing for ProxyJump */ options.proxy_use_fdpass = 0; snprintf(port_s, sizeof(port_s), "%d", options.jump_port); xasprintf(&options.proxy_command, "%s%s%s%s%s%s%s%s%s%s%.*s -W '[%%h]:%%p' %s", sshbin, /* Optional "-l user" argument if jump_user set */ options.jump_user == NULL ? "" : " -l ", options.jump_user == NULL ? "" : options.jump_user, /* Optional "-p port" argument if jump_port set */ options.jump_port <= 0 ? "" : " -p ", options.jump_port <= 0 ? "" : port_s, /* Optional additional jump hosts ",..." */ options.jump_extra == NULL ? "" : " -J ", options.jump_extra == NULL ? "" : options.jump_extra, /* Optional "-F" argument if -F specified */ config == NULL ? "" : " -F ", config == NULL ? "" : config, /* Optional "-v" arguments if -v set */ debug_flag ? " -" : "", debug_flag, "vvv", /* Mandatory hostname */ options.jump_host); debug("Setting implicit ProxyCommand from ProxyJump: %s", options.proxy_command); } if (options.port == 0) options.port = default_ssh_port(); channel_set_af(ssh, options.address_family); /* Tidy and check options */ if (options.host_key_alias != NULL) lowercase(options.host_key_alias); if (options.proxy_command != NULL && strcmp(options.proxy_command, "-") == 0 && options.proxy_use_fdpass) fatal("ProxyCommand=- and ProxyUseFDPass are incompatible"); if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { if (options.control_persist && options.control_path != NULL) { debug("UpdateHostKeys=ask is incompatible with " "ControlPersist; disabling"); options.update_hostkeys = 0; } else if (sshbuf_len(command) != 0 || options.remote_command != NULL || options.request_tty == REQUEST_TTY_NO) { debug("UpdateHostKeys=ask is incompatible with " "remote command execution; disabling"); options.update_hostkeys = 0; } else if (options.log_level < SYSLOG_LEVEL_INFO) { /* no point logging anything; user won't see it */ options.update_hostkeys = 0; } } if (options.connection_attempts <= 0) fatal("Invalid number of ConnectionAttempts"); if (sshbuf_len(command) != 0 && options.remote_command != NULL) fatal("Cannot execute command-line and remote command."); /* Cannot fork to background if no command. */ if (options.fork_after_authentication && sshbuf_len(command) == 0 && options.remote_command == NULL && options.session_type != SESSION_TYPE_NONE) fatal("Cannot fork into background without a command " "to execute."); /* reinit */ log_init(argv0, options.log_level, options.log_facility, !use_syslog); for (j = 0; j < options.num_log_verbose; j++) { if (strcasecmp(options.log_verbose[j], "none") == 0) break; log_verbose_add(options.log_verbose[j]); } if (options.request_tty == REQUEST_TTY_YES || options.request_tty == REQUEST_TTY_FORCE) tty_flag = 1; /* Allocate a tty by default if no command specified. */ if (sshbuf_len(command) == 0 && options.remote_command == NULL) tty_flag = options.request_tty != REQUEST_TTY_NO; /* Force no tty */ if (options.request_tty == REQUEST_TTY_NO || (muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY) || options.session_type == SESSION_TYPE_NONE) tty_flag = 0; /* Do not allocate a tty if stdin is not a tty. */ if ((!isatty(fileno(stdin)) || options.stdin_null) && options.request_tty != REQUEST_TTY_FORCE) { if (tty_flag) logit("Pseudo-terminal will not be allocated because " "stdin is not a terminal."); tty_flag = 0; } /* Set up strings used to percent_expand() arguments */ cinfo = xcalloc(1, sizeof(*cinfo)); if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); cinfo->thishost = xstrdup(thishost); thishost[strcspn(thishost, ".")] = '\0'; cinfo->shorthost = xstrdup(thishost); xasprintf(&cinfo->portstr, "%d", options.port); xasprintf(&cinfo->uidstr, "%llu", (unsigned long long)pw->pw_uid); cinfo->keyalias = xstrdup(options.host_key_alias ? options.host_key_alias : options.host_arg); cinfo->host_arg = xstrdup(options.host_arg); cinfo->remhost = xstrdup(host); cinfo->homedir = xstrdup(pw->pw_dir); cinfo->locuser = xstrdup(pw->pw_name); cinfo->jmphost = xstrdup(options.jump_host == NULL ? "" : options.jump_host); /* * Expand User. It cannot contain %r (itself) or %C since User is * a component of the hash. */ if (options.user != NULL) { if ((p = percent_dollar_expand(options.user, DEFAULT_CLIENT_PERCENT_EXPAND_ARGS_NOUSER(cinfo), (char *)NULL)) == NULL) fatal("invalid environment variable expansion"); free(options.user); options.user = p; if (!valid_ruser(options.user)) fatal("remote username contains invalid characters"); } /* Now User is expanded, store it and calculate hash. */ cinfo->remuser = xstrdup(options.user); cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, cinfo->remhost, cinfo->portstr, cinfo->remuser, cinfo->jmphost); /* * Expand tokens in arguments. NB. LocalCommand is expanded later, * after port-forwarding is set up, so it may pick up any local * tunnel interface name allocated. */ if (options.remote_command != NULL) { debug3("expanding RemoteCommand: %s", options.remote_command); cp = options.remote_command; options.remote_command = default_client_percent_expand(cp, cinfo); debug3("expanded RemoteCommand: %s", options.remote_command); free(cp); if ((r = sshbuf_put(command, options.remote_command, strlen(options.remote_command))) != 0) fatal_fr(r, "buffer error"); } if (options.control_path != NULL) { cp = tilde_expand_filename(options.control_path, getuid()); free(options.control_path); options.control_path = default_client_percent_dollar_expand(cp, cinfo); free(cp); } if (options.identity_agent != NULL) { p = tilde_expand_filename(options.identity_agent, getuid()); cp = default_client_percent_dollar_expand(p, cinfo); free(p); free(options.identity_agent); options.identity_agent = cp; } if (options.revoked_host_keys != NULL) { p = tilde_expand_filename(options.revoked_host_keys, getuid()); cp = default_client_percent_dollar_expand(p, cinfo); free(p); free(options.revoked_host_keys); options.revoked_host_keys = cp; } if (options.forward_agent_sock_path != NULL) { p = tilde_expand_filename(options.forward_agent_sock_path, getuid()); cp = default_client_percent_dollar_expand(p, cinfo); free(p); free(options.forward_agent_sock_path); options.forward_agent_sock_path = cp; if (stat(options.forward_agent_sock_path, &st) != 0) { error("Cannot forward agent socket path \"%s\": %s", options.forward_agent_sock_path, strerror(errno)); if (options.exit_on_forward_failure) cleanup_exit(255); } } if (options.version_addendum != NULL) { cp = default_client_percent_dollar_expand( options.version_addendum, cinfo); free(options.version_addendum); options.version_addendum = cp; } if (options.num_system_hostfiles > 0 && strcasecmp(options.system_hostfiles[0], "none") == 0) { if (options.num_system_hostfiles > 1) fatal("Invalid GlobalKnownHostsFiles: \"none\" " "appears with other entries"); free(options.system_hostfiles[0]); options.system_hostfiles[0] = NULL; options.num_system_hostfiles = 0; } if (options.num_user_hostfiles > 0 && strcasecmp(options.user_hostfiles[0], "none") == 0) { if (options.num_user_hostfiles > 1) fatal("Invalid UserKnownHostsFiles: \"none\" " "appears with other entries"); free(options.user_hostfiles[0]); options.user_hostfiles[0] = NULL; options.num_user_hostfiles = 0; } for (j = 0; j < options.num_user_hostfiles; j++) { if (options.user_hostfiles[j] == NULL) continue; cp = tilde_expand_filename(options.user_hostfiles[j], getuid()); p = default_client_percent_dollar_expand(cp, cinfo); if (strcmp(options.user_hostfiles[j], p) != 0) debug3("expanded UserKnownHostsFile '%s' -> " "'%s'", options.user_hostfiles[j], p); free(options.user_hostfiles[j]); free(cp); options.user_hostfiles[j] = p; } for (j = 0; j < options.num_setenv; j++) { char *name = options.setenv[j], *value; if (name == NULL) continue; /* Expand only the value portion, not the variable name. */ if ((value = strchr(name, '=')) == NULL) { /* shouldn't happen; vars are checked in readconf.c */ fatal("Invalid config SetEnv: %s", name); } *value++ = '\0'; cp = default_client_percent_dollar_expand(value, cinfo); xasprintf(&p, "%s=%s", name, cp); if (strcmp(value, p) != 0) { debug3("expanded SetEnv '%s' '%s' -> '%s'", name, value, cp); } free(options.setenv[j]); free(cp); options.setenv[j] = p; } for (i = 0; i < options.num_local_forwards; i++) { if (options.local_forwards[i].listen_path != NULL) { cp = options.local_forwards[i].listen_path; p = options.local_forwards[i].listen_path = default_client_percent_expand(cp, cinfo); if (strcmp(cp, p) != 0) debug3("expanded LocalForward listen path " "'%s' -> '%s'", cp, p); free(cp); } if (options.local_forwards[i].connect_path != NULL) { cp = options.local_forwards[i].connect_path; p = options.local_forwards[i].connect_path = default_client_percent_expand(cp, cinfo); if (strcmp(cp, p) != 0) debug3("expanded LocalForward connect path " "'%s' -> '%s'", cp, p); free(cp); } } for (i = 0; i < options.num_remote_forwards; i++) { if (options.remote_forwards[i].listen_path != NULL) { cp = options.remote_forwards[i].listen_path; p = options.remote_forwards[i].listen_path = default_client_percent_expand(cp, cinfo); if (strcmp(cp, p) != 0) debug3("expanded RemoteForward listen path " "'%s' -> '%s'", cp, p); free(cp); } if (options.remote_forwards[i].connect_path != NULL) { cp = options.remote_forwards[i].connect_path; p = options.remote_forwards[i].connect_path = default_client_percent_expand(cp, cinfo); if (strcmp(cp, p) != 0) debug3("expanded RemoteForward connect path " "'%s' -> '%s'", cp, p); free(cp); } } if (config_test) { dump_client_config(&options, host); exit(0); } /* Expand SecurityKeyProvider if it refers to an environment variable */ if (options.sk_provider != NULL && *options.sk_provider == '$' && strlen(options.sk_provider) > 1) { if ((cp = getenv(options.sk_provider + 1)) == NULL) { debug("Authenticator provider %s did not resolve; " "disabling", options.sk_provider); free(options.sk_provider); options.sk_provider = NULL; } else { debug2("resolved SecurityKeyProvider %s => %s", options.sk_provider, cp); free(options.sk_provider); options.sk_provider = xstrdup(cp); } } if (muxclient_command != 0 && options.control_path == NULL) fatal("No ControlPath specified for \"-O\" command"); if (options.control_path != NULL) { int sock; if ((sock = muxclient(options.control_path)) >= 0) { ssh_packet_set_connection(ssh, sock, sock); ssh_packet_set_mux(ssh); goto skip_connect; } } /* * If hostname canonicalisation was not enabled, then we may not * have yet resolved the hostname. Do so now. */ if (addrs == NULL && options.proxy_command == NULL) { debug2("resolving \"%s\" port %d", host, options.port); if ((addrs = resolve_host(host, options.port, 1, cname, sizeof(cname))) == NULL) cleanup_exit(255); /* resolve_host logs the error */ } if (options.connection_timeout >= INT_MAX/1000) timeout_ms = INT_MAX; else timeout_ms = options.connection_timeout * 1000; /* Apply channels timeouts, if set */ channel_clear_timeouts(ssh); for (j = 0; j < options.num_channel_timeouts; j++) { debug3("applying channel timeout %s", options.channel_timeouts[j]); if (parse_pattern_interval(options.channel_timeouts[j], &cp, &i) != 0) { fatal_f("internal error: bad timeout %s", options.channel_timeouts[j]); } channel_add_timeout(ssh, cp, i); free(cp); } /* Open a connection to the remote host. */ if (ssh_connect(ssh, host, options.host_arg, addrs, &hostaddr, options.port, options.connection_attempts, &timeout_ms, options.tcp_keep_alive) != 0) exit(255); if (addrs != NULL) freeaddrinfo(addrs); ssh_packet_set_timeout(ssh, options.server_alive_interval, options.server_alive_count_max); if (timeout_ms > 0) debug3("timeout: %d ms remain after connect", timeout_ms); /* * If we successfully made the connection and we have hostbased auth * enabled, load the public keys so we can later use the ssh-keysign * helper to sign challenges. */ sensitive_data.nkeys = 0; sensitive_data.keys = NULL; if (options.hostbased_authentication) { int loaded = 0; sensitive_data.nkeys = 10; sensitive_data.keys = xcalloc(sensitive_data.nkeys, sizeof(*sensitive_data.keys)); /* XXX check errors? */ #define L_PUBKEY(p,o) do { \ if ((o) >= sensitive_data.nkeys) \ fatal_f("pubkey out of array bounds"); \ check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \ &(sensitive_data.keys[o]), p, "pubkey"); \ if (sensitive_data.keys[o] != NULL) { \ debug2("hostbased key %d: %s key from \"%s\"", o, \ sshkey_ssh_name(sensitive_data.keys[o]), p); \ loaded++; \ } \ } while (0) #define L_CERT(p,o) do { \ if ((o) >= sensitive_data.nkeys) \ fatal_f("cert out of array bounds"); \ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \ &(sensitive_data.keys[o]), p, "cert"); \ if (sensitive_data.keys[o] != NULL) { \ debug2("hostbased key %d: %s cert from \"%s\"", o, \ sshkey_ssh_name(sensitive_data.keys[o]), p); \ loaded++; \ } \ } while (0) if (options.hostbased_authentication == 1) { L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 0); L_CERT(_PATH_HOST_ED25519_KEY_FILE, 1); L_CERT(_PATH_HOST_RSA_KEY_FILE, 2); #ifdef WITH_DSA L_CERT(_PATH_HOST_DSA_KEY_FILE, 3); #endif L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4); L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5); L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6); #ifdef WITH_DSA L_PUBKEY(_PATH_HOST_DSA_KEY_FILE, 7); #endif L_CERT(_PATH_HOST_XMSS_KEY_FILE, 8); L_PUBKEY(_PATH_HOST_XMSS_KEY_FILE, 9); if (loaded == 0) debug("HostbasedAuthentication enabled but no " "local public host keys could be loaded."); } } /* load options.identity_files */ load_public_identity_files(cinfo); /* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */ if (options.identity_agent && strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0) { if (strcmp(options.identity_agent, "none") == 0) { unsetenv(SSH_AUTHSOCKET_ENV_NAME); } else { cp = options.identity_agent; /* legacy (limited) format */ if (cp[0] == '$' && cp[1] != '{') { if (!valid_env_name(cp + 1)) { fatal("Invalid IdentityAgent " "environment variable name %s", cp); } if ((p = getenv(cp + 1)) == NULL) unsetenv(SSH_AUTHSOCKET_ENV_NAME); else setenv(SSH_AUTHSOCKET_ENV_NAME, p, 1); } else { /* identity_agent specifies a path directly */ setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); } } } if (options.forward_agent && options.forward_agent_sock_path != NULL) { cp = options.forward_agent_sock_path; if (cp[0] == '$') { if (!valid_env_name(cp + 1)) { fatal("Invalid ForwardAgent environment variable name %s", cp); } if ((p = getenv(cp + 1)) != NULL) forward_agent_sock_path = xstrdup(p); else options.forward_agent = 0; free(cp); } else { forward_agent_sock_path = cp; } } /* Expand ~ in known host file names. */ tilde_expand_paths(options.system_hostfiles, options.num_system_hostfiles); tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); ssh_signal(SIGCHLD, main_sigchld_handler); /* Log into the remote system. Never returns if the login fails. */ ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr, options.port, pw, timeout_ms, cinfo); /* We no longer need the private host keys. Clear them now. */ if (sensitive_data.nkeys != 0) { for (i = 0; i < sensitive_data.nkeys; i++) { if (sensitive_data.keys[i] != NULL) { /* Destroys contents safely */ debug3("clear hostkey %d", i); sshkey_free(sensitive_data.keys[i]); sensitive_data.keys[i] = NULL; } } free(sensitive_data.keys); } for (i = 0; i < options.num_identity_files; i++) { free(options.identity_files[i]); options.identity_files[i] = NULL; if (options.identity_keys[i]) { sshkey_free(options.identity_keys[i]); options.identity_keys[i] = NULL; } } for (i = 0; i < options.num_certificate_files; i++) { free(options.certificate_files[i]); options.certificate_files[i] = NULL; } #ifdef ENABLE_PKCS11 (void)pkcs11_del_provider(options.pkcs11_provider); #endif skip_connect: exit_status = ssh_session2(ssh, cinfo); ssh_conn_info_free(cinfo); ssh_packet_close(ssh); if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); /* Kill ProxyCommand if it is running. */ ssh_kill_proxy_command(); return exit_status; } static void control_persist_detach(void) { pid_t pid; debug_f("backgrounding master process"); /* * master (current process) into the background, and make the * foreground process a client of the backgrounded master. */ switch ((pid = fork())) { case -1: fatal_f("fork: %s", strerror(errno)); case 0: /* Child: master process continues mainloop */ break; default: /* * Parent: set up mux client to connect to backgrounded * master. */ debug2_f("background process is %ld", (long)pid); options.stdin_null = ostdin_null_flag; options.request_tty = orequest_tty; tty_flag = otty_flag; options.fork_after_authentication = ofork_after_authentication; options.session_type = osession_type; close(muxserver_sock); muxserver_sock = -1; options.control_master = SSHCTL_MASTER_NO; (void)muxclient(options.control_path); /* muxclient() doesn't return on success. */ fatal("Failed to connect to new control master"); } if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) error_f("stdfd_devnull failed"); daemon(1, 1); setproctitle("%s [mux]", options.control_path); } /* Do fork() after authentication. Used by "ssh -f" */ static void fork_postauth(void) { if (need_controlpersist_detach) control_persist_detach(); debug("forking to background"); options.fork_after_authentication = 0; if (daemon(1, 1) == -1) fatal("daemon() failed: %.200s", strerror(errno)); if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) error_f("stdfd_devnull failed"); } static void forwarding_success(void) { if (forward_confirms_pending == -1) return; if (--forward_confirms_pending == 0) { debug_f("all expected forwarding replies received"); if (options.fork_after_authentication) fork_postauth(); } else { debug2_f("%d expected forwarding replies remaining", forward_confirms_pending); } } /* Callback for remote forward global requests */ static void ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) { struct Forward *rfwd = (struct Forward *)ctxt; u_int port; int r; /* XXX verbose() on failure? */ debug("remote forward %s for: listen %s%s%d, connect %s:%d", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", rfwd->listen_path ? rfwd->listen_path : rfwd->listen_host ? rfwd->listen_host : "", (rfwd->listen_path || rfwd->listen_host) ? ":" : "", rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : rfwd->connect_host, rfwd->connect_port); if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { if (type == SSH2_MSG_REQUEST_SUCCESS) { if ((r = sshpkt_get_u32(ssh, &port)) != 0) fatal_fr(r, "parse packet"); if (port > 65535) { error("Invalid allocated port %u for remote " "forward to %s:%d", port, rfwd->connect_host, rfwd->connect_port); /* Ensure failure processing runs below */ type = SSH2_MSG_REQUEST_FAILURE; channel_update_permission(ssh, rfwd->handle, -1); } else { rfwd->allocated_port = (int)port; logit("Allocated port %u for remote " "forward to %s:%d", rfwd->allocated_port, rfwd->connect_path ? rfwd->connect_path : rfwd->connect_host, rfwd->connect_port); channel_update_permission(ssh, rfwd->handle, rfwd->allocated_port); } } else { channel_update_permission(ssh, rfwd->handle, -1); } } if (type == SSH2_MSG_REQUEST_FAILURE) { if (options.exit_on_forward_failure) { if (rfwd->listen_path != NULL) fatal("Error: remote port forwarding failed " "for listen path %s", rfwd->listen_path); else fatal("Error: remote port forwarding failed " "for listen port %d", rfwd->listen_port); } else { if (rfwd->listen_path != NULL) logit("Warning: remote port forwarding failed " "for listen path %s", rfwd->listen_path); else logit("Warning: remote port forwarding failed " "for listen port %d", rfwd->listen_port); } } forwarding_success(); } static void client_cleanup_stdio_fwd(struct ssh *ssh, int id, int force, void *arg) { debug("stdio forwarding: done"); cleanup_exit(0); } static void ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) { if (!success) fatal("stdio forwarding failed"); } static void ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg) { if (!success) { error("Tunnel forwarding failed"); if (options.exit_on_forward_failure) cleanup_exit(255); } debug_f("tunnel forward established, id=%d", id); forwarding_success(); } static void ssh_init_stdio_forwarding(struct ssh *ssh) { Channel *c; int in, out; if (options.stdio_forward_host == NULL) return; debug3_f("%s:%d", options.stdio_forward_host, options.stdio_forward_port); if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) fatal_f("dup() in/out failed"); if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host, options.stdio_forward_port, in, out, CHANNEL_NONBLOCK_STDIO)) == NULL) fatal_f("channel_connect_stdio_fwd failed"); channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0); channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL); } static void ssh_init_forward_permissions(struct ssh *ssh, const char *what, char **opens, u_int num_opens) { u_int i; int port; char *addr, *arg, *oarg; int where = FORWARD_LOCAL; channel_clear_permission(ssh, FORWARD_ADM, where); if (num_opens == 0) return; /* permit any */ /* handle keywords: "any" / "none" */ if (num_opens == 1 && strcmp(opens[0], "any") == 0) return; if (num_opens == 1 && strcmp(opens[0], "none") == 0) { channel_disable_admin(ssh, where); return; } /* Otherwise treat it as a list of permitted host:port */ for (i = 0; i < num_opens; i++) { oarg = arg = xstrdup(opens[i]); addr = hpdelim(&arg); if (addr == NULL) fatal_f("missing host in %s", what); addr = cleanhostname(addr); if (arg == NULL || ((port = permitopen_port(arg)) < 0)) fatal_f("bad port number in %s", what); /* Send it to channels layer */ channel_add_permission(ssh, FORWARD_ADM, where, addr, port); free(oarg); } } static void ssh_init_forwarding(struct ssh *ssh, char **ifname) { int success = 0; int i; ssh_init_forward_permissions(ssh, "permitremoteopen", options.permitted_remote_opens, options.num_permitted_remote_opens); if (options.exit_on_forward_failure) forward_confirms_pending = 0; /* track pending requests */ /* Initiate local TCP/IP port forwardings. */ for (i = 0; i < options.num_local_forwards; i++) { debug("Local connections to %.200s:%d forwarded to remote " "address %.200s:%d", (options.local_forwards[i].listen_path != NULL) ? options.local_forwards[i].listen_path : (options.local_forwards[i].listen_host == NULL) ? (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : options.local_forwards[i].listen_host, options.local_forwards[i].listen_port, (options.local_forwards[i].connect_path != NULL) ? options.local_forwards[i].connect_path : options.local_forwards[i].connect_host, options.local_forwards[i].connect_port); success += channel_setup_local_fwd_listener(ssh, &options.local_forwards[i], &options.fwd_opts); } if (i > 0 && success != i && options.exit_on_forward_failure) fatal("Could not request local forwarding."); if (i > 0 && success == 0) error("Could not request local forwarding."); /* Initiate remote TCP/IP port forwardings. */ for (i = 0; i < options.num_remote_forwards; i++) { debug("Remote connections from %.200s:%d forwarded to " "local address %.200s:%d", (options.remote_forwards[i].listen_path != NULL) ? options.remote_forwards[i].listen_path : (options.remote_forwards[i].listen_host == NULL) ? "LOCALHOST" : options.remote_forwards[i].listen_host, options.remote_forwards[i].listen_port, (options.remote_forwards[i].connect_path != NULL) ? options.remote_forwards[i].connect_path : options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_port); if ((options.remote_forwards[i].handle = channel_request_remote_forwarding(ssh, &options.remote_forwards[i])) >= 0) { client_register_global_confirm( ssh_confirm_remote_forward, &options.remote_forwards[i]); forward_confirms_pending++; } else if (options.exit_on_forward_failure) fatal("Could not request remote forwarding."); else logit("Warning: Could not request remote forwarding."); } /* Initiate tunnel forwarding. */ if (options.tun_open != SSH_TUNMODE_NO) { if ((*ifname = client_request_tun_fwd(ssh, options.tun_open, options.tun_local, options.tun_remote, ssh_tun_confirm, NULL)) != NULL) forward_confirms_pending++; else if (options.exit_on_forward_failure) fatal("Could not request tunnel forwarding."); else error("Could not request tunnel forwarding."); } if (forward_confirms_pending > 0) { debug_f("expecting replies for %d forwards", forward_confirms_pending); } } static void check_agent_present(void) { int r; if (options.forward_agent) { /* Clear agent forwarding if we don't have an agent. */ if ((r = ssh_get_authentication_socket(NULL)) != 0) { options.forward_agent = 0; if (r != SSH_ERR_AGENT_NOT_PRESENT) debug_r(r, "ssh_get_authentication_socket"); } } } static void ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) { extern char **environ; const char *display, *term; int r, interactive = tty_flag; char *proto = NULL, *data = NULL; if (!success) return; /* No need for error message, channels code sends one */ display = getenv("DISPLAY"); if (display == NULL && options.forward_x11) debug("X11 forwarding requested but DISPLAY not set"); if (options.forward_x11 && client_x11_get_proto(ssh, display, options.xauth_location, options.forward_x11_trusted, options.forward_x11_timeout, &proto, &data) == 0) { /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); x11_request_forwarding_with_spoofing(ssh, id, display, proto, data, 1); client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); /* XXX exit_on_forward_failure */ interactive = 1; } check_agent_present(); if (options.forward_agent) { debug("Requesting authentication agent forwarding."); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); } /* Tell the packet module whether this is an interactive session. */ ssh_packet_set_interactive(ssh, interactive, options.ip_qos_interactive, options.ip_qos_bulk); if ((term = lookup_env_in_list("TERM", options.setenv, options.num_setenv)) == NULL || *term == '\0') term = getenv("TERM"); client_session2_setup(ssh, id, tty_flag, options.session_type == SESSION_TYPE_SUBSYSTEM, term, NULL, fileno(stdin), command, environ); } /* open new channel for a session */ static int ssh_session2_open(struct ssh *ssh) { Channel *c; int window, packetmax, in, out, err; if (options.stdin_null) { in = open(_PATH_DEVNULL, O_RDONLY); } else { in = dup(STDIN_FILENO); } out = dup(STDOUT_FILENO); err = dup(STDERR_FILENO); if (in == -1 || out == -1 || err == -1) fatal("dup() in/out/err failed"); window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { window >>= 1; packetmax >>= 1; } c = channel_new(ssh, "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO); debug3_f("channel_new: %d", c->self); channel_send_open(ssh, c->self); if (options.session_type != SESSION_TYPE_NONE) channel_register_open_confirm(ssh, c->self, ssh_session2_setup, NULL); return c->self; } static int ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) { int r, interactive, id = -1; char *cp, *tun_fwd_ifname = NULL; /* XXX should be pre-session */ if (!options.control_persist) ssh_init_stdio_forwarding(ssh); ssh_init_forwarding(ssh, &tun_fwd_ifname); if (options.local_command != NULL) { debug3("expanding LocalCommand: %s", options.local_command); cp = options.local_command; options.local_command = percent_expand(cp, DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, (char *)NULL); debug3("expanded LocalCommand: %s", options.local_command); free(cp); } /* Start listening for multiplex clients */ if (!ssh_packet_get_mux(ssh)) muxserver_listen(ssh); /* * If we are in control persist mode and have a working mux listen * socket, then prepare to background ourselves and have a foreground * client attach as a control client. * NB. we must save copies of the flags that we override for * the backgrounding, since we defer attachment of the client until * after the connection is fully established (in particular, * async rfwd replies have been received for ExitOnForwardFailure). */ if (options.control_persist && muxserver_sock != -1) { ostdin_null_flag = options.stdin_null; osession_type = options.session_type; orequest_tty = options.request_tty; otty_flag = tty_flag; ofork_after_authentication = options.fork_after_authentication; options.stdin_null = 1; options.session_type = SESSION_TYPE_NONE; tty_flag = 0; if ((osession_type != SESSION_TYPE_NONE || options.stdio_forward_host != NULL)) need_controlpersist_detach = 1; options.fork_after_authentication = 1; } /* * ControlPersist mux listen socket setup failed, attempt the * stdio forward setup that we skipped earlier. */ if (options.control_persist && muxserver_sock == -1) ssh_init_stdio_forwarding(ssh); if (options.session_type != SESSION_TYPE_NONE) id = ssh_session2_open(ssh); else { interactive = options.control_master == SSHCTL_MASTER_NO; /* ControlPersist may have clobbered ControlMaster, so check */ if (need_controlpersist_detach) interactive = otty_flag != 0; ssh_packet_set_interactive(ssh, interactive, options.ip_qos_interactive, options.ip_qos_bulk); } /* If we don't expect to open a new session, then disallow it */ if (options.control_master == SSHCTL_MASTER_NO && (ssh->compat & SSH_NEW_OPENSSH)) { debug("Requesting no-more-sessions@openssh.com"); if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "no-more-sessions@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); } /* Execute a local command */ if (options.local_command != NULL && options.permit_local_command) ssh_local_cmd(options.local_command); /* * stdout is now owned by the session channel; clobber it here * so future channel closes are propagated to the local fd. * NB. this can only happen after LocalCommand has completed, * as it may want to write to stdout. */ if (!need_controlpersist_detach && stdfd_devnull(0, 1, 0) == -1) error_f("stdfd_devnull failed"); /* * If requested and we are not interested in replies to remote * forwarding requests, then let ssh continue in the background. */ if (options.fork_after_authentication) { if (options.exit_on_forward_failure && options.num_remote_forwards > 0) { debug("deferring postauth fork until remote forward " "confirmation received"); } else fork_postauth(); } return client_loop(ssh, tty_flag, tty_flag ? options.escape_char : SSH_ESCAPECHAR_NONE, id); } /* Loads all IdentityFile and CertificateFile keys */ static void load_public_identity_files(const struct ssh_conn_info *cinfo) { char *filename, *cp; struct sshkey *public; int i; u_int n_ids, n_certs; char *identity_files[SSH_MAX_IDENTITY_FILES]; struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; int identity_file_userprovided[SSH_MAX_IDENTITY_FILES]; char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; #ifdef ENABLE_PKCS11 struct sshkey **keys = NULL; char **comments = NULL; int nkeys; #endif /* PKCS11 */ n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); memset(identity_keys, 0, sizeof(identity_keys)); memset(identity_file_userprovided, 0, sizeof(identity_file_userprovided)); memset(certificate_files, 0, sizeof(certificate_files)); memset(certificates, 0, sizeof(certificates)); memset(certificate_file_userprovided, 0, sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 if (options.pkcs11_provider != NULL && options.num_identity_files < SSH_MAX_IDENTITY_FILES && (pkcs11_init(!options.batch_mode) == 0) && (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, &keys, &comments)) > 0) { for (i = 0; i < nkeys; i++) { if (n_ids >= SSH_MAX_IDENTITY_FILES) { sshkey_free(keys[i]); free(comments[i]); continue; } identity_keys[n_ids] = keys[i]; identity_files[n_ids] = comments[i]; /* transferred */ n_ids++; } free(keys); free(comments); } #endif /* ENABLE_PKCS11 */ for (i = 0; i < options.num_identity_files; i++) { if (n_ids >= SSH_MAX_IDENTITY_FILES || strcasecmp(options.identity_files[i], "none") == 0) { free(options.identity_files[i]); options.identity_files[i] = NULL; continue; } cp = tilde_expand_filename(options.identity_files[i], getuid()); filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), &public, filename, "pubkey"); debug("identity file %s type %d", filename, public ? public->type : -1); free(options.identity_files[i]); identity_files[n_ids] = filename; identity_keys[n_ids] = public; identity_file_userprovided[n_ids] = options.identity_file_userprovided[i]; if (++n_ids >= SSH_MAX_IDENTITY_FILES) continue; /* * If no certificates have been explicitly listed then try * to add the default certificate variant too. */ if (options.num_certificate_files != 0) continue; xasprintf(&cp, "%s-cert", filename); check_load(sshkey_load_public(cp, &public, NULL), &public, filename, "pubkey"); debug("identity file %s type %d", cp, public ? public->type : -1); if (public == NULL) { free(cp); continue; } if (!sshkey_is_cert(public)) { debug_f("key %s type %s is not a certificate", cp, sshkey_type(public)); sshkey_free(public); free(cp); continue; } /* NB. leave filename pointing to private key */ identity_files[n_ids] = xstrdup(filename); identity_keys[n_ids] = public; identity_file_userprovided[n_ids] = options.identity_file_userprovided[i]; n_ids++; } if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES) fatal_f("too many certificates"); for (i = 0; i < options.num_certificate_files; i++) { cp = tilde_expand_filename(options.certificate_files[i], getuid()); filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), &public, filename, "certificate"); debug("certificate file %s type %d", filename, public ? public->type : -1); free(options.certificate_files[i]); options.certificate_files[i] = NULL; if (public == NULL) { free(filename); continue; } if (!sshkey_is_cert(public)) { debug_f("key %s type %s is not a certificate", filename, sshkey_type(public)); sshkey_free(public); free(filename); continue; } certificate_files[n_certs] = filename; certificates[n_certs] = public; certificate_file_userprovided[n_certs] = options.certificate_file_userprovided[i]; ++n_certs; } options.num_identity_files = n_ids; memcpy(options.identity_files, identity_files, sizeof(identity_files)); memcpy(options.identity_keys, identity_keys, sizeof(identity_keys)); memcpy(options.identity_file_userprovided, identity_file_userprovided, sizeof(identity_file_userprovided)); options.num_certificate_files = n_certs; memcpy(options.certificate_files, certificate_files, sizeof(certificate_files)); memcpy(options.certificates, certificates, sizeof(certificates)); memcpy(options.certificate_file_userprovided, certificate_file_userprovided, sizeof(certificate_file_userprovided)); } static void main_sigchld_handler(int sig) { int save_errno = errno; pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid == -1 && errno == EINTR)) ; errno = save_errno; } openssh-10.0p1/PaxHeaders.10889/ssh.h100644 001750 001750 0000000003614775415623 0014122xustar0030 atime=1744182234.856273586 openssh-10.0p1/ssh.h010064400017500001750000000047711477541562300125160ustar00djmdjm/* $OpenBSD: ssh.h,v 1.91 2024/09/25 23:01:39 jsg Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* Default port number. */ #define SSH_DEFAULT_PORT 22 /* * Maximum number of certificate files that can be specified * in configuration files or on the command line. */ #define SSH_MAX_CERTIFICATE_FILES 100 /* * Maximum number of RSA authentication identity files that can be specified * in configuration files or on the command line. */ #define SSH_MAX_IDENTITY_FILES 100 /* * Major protocol version. Different version indicates major incompatibility * that prevents communication. * * Minor protocol version. Different version indicates minor incompatibility * that does not prevent interoperation. * * We support only SSH2 */ #define PROTOCOL_MAJOR_2 2 #define PROTOCOL_MINOR_2 0 /* * Name for the service. The port named by this service overrides the * default port if present. */ #define SSH_SERVICE_NAME "ssh" /* * Name of the environment variable containing the process ID of the * authentication agent. */ #define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID" /* * Name of the environment variable containing the pathname of the * authentication socket. */ #define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK" /* * Environment variable for overwriting the default location of askpass */ #define SSH_ASKPASS_ENV "SSH_ASKPASS" /* * Environment variable to control whether or not askpass is used. */ #define SSH_ASKPASS_REQUIRE_ENV "SSH_ASKPASS_REQUIRE" /* * Length of the session key in bytes. (Specified as 256 bits in the * protocol.) */ #define SSH_SESSION_KEY_LENGTH 32 /* Used to identify ``EscapeChar none'' */ #define SSH_ESCAPECHAR_NONE -2 /* * unprivileged user when UsePrivilegeSeparation=yes; * sshd will change its privileges to this user and its * primary group. */ #ifndef SSH_PRIVSEP_USER #define SSH_PRIVSEP_USER "sshd" #endif /* 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 openssh-10.0p1/PaxHeaders.10889/ssh2.h100644 001750 001750 0000000003614775415623 0014204xustar0030 atime=1744182234.856273586 openssh-10.0p1/ssh2.h010064400017500001750000000135401477541562300125720ustar00djmdjm/* $OpenBSD: ssh2.h,v 1.22 2023/10/10 03:57:45 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * RFC4251: * * Transport layer protocol: * * 1-19 Transport layer generic (e.g. disconnect, ignore, debug, * etc) * 20-29 Algorithm negotiation * 30-49 Key exchange method specific (numbers can be reused for * different authentication methods) * * User authentication protocol: * * 50-59 User authentication generic * 60-79 User authentication method specific (numbers can be reused * for different authentication methods) * * Connection protocol: * * 80-89 Connection protocol generic * 90-127 Channel related messages * * Reserved for client protocols: * * 128-191 Reserved * * Local extensions: * * 192-255 Local extensions * 248-255 Local extensions (OpenSSH will never use numbers in this range) */ /* special marker for no message */ #define SSH_MSG_NONE 0 /* ranges */ #define SSH2_MSG_TRANSPORT_MIN 1 #define SSH2_MSG_TRANSPORT_MAX 49 #define SSH2_MSG_USERAUTH_MIN 50 #define SSH2_MSG_USERAUTH_MAX 79 #define SSH2_MSG_USERAUTH_PER_METHOD_MIN 60 #define SSH2_MSG_USERAUTH_PER_METHOD_MAX SSH2_MSG_USERAUTH_MAX #define SSH2_MSG_CONNECTION_MIN 80 #define SSH2_MSG_CONNECTION_MAX 127 #define SSH2_MSG_RESERVED_MIN 128 #define SSH2_MSG_RESERVED_MAX 191 #define SSH2_MSG_LOCAL_MIN 192 #define SSH2_MSG_LOCAL_MAX 255 #define SSH2_MSG_MIN 1 #define SSH2_MSG_MAX 255 /* transport layer: generic */ #define SSH2_MSG_DISCONNECT 1 #define SSH2_MSG_IGNORE 2 #define SSH2_MSG_UNIMPLEMENTED 3 #define SSH2_MSG_DEBUG 4 #define SSH2_MSG_SERVICE_REQUEST 5 #define SSH2_MSG_SERVICE_ACCEPT 6 #define SSH2_MSG_EXT_INFO 7 #define SSH2_MSG_NEWCOMPRESS 8 /* transport layer: alg negotiation */ #define SSH2_MSG_KEXINIT 20 #define SSH2_MSG_NEWKEYS 21 /* transport layer: kex specific messages, can be reused */ #define SSH2_MSG_KEXDH_INIT 30 #define SSH2_MSG_KEXDH_REPLY 31 /* dh-group-exchange */ #define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30 #define SSH2_MSG_KEX_DH_GEX_GROUP 31 #define SSH2_MSG_KEX_DH_GEX_INIT 32 #define SSH2_MSG_KEX_DH_GEX_REPLY 33 #define SSH2_MSG_KEX_DH_GEX_REQUEST 34 /* ecdh */ #define SSH2_MSG_KEX_ECDH_INIT 30 #define SSH2_MSG_KEX_ECDH_REPLY 31 /* transport layer: OpenSSH extensions */ #define SSH2_MSG_PING 192 #define SSH2_MSG_PONG 193 /* user authentication: generic */ #define SSH2_MSG_USERAUTH_REQUEST 50 #define SSH2_MSG_USERAUTH_FAILURE 51 #define SSH2_MSG_USERAUTH_SUCCESS 52 #define SSH2_MSG_USERAUTH_BANNER 53 /* user authentication: method specific, can be reused */ #define SSH2_MSG_USERAUTH_PK_OK 60 #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 #define SSH2_MSG_USERAUTH_INFO_REQUEST 60 #define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 /* connection protocol: generic */ #define SSH2_MSG_GLOBAL_REQUEST 80 #define SSH2_MSG_REQUEST_SUCCESS 81 #define SSH2_MSG_REQUEST_FAILURE 82 /* channel related messages */ #define SSH2_MSG_CHANNEL_OPEN 90 #define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 #define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 #define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 #define SSH2_MSG_CHANNEL_DATA 94 #define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 #define SSH2_MSG_CHANNEL_EOF 96 #define SSH2_MSG_CHANNEL_CLOSE 97 #define SSH2_MSG_CHANNEL_REQUEST 98 #define SSH2_MSG_CHANNEL_SUCCESS 99 #define SSH2_MSG_CHANNEL_FAILURE 100 /* disconnect reason code */ #define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 #define SSH2_DISCONNECT_PROTOCOL_ERROR 2 #define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 #define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 #define SSH2_DISCONNECT_RESERVED 4 #define SSH2_DISCONNECT_MAC_ERROR 5 #define SSH2_DISCONNECT_COMPRESSION_ERROR 6 #define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 #define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 #define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 #define SSH2_DISCONNECT_CONNECTION_LOST 10 #define SSH2_DISCONNECT_BY_APPLICATION 11 #define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 #define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 #define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 #define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 /* misc */ #define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 #define SSH2_OPEN_CONNECT_FAILED 2 #define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 #define SSH2_OPEN_RESOURCE_SHORTAGE 4 #define SSH2_EXTENDED_DATA_STDERR 1 /* Certificate types for OpenSSH certificate keys extension */ #define SSH2_CERT_TYPE_USER 1 #define SSH2_CERT_TYPE_HOST 2 openssh-10.0p1/PaxHeaders.10889/ssh_api.c100644 001750 001750 0000000003614775415623 0014746xustar0030 atime=1744182234.856273586 openssh-10.0p1/ssh_api.c010064400017500001750000000362671477541562300133470ustar00djmdjm/* $OpenBSD: ssh_api.c,v 1.32 2024/10/18 05:14:51 djm Exp $ */ /* * Copyright (c) 2012 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. */ #include "includes.h" #include #include #include #include "ssh_api.h" #include "compat.h" #include "log.h" #include "authfile.h" #include "sshkey.h" #include "dh.h" #include "misc.h" #include "ssh2.h" #include "version.h" #include "myproposal.h" #include "ssherr.h" #include "sshbuf.h" #include "openbsd-compat/openssl-compat.h" #include int _ssh_exchange_banner(struct ssh *); 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 ssh *, struct sshkey *, struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *); /* * stubs for privsep calls in the server side implementation of kex. */ int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, const u_char *, u_int, const char *, const char *, const char *, u_int); #ifdef WITH_OPENSSL DH *mm_choose_dh(int, int, int); #endif int mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { size_t slen = 0; int ret; ret = sshkey_sign(key, sigp, &slen, data, datalen, alg, sk_provider, sk_pin, compat); *lenp = slen; return ret; } #ifdef WITH_OPENSSL DH * mm_choose_dh(int min, int nbits, int max) { return choose_dh(min, nbits, max); } #endif /* API */ int ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) { char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; char *populated[PROPOSAL_MAX]; struct ssh *ssh; char **proposal; static int called; int r; if (!called) { seed_rng(); called = 1; } if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL) return SSH_ERR_ALLOC_FAIL; if (is_server) ssh_packet_set_server(ssh); /* Initialize key exchange */ proposal = kex_params ? kex_params->proposal : myproposal; kex_proposal_populate_entries(ssh, populated, proposal[PROPOSAL_KEX_ALGS], proposal[PROPOSAL_ENC_ALGS_CTOS], proposal[PROPOSAL_MAC_ALGS_CTOS], proposal[PROPOSAL_COMP_ALGS_CTOS], proposal[PROPOSAL_SERVER_HOST_KEY_ALGS]); r = kex_ready(ssh, populated); kex_proposal_free_entries(populated); if (r != 0) { ssh_free(ssh); return r; } ssh->kex->server = is_server; if (is_server) { #ifdef WITH_OPENSSL 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] = kex_gen_server; # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server; ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = 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] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; return 0; } void ssh_free(struct ssh *ssh) { struct key_entry *k; if (ssh == NULL) return; /* * we've only created the public keys variants in case we * are a acting as a server. */ while ((k = TAILQ_FIRST(&ssh->public_keys)) != NULL) { TAILQ_REMOVE(&ssh->public_keys, k, next); if (ssh->kex && ssh->kex->server) sshkey_free(k->key); free(k); } while ((k = TAILQ_FIRST(&ssh->private_keys)) != NULL) { TAILQ_REMOVE(&ssh->private_keys, k, next); free(k); } ssh_packet_close(ssh); free(ssh); } void ssh_set_app_data(struct ssh *ssh, void *app_data) { ssh->app_data = app_data; } void * ssh_get_app_data(struct ssh *ssh) { return ssh->app_data; } /* Returns < 0 on error, 0 otherwise */ int ssh_add_hostkey(struct ssh *ssh, struct sshkey *key) { struct sshkey *pubkey = NULL; struct key_entry *k = NULL, *k_prv = NULL; int r; if (ssh->kex->server) { if ((r = sshkey_from_private(key, &pubkey)) != 0) return r; if ((k = malloc(sizeof(*k))) == NULL || (k_prv = malloc(sizeof(*k_prv))) == NULL) { free(k); sshkey_free(pubkey); return SSH_ERR_ALLOC_FAIL; } k_prv->key = key; TAILQ_INSERT_TAIL(&ssh->private_keys, k_prv, next); /* add the public key, too */ k->key = pubkey; TAILQ_INSERT_TAIL(&ssh->public_keys, k, next); r = 0; } else { if ((k = malloc(sizeof(*k))) == NULL) return SSH_ERR_ALLOC_FAIL; k->key = key; TAILQ_INSERT_TAIL(&ssh->public_keys, k, next); r = 0; } return r; } int ssh_set_verify_host_key_callback(struct ssh *ssh, int (*cb)(struct sshkey *, struct ssh *)) { if (cb == NULL || ssh->kex == NULL) return SSH_ERR_INVALID_ARGUMENT; ssh->kex->verify_host_key = cb; return 0; } int ssh_input_append(struct ssh *ssh, const u_char *data, size_t len) { return sshbuf_put(ssh_packet_get_input(ssh), data, len); } int ssh_packet_next(struct ssh *ssh, u_char *typep) { int r; u_int32_t seqnr; u_char type; /* * Try to read a packet. Return SSH_MSG_NONE if no packet or not * enough data. */ *typep = SSH_MSG_NONE; 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 * call the function and get the next packet. * Otherwise return the packet type to the caller so it * can decide how to go on. * * We will only call the dispatch function for: * 20-29 Algorithm negotiation * 30-49 Key exchange method specific (numbers can be reused for * different authentication methods) */ for (;;) { if ((r = ssh_packet_read_poll2(ssh, &type, &seqnr)) != 0) return r; if (type > 0 && type < DISPATCH_MAX && type >= SSH2_MSG_KEXINIT && type <= SSH2_MSG_TRANSPORT_MAX && ssh->dispatch[type] != NULL) { if ((r = (*ssh->dispatch[type])(type, seqnr, ssh)) != 0) return r; } else { *typep = type; return 0; } } } const u_char * ssh_packet_payload(struct ssh *ssh, size_t *lenp) { return sshpkt_ptr(ssh, lenp); } int ssh_packet_put(struct ssh *ssh, int type, const u_char *data, size_t len) { int r; if ((r = sshpkt_start(ssh, type)) != 0 || (r = sshpkt_put(ssh, data, len)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; return 0; } const u_char * ssh_output_ptr(struct ssh *ssh, size_t *len) { struct sshbuf *output = ssh_packet_get_output(ssh); *len = sshbuf_len(output); return sshbuf_ptr(output); } int ssh_output_consume(struct ssh *ssh, size_t len) { return sshbuf_consume(ssh_packet_get_output(ssh), len); } int ssh_output_space(struct ssh *ssh, size_t len) { return (0 == sshbuf_check_reserve(ssh_packet_get_output(ssh), len)); } int ssh_input_space(struct ssh *ssh, size_t len) { return (0 == sshbuf_check_reserve(ssh_packet_get_input(ssh), len)); } /* Read other side's version identification. */ int _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) { struct sshbuf *input = ssh_packet_get_input(ssh); const char *mismatch = "Protocol mismatch.\r\n"; 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; for (j = n = 0;;) { 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 (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; } if (sshbuf_len(banner) >= 4 && memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0) break; debug_f("%.*s", (int)sshbuf_len(banner), sshbuf_ptr(banner)); /* Accept lines before banner only on client */ if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) { bad: if ((r = sshbuf_put(ssh_packet_get_output(ssh), mismatch, strlen(mismatch))) != 0) return r; return SSH_ERR_NO_PROTOCOL_VERSION; } } 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(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); compat_banner(ssh, remote_version); if (remote_major == 1 && remote_minor == 99) { remote_major = 2; remote_minor = 0; } if (remote_major != 2) 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, struct sshbuf *banner) { char *cp; int r; 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; if ((cp = sshbuf_dup_string(banner)) == NULL) return SSH_ERR_ALLOC_FAIL; debug("Local version string %.100s", cp); free(cp); return 0; } int _ssh_exchange_banner(struct ssh *ssh) { struct kex *kex = ssh->kex; int r; /* * if _ssh_read_banner() cannot parse a full version string * it will return NULL and we end up calling it again. */ r = 0; if (kex->server) { if (sshbuf_len(ssh->kex->server_version) == 0) r = _ssh_send_banner(ssh, ssh->kex->server_version); if (r == 0 && 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 (sshbuf_len(ssh->kex->server_version) == 0) r = _ssh_read_banner(ssh, ssh->kex->server_version); if (r == 0 && 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 (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; } return 0; } struct sshkey * _ssh_host_public_key(int type, int nid, struct ssh *ssh) { struct key_entry *k; debug3_f("need %d", type); TAILQ_FOREACH(k, &ssh->public_keys, next) { debug3_f("check %s", sshkey_type(k->key)); if (k->key->type == type && (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) return (k->key); } return (NULL); } struct sshkey * _ssh_host_private_key(int type, int nid, struct ssh *ssh) { struct key_entry *k; debug3_f("need %d", type); TAILQ_FOREACH(k, &ssh->private_keys, next) { debug3_f("check %s", sshkey_type(k->key)); if (k->key->type == type && (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) return (k->key); } return (NULL); } int _ssh_verify_host_key(struct sshkey *hostkey, struct ssh *ssh) { struct key_entry *k; debug3_f("need %s", sshkey_type(hostkey)); TAILQ_FOREACH(k, &ssh->public_keys, next) { debug3_f("check %s", sshkey_type(k->key)); if (sshkey_equal_public(hostkey, k->key)) return (0); /* ok */ } return (-1); /* failed */ } /* offer hostkey algorithms in kexinit depending on registered keys */ int _ssh_order_hostkeyalgs(struct ssh *ssh) { struct key_entry *k; char *orig, *avail, *oavail = NULL, *alg, *replace = NULL; char **proposal; size_t maxlen; int ktype, nid, r; /* XXX we de-serialize ssh->kex->my, modify it, and change it */ if ((r = kex_buf2prop(ssh->kex->my, NULL, &proposal)) != 0) return r; orig = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; if ((oavail = avail = strdup(orig)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } maxlen = strlen(avail) + 1; if ((replace = calloc(1, maxlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } *replace = '\0'; while ((alg = strsep(&avail, ",")) && *alg != '\0') { if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) continue; nid = sshkey_ecdsa_nid_from_name(alg); TAILQ_FOREACH(k, &ssh->public_keys, next) { if (k->key->type != ktype && (!sshkey_is_cert(k->key) || k->key->type != sshkey_type_plain(ktype))) continue; if (sshkey_type_plain(k->key->type) == KEY_ECDSA && k->key->ecdsa_nid != nid) continue; /* Candidate */ if (*replace != '\0') strlcat(replace, ",", maxlen); strlcat(replace, alg, maxlen); break; } } if (*replace != '\0') { debug2_f("orig/%d %s", ssh->kex->server, orig); debug2_f("replace/%d %s", ssh->kex->server, replace); free(orig); proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = replace; replace = NULL; /* owned by proposal */ r = kex_prop2buf(ssh->kex->my, proposal); } out: free(oavail); free(replace); kex_prop_free(proposal); return r; } int _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, alg, NULL, NULL, ssh->compat); } openssh-10.0p1/PaxHeaders.10889/ssh_api.h100644 001750 001750 0000000003614775415623 0014753xustar0030 atime=1744182234.857249852 openssh-10.0p1/ssh_api.h010064400017500001750000000105221477541562300133360ustar00djmdjm/* $OpenBSD: ssh_api.h,v 1.2 2018/04/10 00:10:49 djm Exp $ */ /* * Copyright (c) 2012 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. */ #ifndef API_H #define API_H #include #include #include "openbsd-compat/sys-queue.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "ssh.h" #include "ssh2.h" #include "packet.h" struct kex_params { char *proposal[PROPOSAL_MAX]; }; /* public SSH API functions */ /* * ssh_init() create a ssh connection object with given (optional) * key exchange parameters. */ int ssh_init(struct ssh **, int is_server, struct kex_params *kex_params); /* * release ssh connection state. */ void ssh_free(struct ssh *); /* * attach application specific data to the connection state */ void ssh_set_app_data(struct ssh *, void *); void *ssh_get_app_data(struct ssh *); /* * ssh_add_hostkey() registers a private/public hostkey for an ssh * connection. * ssh_add_hostkey() needs to be called before a key exchange is * initiated with ssh_packet_next(). * private hostkeys are required if we need to act as a server. * public hostkeys are used to verify the servers hostkey. */ int ssh_add_hostkey(struct ssh *ssh, struct sshkey *key); /* * ssh_set_verify_host_key_callback() registers a callback function * which should be called instead of the default verification. The * function given must return 0 if the hostkey is ok, -1 if the * verification has failed. */ int ssh_set_verify_host_key_callback(struct ssh *ssh, int (*cb)(struct sshkey *, struct ssh *)); /* * ssh_packet_next() advances to the next input packet and returns * the packet type in typep. * ssh_packet_next() works by processing an input byte-stream, * decrypting the received data and hiding the key-exchange from * the caller. * 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(). * 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(). */ int ssh_packet_next(struct ssh *ssh, u_char *typep); /* * ssh_packet_payload() returns a pointer to the raw payload data of * the current input packet and the length of this payload. * the payload is accessible until ssh_packet_next() is called again. */ const u_char *ssh_packet_payload(struct ssh *ssh, size_t *lenp); /* * ssh_packet_put() creates an encrypted packet with the given type * and payload. * the encrypted packet is appended to the output byte-stream. */ int ssh_packet_put(struct ssh *ssh, int type, const u_char *data, size_t len); /* * ssh_input_space() checks if 'len' bytes can be appended to the * input byte-stream. */ int ssh_input_space(struct ssh *ssh, size_t len); /* * ssh_input_append() appends data to the input byte-stream. */ int ssh_input_append(struct ssh *ssh, const u_char *data, size_t len); /* * ssh_output_space() checks if 'len' bytes can be appended to the * output byte-stream. XXX */ int ssh_output_space(struct ssh *ssh, size_t len); /* * ssh_output_ptr() retrieves both a pointer and the length of the * current output byte-stream. the bytes need to be sent over the * network. the number of bytes that have been successfully sent can * be removed from the output byte-stream with ssh_output_consume(). */ const u_char *ssh_output_ptr(struct ssh *ssh, size_t *len); /* * ssh_output_consume() removes the given number of bytes from * the output byte-stream. */ int ssh_output_consume(struct ssh *ssh, size_t len); #endif openssh-10.0p1/PaxHeaders.10889/ssh_config100644 001750 001750 0000000003614775415623 0015221xustar0030 atime=1744182234.857249852 openssh-10.0p1/ssh_config010064400017500001750000000027661477541562300136170ustar00djmdjm# $OpenBSD: ssh_config,v 1.36 2023/08/02 23:04:38 djm Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for # users, and the values can be changed in per-user configuration files # or on the command line. # Configuration data is parsed as follows: # 1. command line options # 2. user-specific file # 3. system-wide file # Any configuration value is only changed the first time it is set. # Thus, host-specific definitions should be at the beginning of the # configuration file, and defaults at the end. # Site-wide defaults for some commonly used options. For a comprehensive # list of available options, their meanings and defaults, please see the # ssh_config(5) man page. # Host * # ForwardAgent no # ForwardX11 no # PasswordAuthentication yes # HostbasedAuthentication no # GSSAPIAuthentication no # GSSAPIDelegateCredentials no # BatchMode no # CheckHostIP no # AddressFamily any # ConnectTimeout 0 # StrictHostKeyChecking ask # IdentityFile ~/.ssh/id_rsa # IdentityFile ~/.ssh/id_dsa # IdentityFile ~/.ssh/id_ecdsa # IdentityFile ~/.ssh/id_ed25519 # Port 22 # 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 # PermitLocalCommand no # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h # UserKnownHostsFile ~/.ssh/known_hosts.d/%k openssh-10.0p1/PaxHeaders.10889/ssh_config.0100644 001750 001750 0000000003514775415623 0015356xustar0029 atime=1744182234.85822642 openssh-10.0p1/ssh_config.0010064400017500001750000002347341477541562300137570ustar00djmdjmSSH_CONFIG(5) File Formats Manual SSH_CONFIG(5) NAME ssh_config M-bM-^@M-^S OpenSSH client configuration file 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) Unless noted otherwise, for each parameter, the first obtained value will be used. The configuration files contain sections separated by 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 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 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. 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. 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 keyword 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 criteria or the single token all which always matches. The available criteria keywords are: canonical, final, exec, localnetwork, host, originalhost, tagged, command, user, localuser, and version. The all criteria must appear alone or immediately after canonical or final. Other criteria may be combined arbitrarily. All criteria but all, canonical, and final require an argument. Criteria may be negated by prepending an exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y). The canonical keyword 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 final keyword requests that the configuration be re-parsed (regardless of whether CanonicalizeHostname is enabled), and matches only during this final pass. If CanonicalizeHostname is enabled, then canonical and final match during the same pass. 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. Arguments to exec accept the tokens described in the TOKENS section. The localnetwork keyword matches the addresses of active local network interfaces against the supplied list of networks in CIDR format. This may be convenient for varying the effective configuration on devices that roam between networks. Note that network address is not a trustworthy criteria in many situations (e.g. when the network is automatically configured using DHCP) and so caution should be applied if using it to control security- sensitive configuration. 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 tagged keyword matches a tag name specified by a prior Tag directive or on the ssh(1) command-line using the -P flag. The command keyword matches the remote command that has been requested, or the subsystem name that is being invoked (e.g. "sftp" for an SFTP session). The empty string will match the case where a command or tag has not been specified, i.e. M-bM-^@M-^XMatch tag ""M-bM-^@M-^Y. The version keyword matches against the version string of ssh(1), for example M-bM-^@M-^\OpenSSH_10.0M-bM-^@M-^]. 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). Finally, the sessiontype keyword matches the requested session type, which may be one of shell for interactive sessions, exec for command execution sessions, subsystem for subsystem invocations such as sftp(1), or none for transport-only sessions, such as when ssh(1) is started with the -N flag. AddKeysToAgent Specifies whether keys should be automatically added to a running ssh-agent(1). If this option is set to 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 ssh-add(1). If this option is set to ask, ssh(1) will require confirmation using the SSH_ASKPASS program before adding a key (see ssh-add(1) for details). If this option is set to confirm, each use of the key must be confirmed, as if the -c option was specified to ssh-add(1). If this option is set to no, no keys are added to the agent. Alternately, this option may be specified as a time interval using the format described in the TIME FORMATS section of sshd_config(5) to specify the key's lifetime in ssh-agent(1), after which it will automatically be removed. The argument must be no (the default), yes, confirm (optionally followed by a time interval), ask or a time interval. AddressFamily Specifies which address family to use when connecting. Valid arguments are any (the default), inet (use IPv4 only), or inet6 (use IPv6 only). BatchMode If set to yes, user interaction such as password prompts and host key confirmation requests will be disabled. This option is useful in scripts and other batch jobs where no user is present to interact with ssh(1). The argument must be yes or no (the default). 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. BindInterface Use the address of the specified interface on the local machine as the source address of the connection. 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, yes, will attempt to look up the unqualified hostname using the system resolver's search rules. A value of no 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, no, is not to perform any name rewriting and let the system resolver handle all hostname lookups. If set to yes then, for connections that do not use a ProxyCommand or ProxyJump, 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 always, 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. A value of none disables the use of a ProxyJump host. CanonicalizeMaxDots Specifies the maximum number of dot characters in a hostname before canonicalization is disabled. The default, 1, allows a single dot (i.e. hostname.subdomain). 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, "*.a.example.com:*.b.example.com,*.c.example.com" will allow hostnames matching "*.a.example.com" to be canonicalized to names in the "*.b.example.com" or "*.c.example.com" domains. A single argument of "none" causes no CNAMEs to be considered for canonicalization. This is the default behaviour. CASignatureAlgorithms Specifies which algorithms are allowed for signing of certificates by certificate authorities (CAs). The default is: ssh-ed25519,ecdsa-sha2-nistp256, ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. ssh(1) will not accept host certificates signed using algorithms other than those specified. 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 IdentityFile directive or -i flag to ssh(1), via ssh-agent(1), or via a PKCS11Provider or SecurityKeyProvider. Arguments to CertificateFile may use the tilde syntax to refer to a user's home directory, the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. It is possible to have multiple certificate files specified in configuration files; these certificates will be tried in sequence. Multiple CertificateFile directives will add to the list of certificates used for authentication. ChannelTimeout Specifies whether and how quickly ssh(1) should close inactive channels. Timeouts are specified as one or more M-bM-^@M-^\type=intervalM-bM-^@M-^] pairs separated by whitespace, where the M-bM-^@M-^\typeM-bM-^@M-^] must be the special keyword M-bM-^@M-^\globalM-bM-^@M-^] or a channel type name from the list below, optionally containing wildcard characters. The timeout value M-bM-^@M-^\intervalM-bM-^@M-^] is specified in seconds or may use any of the units documented in the TIME FORMATS section. For example, M-bM-^@M-^\session=5mM-bM-^@M-^] would cause interactive sessions to terminate after five minutes of inactivity. Specifying a zero value disables the inactivity timeout. The special timeout M-bM-^@M-^\globalM-bM-^@M-^] applies to all active channels, taken together. Traffic on any active channel will reset the timeout, but when the timeout expires then all open channels will be closed. Note that this global timeout is not matched by wildcards and must be specified explicitly. The available channel type names include: agent-connection Open connections to ssh-agent(1). direct-tcpip, direct-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established from a ssh(1) local forwarding, i.e. LocalForward or DynamicForward. forwarded-tcpip, forwarded-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established to a sshd(8) listening on behalf of a ssh(1) remote forwarding, i.e. RemoteForward. session The interactive main session, including shell session, command execution, scp(1), sftp(1), etc. tun-connection Open TunnelForward connections. x11-connection Open X11 forwarding sessions. Note that in all the above cases, terminating an inactive session does not guarantee to remove all resources associated with the session, e.g. shell processes or X11 clients relating to the session may continue to execute. Moreover, terminating an inactive channel or session does not necessarily close the SSH connection, nor does it prevent a client from requesting another channel of the same type. In particular, expiring an inactive forwarding session does not prevent another identical forwarding from being subsequently created. The default is not to expire channels of any type for inactivity. CheckHostIP If set to yes, ssh(1) will additionally check the host IP address in the known_hosts file. This allows it to detect if a host key changed due to DNS spoofing and will add addresses of destination hosts to ~/.ssh/known_hosts in the process, regardless of the setting of StrictHostKeyChecking. If the option is set to no (the default), the check will not be executed. Ciphers Specifies the ciphers allowed and their order of preference. Multiple ciphers must be comma-separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified ciphers will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified ciphers will be placed at the head of the default set. 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 chacha20-poly1305@openssh.com The default is: chacha20-poly1305@openssh.com, aes128-gcm@openssh.com,aes256-gcm@openssh.com, aes128-ctr,aes192-ctr,aes256-ctr The list of available ciphers may also be obtained using "ssh -Q cipher". 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 yes or no (the default). Compression Specifies whether to use compression. The argument must be yes or no (the default). 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 timeout is applied both to establishing the connection and to performing the initial SSH protocol handshake and key exchange. ControlMaster Enables the sharing of multiple sessions over a single network connection. When set to yes, 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 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. Setting this to ask will cause ssh(1) to listen for control connections, but require confirmation using ssh-askpass(1). If the ControlPath cannot be opened, ssh(1) 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: auto and autoask. The latter requires confirmation like the ask option. ControlPath Specify the path to the control socket used for connection sharing as described in the ControlMaster section above or the string none to disable connection sharing. Arguments to ControlPath may use the tilde syntax to refer to a user's home directory, the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. 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 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 yes or 0, then the master connection will remain in the background indefinitely (until killed or closed via a mechanism such as the "ssh -O exit"). 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 localhost 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. EnableEscapeCommandline Enables the command line option in the EscapeChar menu for interactive sessions (default M-bM-^@M-^X~CM-bM-^@M-^Y). By default, the command line is disabled. EnableSSHKeysign Setting this option to yes 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 yes or no (the default). 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 none 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, (e.g. if either end is unable to bind and listen on a specified port). Note that ExitOnForwardFailure does not apply to connections made over port forwardings and will not, for example, cause ssh(1) to exit if TCP connections to the ultimate forwarding destination fail. The argument must be yes or no (the default). FingerprintHash Specifies the hash algorithm used when displaying key fingerprints. Valid options are: md5 and sha256 (the default). ForkAfterAuthentication 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 the StdinNull configuration option being set to M-bM-^@M-^\yesM-bM-^@M-^]. The recommended way to start X11 programs at a remote site is with something like ssh -f host xterm, which is the same as ssh host xterm if the ForkAfterAuthentication configuration option is set to M-bM-^@M-^\yesM-bM-^@M-^]. If the ExitOnForwardFailure configuration option is set to M-bM-^@M-^\yesM-bM-^@M-^], then a client started with the ForkAfterAuthentication configuration option being set to M-bM-^@M-^\yesM-bM-^@M-^] will wait for all remote port forwards to be successfully established before placing itself in the background. The argument to this keyword must be yes (same as the -f option) or no (the default). ForwardAgent Specifies whether the connection to the authentication agent (if any) will be forwarded to the remote machine. The argument may be yes, no (the default), an explicit path to an agent socket or the name of an environment variable (beginning with M-bM-^@M-^X$M-bM-^@M-^Y) in which to find the path. 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 yes or no (the default). 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. Setting 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. ForwardX11Trusted If this option is set to yes, remote X11 clients will have full access to the original X11 display. If this option is set to no (the default), remote X11 clients will be considered untrusted and prevented from stealing or tampering with data belonging to trusted X11 clients. Furthermore, the xauth(1) token used for the session will be set to expire after 20 minutes. Remote clients will be refused access after this time. 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 yes or no (the default). 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 no. GSSAPIDelegateCredentials Forward (delegate) credentials to the server. The default is no. 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 visually reveal identifying information if the file's contents are disclosed. The default is no. Note that existing names and addresses in known hosts files will not be converted automatically, but may be manually hashed using ssh-keygen(1). HostbasedAcceptedAlgorithms Specifies the signature algorithms that will be used for hostbased authentication as a comma-separated list of patterns. Alternately if the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified signature algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified signature algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified signature algorithms will be placed at the head of the default set. The default for this option is: ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 The -Q option of ssh(1) may be used to list supported signature algorithms. This was formerly named HostbasedKeyTypes. HostbasedAuthentication Specifies whether to try rhosts based authentication with public key authentication. The argument must be yes or no (the default). HostKeyAlgorithms Specifies the host key signature algorithms that the client wants to use in order of preference. Alternately if the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified signature algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified signature algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified signature algorithms will be placed at the head of the default set. The default for this option is: ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ecdsa-sha2-nistp256@openssh.com, sk-ssh-ed25519@openssh.com, rsa-sha2-512,rsa-sha2-256 If hostkeys are known for the destination host then this default is modified to prefer their algorithms. The list of available signature algorithms may also be obtained using "ssh -Q HostKeyAlgorithms". HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key in the host key database files and when validating host certificates. This option is useful for tunneling SSH connections or for multiple servers running on a single host. Hostname Specifies the real host name to log into. This can be used to specify nicknames or abbreviations for hosts. Arguments to Hostname accept the tokens described in the TOKENS section. Numeric IP addresses are also permitted (both on the command line and in Hostname specifications). The default is the name given on the command line. IdentitiesOnly Specifies that ssh(1) should only use the configured authentication identity and certificate files (either the default files, or those explicitly configured in the ssh_config files or passed on the ssh(1) command-line), even if ssh-agent(1) or a PKCS11Provider or SecurityKeyProvider offers more identities. The argument to this keyword must be yes or no (the default). This option is intended for situations where ssh-agent offers many different identities. IdentityAgent Specifies the UNIX-domain socket used to communicate with the authentication agent. This option overrides the SSH_AUTH_SOCK environment variable and can be used to select a specific agent. Setting the socket name to none disables the use of an authentication agent. If the string "SSH_AUTH_SOCK" is specified, the location of the socket will be read from the SSH_AUTH_SOCK environment variable. Otherwise if the specified value begins with a M-bM-^@M-^X$M-bM-^@M-^Y character, then it will be treated as an environment variable containing the location of the socket. Arguments to IdentityAgent may use the tilde syntax to refer to a user's home directory, the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. IdentityFile Specifies a file from which the user's ECDSA, authenticator- hosted ECDSA, Ed25519, authenticator-hosted Ed25519 or RSA authentication identity is read. You can also specify a public key file to use the corresponding private key that is loaded in ssh-agent(1) when the private key file is not present locally. The default is ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519_sk. Additionally, any identities represented by the authentication agent will be used for authentication unless IdentitiesOnly is set. If no certificates have been explicitly specified by CertificateFile, ssh(1) will try to load certificate information from the filename obtained by appending -cert.pub to the path of a specified IdentityFile. Arguments to IdentityFile may use the tilde syntax to refer to a user's home directory or the tokens described in the TOKENS section. Alternately an argument of none may be used to indicate no identity files should be loaded. 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. IdentityFile may also be used in conjunction with CertificateFile in order to provide any certificate also needed for authentication with the identity. 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. Include Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(7) wildcards, tokens as described in the TOKENS section, environment variables as described in the ENVIRONMENT VARIABLES section and, for user configurations, shell-like M-bM-^@M-^X~M-bM-^@M-^Y references to user home directories. Wildcards will be expanded and processed in lexical order. Files without absolute paths are assumed to be in ~/.ssh if included in a user configuration file or /etc/ssh if included from the system configuration file. Include directive may appear inside a Match or Host block to perform conditional inclusion. IPQoS Specifies the IPv4 type-of-service or DSCP class for connections. Accepted values are af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, ef, le, lowdelay, throughput, reliability, a numeric value, or none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is af21 (Low-Latency Data) for interactive sessions and cs1 (Lower Effort) for non- interactive sessions. KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. The argument to this keyword must be yes (the default) or no. ChallengeResponseAuthentication is a deprecated alias for this. 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: bsdauth and pam. KexAlgorithms Specifies the permitted KEX (Key Exchange) algorithms that will be used and their preference order. The selected algorithm will be the first algorithm in this list that the server also supports. Multiple algorithms must be comma-separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will be placed at the head of the default set. The default is: mlkem768x25519-sha256, sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256 The list of supported key exchange algorithms may also be obtained using "ssh -Q kex". KnownHostsCommand Specifies a command to use to obtain a list of host keys, in addition to those listed in UserKnownHostsFile and GlobalKnownHostsFile. This command is executed after the files have been read. It may write host key lines to standard output in identical format to the usual files (described in the VERIFYING HOST KEYS section in ssh(1)). Arguments to KnownHostsCommand accept the tokens described in the TOKENS section. The command may be invoked multiple times per connection: once when preparing the preference list of host key algorithms to use, again to obtain the host key for the requested host name and, if CheckHostIP is enabled, one more time to obtain the host key matching the server's address. If the command exits abnormally or returns a non-zero exit status then the connection is terminated. LocalCommand Specifies a command to execute on the local machine after successfully connecting to the server. The command string extends to the end of the line, and is executed with the user's shell. Arguments to LocalCommand accept the tokens described in the TOKENS section. 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 or Unix-domain socket on the local machine be forwarded over the secure channel to the specified host and port (or Unix-domain socket) from the remote machine. For a TCP port, the first argument must be [bind_address:]port or a Unix domain socket path. The second argument is the destination and may be host:hostport or a Unix domain socket path if the remote host supports it. IPv6 addresses can be specified by enclosing addresses in square brackets. If either argument contains a '/' in it, that argument will be interpreted as a Unix-domain socket (on the corresponding host) rather than a TCP port. 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 localhost 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. Unix domain socket paths may use the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. 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. LogVerbose Specify one or more overrides to LogLevel. An override consists of one or more pattern lists that matches the source file, function and line number to force detailed logging for. For example, an override pattern of: kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* would enable detailed logging for line 1000 of kex.c, everything in the kex_exchange_identification() function, and all code in the packet.c file. This option is intended for debugging and no overrides are enabled by default. MACs Specifies the MAC (message authentication code) algorithms in order of preference. The MAC algorithm is used for data integrity protection. Multiple algorithms must be comma- separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will be placed at the head of the default set. The algorithms that contain "-etm" 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, hmac-sha1-etm@openssh.com, umac-64@openssh.com,umac-128@openssh.com, hmac-sha2-256,hmac-sha2-512,hmac-sha1 The list of available MAC algorithms may also be obtained using "ssh -Q mac". NoHostAuthenticationForLocalhost Disable host authentication for localhost (loopback addresses). The argument to this keyword must be yes or no (the default). NumberOfPasswordPrompts Specifies the number of password prompts before giving up. The argument to this keyword must be an integer. The default is 3. ObscureKeystrokeTiming Specifies whether ssh(1) should try to obscure inter-keystroke timings from passive observers of network traffic. If enabled, then for interactive sessions, ssh(1) will send keystrokes at fixed intervals of a few tens of milliseconds and will send fake keystroke packets for some time after typing ceases. The argument to this keyword must be yes, no or an interval specifier of the form interval:milliseconds (e.g. interval:80 for 80 milliseconds). The default is to obscure keystrokes using a 20ms packet interval. Note that smaller intervals will result in higher fake keystroke packet rates. PasswordAuthentication Specifies whether to use password authentication. The argument to this keyword must be yes (the default) or no. PermitLocalCommand Allow local command execution via the LocalCommand option or using the !command escape sequence in ssh(1). The argument must be yes or no (the default). PermitRemoteOpen Specifies the destinations to which remote TCP port forwarding is permitted when RemoteForward is used as a SOCKS proxy. The forwarding specification must be one of the following forms: PermitRemoteOpen host:port PermitRemoteOpen IPv4_addr:port PermitRemoteOpen [IPv6_addr]:port Multiple forwards may be specified by separating them with whitespace. An argument of any can be used to remove all restrictions and permit any forwarding requests. An argument of none can be used to prohibit all forwarding requests. The wildcard M-bM-^@M-^X*M-bM-^@M-^Y 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. PKCS11Provider Specifies which PKCS#11 provider to use or 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 ssh(1) should use to communicate with a PKCS#11 token providing keys for user authentication. 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 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 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. Arguments to ProxyCommand accept the tokens described in the 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 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 none 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 ProxyJump Specifies one or more jump proxies as either [user@]host[:port] or an ssh URI. Multiple proxies may be separated by comma characters and will be visited sequentially. Setting this option will cause ssh(1) to connect to the target host by first making a ssh(1) connection to the specified ProxyJump host and then establishing a TCP forwarding to the ultimate target from there. Setting the host to none disables this option entirely. Note that this option will compete with the ProxyCommand option - whichever is specified first will prevent later instances of the other from taking effect. 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. ~/.ssh/config should be used if specific configuration is required for jump hosts. 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 no. PubkeyAcceptedAlgorithms Specifies the signature algorithms that will be used for public key authentication as a comma-separated list of patterns. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the algorithms after it will be appended to the default instead of replacing it. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will be placed at the head of the default set. The default for this option is: ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 The list of available signature algorithms may also be obtained using "ssh -Q PubkeyAcceptedAlgorithms". PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be yes (the default), no, unbound or host-bound. The final two options enable public key authentication while respectively disabling or enabling the OpenSSH host-bound authentication protocol extension required for restricted ssh-agent(1) forwarding. RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of 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 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. 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 RemoteCommand accept the tokens described in the TOKENS section. RemoteForward Specifies that a TCP port or Unix-domain socket on the remote machine be forwarded over the secure channel. The remote port may either be forwarded to a specified host and port or Unix- domain socket 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 [bind_address:]port or, if the remote host supports it, a Unix domain socket path. If forwarding to a specific destination then the second argument must be host:hostport or a Unix domain socket path, otherwise if no destination argument is specified then the remote forwarding will be established as a SOCKS proxy. When acting as a SOCKS proxy, the destination of the connection can be restricted by PermitRemoteOpen. IPv6 addresses can be specified by enclosing addresses in square brackets. If either argument contains a '/' in it, that argument will be interpreted as a Unix-domain socket (on the corresponding host) rather than a TCP port. Multiple forwardings may be specified, and additional forwardings can be given on the command line. Privileged ports can be forwarded only when logging in as root on the remote machine. Unix domain socket paths may use the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. If the port argument is 0, 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: no (never request a TTY), yes (always request a TTY when standard input is a TTY), force (always request a TTY) or auto (request a TTY when opening a login session). This option mirrors the -t and -T flags for ssh(1). RequiredRSASize Specifies the minimum RSA key size (in bits) that ssh(1) will accept. User authentication keys smaller than this limit will be ignored. Servers that present host keys smaller than this limit will cause the connection to be terminated. The default is 1024 bits. Note that this limit may only be raised from the default. 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). Arguments to RevokedHostKeys may use the tilde syntax to refer to a user's home directory, the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. 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. If the specified value begins with a M-bM-^@M-^X$M-bM-^@M-^Y character, then it will be treated as an environment variable containing the path to the library. SendEnv Specifies what variables from the local environ(7) should be sent to the server. The server must also support it, and the server must be configured to accept these environment variables. Note that the TERM environment variable is always sent whenever a pseudo-terminal is requested as it is required by the protocol. 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. See PATTERNS for more information on patterns. It is possible to clear previously set SendEnv variable names by prefixing patterns with -. The default is not to send any environment variables. 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 unresponsive. 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. 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. SessionType May be used to either request invocation of a subsystem on the remote system, or to prevent the execution of a remote command at all. The latter is useful for just forwarding ports. The argument to this keyword must be none (same as the -N option), subsystem (same as the -s option) or default (shell or command execution). SetEnv Directly specify one or more environment variables and their contents to be sent to the server in the form M-bM-^@M-^\NAME=VALUEM-bM-^@M-^]. Similarly to SendEnv, with the exception of the TERM variable, the server must be prepared to accept the environment variable. The M-bM-^@M-^\VALUEM-bM-^@M-^] may use the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. StdinNull Redirects stdin from /dev/null (actually, prevents reading from stdin). Either this or the equivalent -n option must be used when ssh is run in the background. The argument to this keyword must be yes (same as the -n option) or no (the default). 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 yes or no (the default). StrictHostKeyChecking If this flag is set to yes, 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 man-in-the-middle (MITM) 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 accept-new then ssh will automatically add new host keys to the user's known_hosts file, but will not permit connections to hosts with changed host keys. If this flag is set to no or 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 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. SyslogFacility Gives the facility code that is used when logging messages from ssh(1). The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is USER. 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 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. To disable TCP keepalive messages, the value should be set to no. See also ServerAliveInterval for protocol-level keepalives. Tag Specify a configuration tag name that may be later used by a Match directive to select a block of configuration. Tunnel Request tun(4) device forwarding between the client and the server. The argument must be yes, point-to-point (layer 3), ethernet (layer 2), or no (the default). Specifying yes requests the default tunnel mode, which is point-to-point. 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 any, which uses the next available tunnel device. If remote_tun is not specified, it defaults to any. The default is any:any. 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 yes, no or 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 explicitly accepted by the user, the host was authenticated via UserKnownHostsFile (i.e. not GlobalKnownHostsFile) and the host was authenticated using a plain key and not a certificate. UpdateHostKeys is enabled by default if the user has not overridden the default UserKnownHostsFile setting and has not enabled VerifyHostKeyDNS, otherwise UpdateHostKeys will be set to no. If UpdateHostKeys is set to ask, 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 "hostkeys@openssh.com" protocol extension used to inform the client of all the server's hostkeys. 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. Arguments to User may use the tokens described in the TOKENS section (with the exception of %r and %C) and environment variables as described in the ENVIRONMENT VARIABLES section. UserKnownHostsFile Specifies one or more files to use for the user host key database, separated by whitespace. Each filename may use tilde notation to refer to the user's home directory, the tokens described in the TOKENS section and environment variables as described in the ENVIRONMENT VARIABLES section. A value of none causes ssh(1) to ignore any user-specific known hosts files. 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 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 ask. If this option is set to ask, information on fingerprint match will be displayed, but the user will still need to confirm new host keys according to the StrictHostKeyChecking option. The default is no. See also VERIFYING HOST KEYS in ssh(1). VersionAddendum Optionally specifies additional text to append to the SSH protocol banner sent by the client upon connection. The default is none. VisualHostKey If this flag is set to 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 no (the default), no fingerprint strings are printed at login and only the fingerprint string will be printed for unknown host keys. 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 ".co.uk" 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 "dialup" pool, the following entry (in authorized_keys) could be used: from="!*.dialup.example.com,*.example.com" Note that a negated match will never produce a positive result by itself. For example, attempting to match "host3" against the following pattern- list will fail: from="!host1,!host2" The solution here is to include a term that will yield a positive match, such as a wildcard: from="!host1,!host2,*" TOKENS Arguments to some keywords can make use of tokens, which are expanded at runtime: %% A literal M-bM-^@M-^X%M-bM-^@M-^Y. %C Hash of %l%h%p%r%j. %d Local user's home directory. %f The fingerprint of the server's host key. %H The known_hosts hostname or address that is being searched for. %h The remote hostname. %I A string describing the reason for a KnownHostsCommand execution: either ADDRESS when looking up a host by address (only when CheckHostIP is enabled), HOSTNAME when searching by hostname, or ORDER when preparing the host key algorithm preference list to use for the destination host. %i The local user ID. %j The contents of the ProxyJump option, or the empty string if this option is unset. %K The base64 encoded host key. %k The host key alias if specified, otherwise the original remote hostname given on the command line. %L The local hostname. %l The local hostname, including the domain name. %n The original remote hostname, as given on the command line. %p The remote port. %r The remote username. %T The local tun(4) or tap(4) network interface assigned if tunnel forwarding was requested, or "NONE" otherwise. %t The type of the server host key, e.g. ssh-ed25519. %u The local username. CertificateFile, ControlPath, IdentityAgent, IdentityFile, Include, KnownHostsCommand, LocalForward, Match exec, RemoteCommand, RemoteForward, RevokedHostKeys, UserKnownHostsFile and VersionAddendum accept the tokens %%, %C, %d, %h, %i, %j, %k, %L, %l, %n, %p, %r, and %u. KnownHostsCommand additionally accepts the tokens %f, %H, %I, %K and %t. Hostname accepts the tokens %% and %h. LocalCommand accepts all tokens. ProxyCommand and ProxyJump accept the tokens %%, %h, %n, %p, and %r. Note that some of these directives build commands for execution via the shell. Because ssh(1) performs no filtering or escaping of characters that have special meaning in shell commands (e.g. quotes), it is the user's responsibility to ensure that the arguments passed to ssh(1) do not contain such characters and that tokens are appropriately quoted when used. ENVIRONMENT VARIABLES Arguments to some keywords can be expanded at runtime from environment variables on the client by enclosing them in ${}, for example ${HOME}/.ssh would refer to the user's .ssh directory. If a specified environment variable does not exist then an error will be returned and the setting for that keyword will be ignored. The keywords CertificateFile, ControlPath, IdentityAgent, IdentityFile, Include, KnownHostsCommand, and UserKnownHostsFile support environment variables. The keywords LocalForward and RemoteForward support environment variables only for Unix domain socket paths. 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 writable 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 7.6 March 3, 2025 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/ssh_config.5100644 001750 001750 0000000003614775415623 0015364xustar0030 atime=1744182234.859202797 openssh-10.0p1/ssh_config.5010064400017500001750000002107751477541562300137630ustar00djmdjm.\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $OpenBSD: ssh_config.5,v 1.413 2025/03/03 06:53:09 dtucker Exp $ .Dd $Mdocdate: March 3 2025 $ .Dt SSH_CONFIG 5 .Os .Sh NAME .Nm ssh_config .Nd OpenSSH client configuration file .Sh DESCRIPTION .Xr ssh 1 obtains configuration data from the following sources in the following order: .Pp .Bl -enum -offset indent -compact .It command-line options .It user's configuration file .Pq Pa ~/.ssh/config .It system-wide configuration file .Pq Pa /etc/ssh/ssh_config .El .Pp Unless noted otherwise, for each parameter, the first obtained value will be used. The configuration files contain sections separated by .Cm Host specifications, and that section is only applied for hosts that match one of the patterns given in the specification. The matched host name is usually the one given on the command line (see the .Cm CanonicalizeHostname option for exceptions). .Pp Since the first obtained value for each parameter is used, more host-specific declarations should be given near the beginning of the file, and general defaults at the end. .Pp The file contains keyword-argument pairs, one per line. Lines starting with .Ql # and empty lines are interpreted as comments. Arguments may optionally be enclosed in double quotes .Pq \&" in order to represent arguments containing spaces. Configuration options may be separated by whitespace or optional whitespace and exactly one .Ql = ; the latter format is useful to avoid the need to quote whitespace when specifying configuration options using the .Nm ssh , .Nm scp , and .Nm sftp .Fl o option. .Pp The possible keywords and their meanings are as follows (note that keywords are case-insensitive and arguments are case-sensitive): .Bl -tag -width Ds .It Cm Host Restricts the following declarations (up to the next .Cm Host or .Cm Match keyword) to be only for those hosts that match one of the patterns given after the keyword. If more than one pattern is provided, they should be separated by whitespace. A single .Ql * as a pattern can be used to provide global defaults for all hosts. The host is usually the .Ar hostname argument given on the command line (see the .Cm CanonicalizeHostname keyword for exceptions). .Pp A pattern entry may be negated by prefixing it with an exclamation mark .Pq Sq !\& . If a negated entry is matched, then the .Cm Host entry is ignored, regardless of whether any other patterns on the line match. Negated matches are therefore useful to provide exceptions for wildcard matches. .Pp See .Sx PATTERNS for more information on patterns. .It Cm Match Restricts the following declarations (up to the next .Cm Host or .Cm Match keyword) to be used only when the conditions following the .Cm Match keyword are satisfied. Match conditions are specified using one or more criteria or the single token .Cm all which always matches. The available criteria keywords are: .Cm canonical , .Cm final , .Cm exec , .Cm localnetwork , .Cm host , .Cm originalhost , .Cm tagged , .Cm command , .Cm user , .Cm localuser , and .Cm version . The .Cm all criteria must appear alone or immediately after .Cm canonical or .Cm final . Other criteria may be combined arbitrarily. All criteria but .Cm all , .Cm canonical , and .Cm final require an argument. Criteria may be negated by prepending an exclamation mark .Pq Sq !\& . .Pp The .Cm canonical keyword matches only when the configuration file is being re-parsed after hostname canonicalization (see the .Cm CanonicalizeHostname option). This may be useful to specify conditions that work with canonical host names only. .Pp The .Cm final keyword requests that the configuration be re-parsed (regardless of whether .Cm CanonicalizeHostname is enabled), and matches only during this final pass. If .Cm CanonicalizeHostname is enabled, then .Cm canonical and .Cm final match during the same pass. .Pp The .Cm exec keyword executes the specified command under the user's shell. If the command returns a zero exit status then the condition is considered true. Commands containing whitespace characters must be quoted. Arguments to .Cm exec accept the tokens described in the .Sx TOKENS section. .Pp The .Cm localnetwork keyword matches the addresses of active local network interfaces against the supplied list of networks in CIDR format. This may be convenient for varying the effective configuration on devices that roam between networks. Note that network address is not a trustworthy criteria in many situations (e.g. when the network is automatically configured using DHCP) and so caution should be applied if using it to control security-sensitive configuration. .Pp The other keywords' criteria must be single entries or comma-separated lists and may use the wildcard and negation operators described in the .Sx PATTERNS section. .Pp The criteria for the .Cm host keyword are matched against the target hostname, after any substitution by the .Cm Hostname or .Cm CanonicalizeHostname options. The .Cm originalhost keyword matches against the hostname as it was specified on the command-line. .Pp The .Cm tagged keyword matches a tag name specified by a prior .Cm Tag directive or on the .Xr ssh 1 command-line using the .Fl P flag. The .Cm command keyword matches the remote command that has been requested, or the subsystem name that is being invoked (e.g.\& .Qq sftp for an SFTP session). The empty string will match the case where a command or tag has not been specified, i.e.\& .Sq Match tag \&"\&" . The .Cm version keyword matches against the version string of .Xr ssh 1 , for example .Dq OpenSSH_10.0 . .Pp The .Cm user keyword matches against the target username on the remote host. The .Cm localuser keyword matches against the name of the local user running .Xr ssh 1 (this keyword may be useful in system-wide .Nm files). .Pp Finally, the .Cm sessiontype keyword matches the requested session type, which may be one of .Cm shell for interactive sessions, .Cm exec for command execution sessions, .Cm subsystem for subsystem invocations such as .Xr sftp 1 , or .Cm none for transport-only sessions, such as when .Xr ssh 1 is started with the .Fl N flag. .It Cm AddKeysToAgent Specifies whether keys should be automatically added to a running .Xr ssh-agent 1 . If this option is set to .Cm yes and a key is loaded from a file, the key and its passphrase are added to the agent with the default lifetime, as if by .Xr ssh-add 1 . If this option is set to .Cm ask , .Xr ssh 1 will require confirmation using the .Ev SSH_ASKPASS program before adding a key (see .Xr ssh-add 1 for details). If this option is set to .Cm confirm , each use of the key must be confirmed, as if the .Fl c option was specified to .Xr ssh-add 1 . If this option is set to .Cm no , no keys are added to the agent. Alternately, this option may be specified as a time interval using the format described in the .Sx TIME FORMATS section of .Xr sshd_config 5 to specify the key's lifetime in .Xr ssh-agent 1 , after which it will automatically be removed. The argument must be .Cm no (the default), .Cm yes , .Cm confirm (optionally followed by a time interval), .Cm ask or a time interval. .It Cm AddressFamily Specifies which address family to use when connecting. Valid arguments are .Cm any (the default), .Cm inet (use IPv4 only), or .Cm inet6 (use IPv6 only). .It Cm BatchMode If set to .Cm yes , user interaction such as password prompts and host key confirmation requests will be disabled. This option is useful in scripts and other batch jobs where no user is present to interact with .Xr ssh 1 . The argument must be .Cm yes or .Cm no (the default). .It Cm BindAddress Use the specified address on the local machine as the source address of the connection. Only useful on systems with more than one address. .It Cm BindInterface Use the address of the specified interface on the local machine as the source address of the connection. .It Cm CanonicalDomains When .Cm CanonicalizeHostname is enabled, this option specifies the list of domain suffixes in which to search for the specified destination host. .It Cm CanonicalizeFallbackLocal Specifies whether to fail with an error when hostname canonicalization fails. The default, .Cm yes , will attempt to look up the unqualified hostname using the system resolver's search rules. A value of .Cm no will cause .Xr ssh 1 to fail instantly if .Cm CanonicalizeHostname is enabled and the target hostname cannot be found in any of the domains specified by .Cm CanonicalDomains . .It Cm CanonicalizeHostname Controls whether explicit hostname canonicalization is performed. The default, .Cm no , is not to perform any name rewriting and let the system resolver handle all hostname lookups. If set to .Cm yes then, for connections that do not use a .Cm ProxyCommand or .Cm ProxyJump , .Xr ssh 1 will attempt to canonicalize the hostname specified on the command line using the .Cm CanonicalDomains suffixes and .Cm CanonicalizePermittedCNAMEs rules. If .Cm CanonicalizeHostname is set to .Cm always , then canonicalization is applied to proxied connections too. .Pp If this option is enabled, then the configuration files are processed again using the new target name to pick up any new configuration in matching .Cm Host and .Cm Match stanzas. A value of .Cm none disables the use of a .Cm ProxyJump host. .It Cm CanonicalizeMaxDots Specifies the maximum number of dot characters in a hostname before canonicalization is disabled. The default, 1, allows a single dot (i.e. hostname.subdomain). .It Cm CanonicalizePermittedCNAMEs Specifies rules to determine whether CNAMEs should be followed when canonicalizing hostnames. The rules consist of one or more arguments of .Ar source_domain_list : Ns Ar target_domain_list , where .Ar source_domain_list is a pattern-list of domains that may follow CNAMEs in canonicalization, and .Ar target_domain_list is a pattern-list of domains that they may resolve to. .Pp For example, .Qq *.a.example.com:*.b.example.com,*.c.example.com will allow hostnames matching .Qq *.a.example.com to be canonicalized to names in the .Qq *.b.example.com or .Qq *.c.example.com domains. .Pp A single argument of .Qq none causes no CNAMEs to be considered for canonicalization. This is the default behaviour. .It Cm CASignatureAlgorithms Specifies which algorithms are allowed for signing of certificates by certificate authorities (CAs). The default is: .Bd -literal -offset indent ssh-ed25519,ecdsa-sha2-nistp256, ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. .Pp .Xr ssh 1 will not accept host certificates signed using algorithms other than those specified. .It Cm CertificateFile Specifies a file from which the user's certificate is read. A corresponding private key must be provided separately in order to use this certificate either from an .Cm IdentityFile directive or .Fl i flag to .Xr ssh 1 , via .Xr ssh-agent 1 , or via a .Cm PKCS11Provider or .Cm SecurityKeyProvider . .Pp Arguments to .Cm CertificateFile may use the tilde syntax to refer to a user's home directory, the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. .Pp It is possible to have multiple certificate files specified in configuration files; these certificates will be tried in sequence. Multiple .Cm CertificateFile directives will add to the list of certificates used for authentication. .It Cm ChannelTimeout Specifies whether and how quickly .Xr ssh 1 should close inactive channels. Timeouts are specified as one or more .Dq type=interval pairs separated by whitespace, where the .Dq type must be the special keyword .Dq global or a channel type name from the list below, optionally containing wildcard characters. .Pp The timeout value .Dq interval is specified in seconds or may use any of the units documented in the .Sx TIME FORMATS section. For example, .Dq session=5m would cause interactive sessions to terminate after five minutes of inactivity. Specifying a zero value disables the inactivity timeout. .Pp The special timeout .Dq global applies to all active channels, taken together. Traffic on any active channel will reset the timeout, but when the timeout expires then all open channels will be closed. Note that this global timeout is not matched by wildcards and must be specified explicitly. .Pp The available channel type names include: .Bl -tag -width Ds .It Cm agent-connection Open connections to .Xr ssh-agent 1 . .It Cm direct-tcpip , Cm direct-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established from a .Xr ssh 1 local forwarding, i.e.\& .Cm LocalForward or .Cm DynamicForward . .It Cm forwarded-tcpip , Cm forwarded-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established to a .Xr sshd 8 listening on behalf of a .Xr ssh 1 remote forwarding, i.e.\& .Cm RemoteForward . .It Cm session The interactive main session, including shell session, command execution, .Xr scp 1 , .Xr sftp 1 , etc. .It Cm tun-connection Open .Cm TunnelForward connections. .It Cm x11-connection Open X11 forwarding sessions. .El .Pp Note that in all the above cases, terminating an inactive session does not guarantee to remove all resources associated with the session, e.g. shell processes or X11 clients relating to the session may continue to execute. .Pp Moreover, terminating an inactive channel or session does not necessarily close the SSH connection, nor does it prevent a client from requesting another channel of the same type. In particular, expiring an inactive forwarding session does not prevent another identical forwarding from being subsequently created. .Pp The default is not to expire channels of any type for inactivity. .It Cm CheckHostIP If set to .Cm yes , .Xr ssh 1 will additionally check the host IP address in the .Pa known_hosts file. This allows it to detect if a host key changed due to DNS spoofing and will add addresses of destination hosts to .Pa ~/.ssh/known_hosts in the process, regardless of the setting of .Cm StrictHostKeyChecking . If the option is set to .Cm no (the default), the check will not be executed. .It Cm Ciphers Specifies the ciphers allowed and their order of preference. Multiple ciphers must be comma-separated. If the specified list begins with a .Sq + character, then the specified ciphers will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified ciphers (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified ciphers will be placed at the head of the default set. .Pp The supported ciphers are: .Bd -literal -offset indent 3des-cbc aes128-cbc aes192-cbc aes256-cbc aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com .Ed .Pp The default is: .Bd -literal -offset indent chacha20-poly1305@openssh.com, aes128-gcm@openssh.com,aes256-gcm@openssh.com, aes128-ctr,aes192-ctr,aes256-ctr .Ed .Pp The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClearAllForwardings Specifies that all local, remote, and dynamic port forwardings specified in the configuration files or on the command line be cleared. This option is primarily useful when used from the .Xr ssh 1 command line to clear port forwardings set in configuration files, and is automatically set by .Xr scp 1 and .Xr sftp 1 . The argument must be .Cm yes or .Cm no (the default). .It Cm Compression Specifies whether to use compression. The argument must be .Cm yes or .Cm no (the default). .It Cm ConnectionAttempts Specifies the number of tries (one per second) to make before exiting. The argument must be an integer. This may be useful in scripts if the connection sometimes fails. The default is 1. .It Cm ConnectTimeout Specifies the timeout (in seconds) used when connecting to the SSH server, instead of using the default system TCP timeout. This timeout is applied both to establishing the connection and to performing the initial SSH protocol handshake and key exchange. .It Cm ControlMaster Enables the sharing of multiple sessions over a single network connection. When set to .Cm yes , .Xr ssh 1 will listen for connections on a control socket specified using the .Cm ControlPath argument. Additional sessions can connect to this socket using the same .Cm ControlPath with .Cm ControlMaster set to .Cm no (the default). These sessions will try to reuse the master instance's network connection rather than initiating new ones, but will fall back to connecting normally if the control socket does not exist, or is not listening. .Pp Setting this to .Cm ask will cause .Xr ssh 1 to listen for control connections, but require confirmation using .Xr ssh-askpass 1 . If the .Cm ControlPath cannot be opened, .Xr ssh 1 will continue without connecting to a master instance. .Pp X11 and .Xr ssh-agent 1 forwarding is supported over these multiplexed connections, however the display and agent forwarded will be the one belonging to the master connection i.e. it is not possible to forward multiple displays or agents. .Pp Two additional options allow for opportunistic multiplexing: try to use a master connection but fall back to creating a new one if one does not already exist. These options are: .Cm auto and .Cm autoask . The latter requires confirmation like the .Cm ask option. .It Cm ControlPath Specify the path to the control socket used for connection sharing as described in the .Cm ControlMaster section above or the string .Cm none to disable connection sharing. Arguments to .Cm ControlPath may use the tilde syntax to refer to a user's home directory, the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. It is recommended that any .Cm ControlPath used for opportunistic connection sharing include at least %h, %p, and %r (or alternatively %C) and be placed in a directory that is not writable by other users. This ensures that shared connections are uniquely identified. .It Cm ControlPersist When used in conjunction with .Cm ControlMaster , specifies that the master connection should remain open in the background (waiting for future client connections) after the initial client connection has been closed. If set to .Cm no (the default), then the master connection will not be placed into the background, and will close as soon as the initial client connection is closed. If set to .Cm yes or 0, then the master connection will remain in the background indefinitely (until killed or closed via a mechanism such as the .Qq ssh -O exit ) . If set to a time in seconds, or a time in any of the formats documented in .Xr sshd_config 5 , then the backgrounded master connection will automatically terminate after it has remained idle (with no client connections) for the specified time. .It Cm DynamicForward Specifies that a TCP port on the local machine be forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. .Pp The argument must be .Sm off .Oo Ar bind_address : Oc Ar port . .Sm on IPv6 addresses can be specified by enclosing addresses in square brackets. By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Cm localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. .Pp Currently the SOCKS4 and SOCKS5 protocols are supported, and .Xr ssh 1 will act as a SOCKS server. Multiple forwardings may be specified, and additional forwardings can be given on the command line. Only the superuser can forward privileged ports. .It Cm EnableEscapeCommandline Enables the command line option in the .Cm EscapeChar menu for interactive sessions (default .Ql ~C ) . By default, the command line is disabled. .It Cm EnableSSHKeysign Setting this option to .Cm yes in the global client configuration file .Pa /etc/ssh/ssh_config enables the use of the helper program .Xr ssh-keysign 8 during .Cm HostbasedAuthentication . The argument must be .Cm yes or .Cm no (the default). This option should be placed in the non-hostspecific section. See .Xr ssh-keysign 8 for more information. .It Cm EscapeChar Sets the escape character (default: .Ql ~ ) . The escape character can also be set on the command line. The argument should be a single character, .Ql ^ followed by a letter, or .Cm none to disable the escape character entirely (making the connection transparent for binary data). .It Cm ExitOnForwardFailure Specifies whether .Xr ssh 1 should terminate the connection if it cannot set up all requested dynamic, tunnel, local, and remote port forwardings, (e.g.\& if either end is unable to bind and listen on a specified port). Note that .Cm ExitOnForwardFailure does not apply to connections made over port forwardings and will not, for example, cause .Xr ssh 1 to exit if TCP connections to the ultimate forwarding destination fail. The argument must be .Cm yes or .Cm no (the default). .It Cm FingerprintHash Specifies the hash algorithm used when displaying key fingerprints. Valid options are: .Cm md5 and .Cm sha256 (the default). .It Cm ForkAfterAuthentication Requests .Nm ssh to go to background just before command execution. This is useful if .Nm ssh is going to ask for passwords or passphrases, but the user wants it in the background. This implies the .Cm StdinNull configuration option being set to .Dq yes . The recommended way to start X11 programs at a remote site is with something like .Ic ssh -f host xterm , which is the same as .Ic ssh host xterm if the .Cm ForkAfterAuthentication configuration option is set to .Dq yes . .Pp If the .Cm ExitOnForwardFailure configuration option is set to .Dq yes , then a client started with the .Cm ForkAfterAuthentication configuration option being set to .Dq yes will wait for all remote port forwards to be successfully established before placing itself in the background. The argument to this keyword must be .Cm yes (same as the .Fl f option) or .Cm no (the default). .It Cm ForwardAgent Specifies whether the connection to the authentication agent (if any) will be forwarded to the remote machine. The argument may be .Cm yes , .Cm no (the default), an explicit path to an agent socket or the name of an environment variable (beginning with .Sq $ ) in which to find the path. .Pp Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent's Unix-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. .It Cm ForwardX11 Specifies whether X11 connections will be automatically redirected over the secure channel and .Ev DISPLAY set. The argument must be .Cm yes or .Cm no (the default). .Pp X11 forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the user's X11 authorization database) can access the local X11 display through the forwarded connection. An attacker may then be able to perform activities such as keystroke monitoring if the .Cm ForwardX11Trusted option is also enabled. .It Cm ForwardX11Timeout Specify a timeout for untrusted X11 forwarding using the format described in the .Sx TIME FORMATS section of .Xr sshd_config 5 . X11 connections received by .Xr ssh 1 after this time will be refused. Setting .Cm ForwardX11Timeout to zero will disable the timeout and permit X11 forwarding for the life of the connection. The default is to disable untrusted X11 forwarding after twenty minutes has elapsed. .It Cm ForwardX11Trusted If this option is set to .Cm yes , remote X11 clients will have full access to the original X11 display. .Pp If this option is set to .Cm no (the default), remote X11 clients will be considered untrusted and prevented from stealing or tampering with data belonging to trusted X11 clients. Furthermore, the .Xr xauth 1 token used for the session will be set to expire after 20 minutes. Remote clients will be refused access after this time. .Pp See the X11 SECURITY extension specification for full details on the restrictions imposed on untrusted clients. .It Cm GatewayPorts Specifies whether remote hosts are allowed to connect to local forwarded ports. By default, .Xr ssh 1 binds local port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. .Cm GatewayPorts can be used to specify that ssh should bind local port forwardings to the wildcard address, thus allowing remote hosts to connect to forwarded ports. The argument must be .Cm yes or .Cm no (the default). .It Cm GlobalKnownHostsFile Specifies one or more files to use for the global host key database, separated by whitespace. The default is .Pa /etc/ssh/ssh_known_hosts , .Pa /etc/ssh/ssh_known_hosts2 . .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . .It Cm GSSAPIDelegateCredentials Forward (delegate) credentials to the server. The default is .Cm no . .It Cm HashKnownHosts Indicates that .Xr ssh 1 should hash host names and addresses when they are added to .Pa ~/.ssh/known_hosts . These hashed names may be used normally by .Xr ssh 1 and .Xr sshd 8 , but they do not visually reveal identifying information if the file's contents are disclosed. The default is .Cm no . Note that existing names and addresses in known hosts files will not be converted automatically, but may be manually hashed using .Xr ssh-keygen 1 . .It Cm HostbasedAcceptedAlgorithms Specifies the signature algorithms that will be used for hostbased authentication as a comma-separated list of patterns. Alternately if the specified list begins with a .Sq + character, then the specified signature algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified signature algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified signature algorithms will be placed at the head of the default set. The default for this option is: .Bd -literal -offset 3n ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp The .Fl Q option of .Xr ssh 1 may be used to list supported signature algorithms. This was formerly named HostbasedKeyTypes. .It Cm HostbasedAuthentication Specifies whether to try rhosts based authentication with public key authentication. The argument must be .Cm yes or .Cm no (the default). .It Cm HostKeyAlgorithms Specifies the host key signature algorithms that the client wants to use in order of preference. Alternately if the specified list begins with a .Sq + character, then the specified signature algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified signature algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified signature algorithms will be placed at the head of the default set. The default for this option is: .Bd -literal -offset 3n ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ecdsa-sha2-nistp256@openssh.com, sk-ssh-ed25519@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp If hostkeys are known for the destination host then this default is modified to prefer their algorithms. .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key in the host key database files and when validating host certificates. This option is useful for tunneling SSH connections or for multiple servers running on a single host. .It Cm Hostname Specifies the real host name to log into. This can be used to specify nicknames or abbreviations for hosts. Arguments to .Cm Hostname accept the tokens described in the .Sx TOKENS section. Numeric IP addresses are also permitted (both on the command line and in .Cm Hostname specifications). The default is the name given on the command line. .It Cm IdentitiesOnly Specifies that .Xr ssh 1 should only use the configured authentication identity and certificate files (either the default files, or those explicitly configured in the .Nm files or passed on the .Xr ssh 1 command-line), even if .Xr ssh-agent 1 or a .Cm PKCS11Provider or .Cm SecurityKeyProvider offers more identities. The argument to this keyword must be .Cm yes or .Cm no (the default). This option is intended for situations where ssh-agent offers many different identities. .It Cm IdentityAgent Specifies the .Ux Ns -domain socket used to communicate with the authentication agent. .Pp This option overrides the .Ev SSH_AUTH_SOCK environment variable and can be used to select a specific agent. Setting the socket name to .Cm none disables the use of an authentication agent. If the string .Qq SSH_AUTH_SOCK is specified, the location of the socket will be read from the .Ev SSH_AUTH_SOCK environment variable. Otherwise if the specified value begins with a .Sq $ character, then it will be treated as an environment variable containing the location of the socket. .Pp Arguments to .Cm IdentityAgent may use the tilde syntax to refer to a user's home directory, the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. .It Cm IdentityFile Specifies a file from which the user's ECDSA, authenticator-hosted ECDSA, Ed25519, authenticator-hosted Ed25519 or RSA authentication identity is read. You can also specify a public key file to use the corresponding private key that is loaded in .Xr ssh-agent 1 when the private key file is not present locally. The default is .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ecdsa_sk , .Pa ~/.ssh/id_ed25519 and .Pa ~/.ssh/id_ed25519_sk . Additionally, any identities represented by the authentication agent will be used for authentication unless .Cm IdentitiesOnly is set. If no certificates have been explicitly specified by .Cm CertificateFile , .Xr ssh 1 will try to load certificate information from the filename obtained by appending .Pa -cert.pub to the path of a specified .Cm IdentityFile . .Pp Arguments to .Cm IdentityFile may use the tilde syntax to refer to a user's home directory or the tokens described in the .Sx TOKENS section. Alternately an argument of .Cm none may be used to indicate no identity files should be loaded. .Pp It is possible to have multiple identity files specified in configuration files; all these identities will be tried in sequence. Multiple .Cm IdentityFile directives will add to the list of identities tried (this behaviour differs from that of other configuration directives). .Pp .Cm IdentityFile may be used in conjunction with .Cm IdentitiesOnly to select which identities in an agent are offered during authentication. .Cm IdentityFile may also be used in conjunction with .Cm CertificateFile in order to provide any certificate also needed for authentication with the identity. .It Cm IgnoreUnknown Specifies a pattern-list of unknown options to be ignored if they are encountered in configuration parsing. This may be used to suppress errors if .Nm contains options that are unrecognised by .Xr ssh 1 . It is recommended that .Cm IgnoreUnknown be listed early in the configuration file as it will not be applied to unknown options that appear before it. .It Cm Include Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain .Xr glob 7 wildcards, tokens as described in the .Sx TOKENS section, environment variables as described in the .Sx ENVIRONMENT VARIABLES section and, for user configurations, shell-like .Sq ~ references to user home directories. Wildcards will be expanded and processed in lexical order. Files without absolute paths are assumed to be in .Pa ~/.ssh if included in a user configuration file or .Pa /etc/ssh if included from the system configuration file. .Cm Include directive may appear inside a .Cm Match or .Cm Host block to perform conditional inclusion. .It Cm IPQoS Specifies the IPv4 type-of-service or DSCP class for connections. Accepted values are .Cm af11 , .Cm af12 , .Cm af13 , .Cm af21 , .Cm af22 , .Cm af23 , .Cm af31 , .Cm af32 , .Cm af33 , .Cm af41 , .Cm af42 , .Cm af43 , .Cm cs0 , .Cm cs1 , .Cm cs2 , .Cm cs3 , .Cm cs4 , .Cm cs5 , .Cm cs6 , .Cm cs7 , .Cm ef , .Cm le , .Cm lowdelay , .Cm throughput , .Cm reliability , a numeric value, or .Cm none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is .Cm af21 (Low-Latency Data) for interactive sessions and .Cm cs1 (Lower Effort) for non-interactive sessions. .It Cm KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. The argument to this keyword must be .Cm yes (the default) or .Cm no . .Cm ChallengeResponseAuthentication is a deprecated alias for this. .It Cm KbdInteractiveDevices Specifies the list of methods to use in keyboard-interactive authentication. Multiple method names must be comma-separated. The default is to use the server specified list. The methods available vary depending on what the server supports. For an OpenSSH server, it may be zero or more of: .Cm bsdauth and .Cm pam . .It Cm KexAlgorithms Specifies the permitted KEX (Key Exchange) algorithms that will be used and their preference order. The selected algorithm will be the first algorithm in this list that the server also supports. Multiple algorithms must be comma-separated. .Pp If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. 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 default is: .Bd -literal -offset indent mlkem768x25519-sha256, sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256 .Ed .Pp The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q kex . .It Cm KnownHostsCommand Specifies a command to use to obtain a list of host keys, in addition to those listed in .Cm UserKnownHostsFile and .Cm GlobalKnownHostsFile . This command is executed after the files have been read. It may write host key lines to standard output in identical format to the usual files (described in the .Sx VERIFYING HOST KEYS section in .Xr ssh 1 ) . Arguments to .Cm KnownHostsCommand accept the tokens described in the .Sx TOKENS section. The command may be invoked multiple times per connection: once when preparing the preference list of host key algorithms to use, again to obtain the host key for the requested host name and, if .Cm CheckHostIP is enabled, one more time to obtain the host key matching the server's address. If the command exits abnormally or returns a non-zero exit status then the connection is terminated. .It Cm LocalCommand Specifies a command to execute on the local machine after successfully connecting to the server. The command string extends to the end of the line, and is executed with the user's shell. Arguments to .Cm LocalCommand accept the tokens described in the .Sx TOKENS section. .Pp The command is run synchronously and does not have access to the session of the .Xr ssh 1 that spawned it. It should not be used for interactive commands. .Pp This directive is ignored unless .Cm PermitLocalCommand has been enabled. .It Cm LocalForward Specifies that a TCP port or Unix-domain socket on the local machine be forwarded over the secure channel to the specified host and port (or Unix-domain socket) from the remote machine. For a TCP port, the first argument must be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on or a Unix domain socket path. The second argument is the destination and may be .Ar host : Ns Ar hostport or a Unix domain socket path if the remote host supports it. .Pp IPv6 addresses can be specified by enclosing addresses in square brackets. .Pp If either argument contains a '/' in it, that argument will be interpreted as a Unix-domain socket (on the corresponding host) rather than a TCP port. .Pp Multiple forwardings may be specified, and additional forwardings can be given on the command line. Only the superuser can forward privileged ports. By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Cm localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. Unix domain socket paths may use the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. .It Cm LogLevel Gives the verbosity level that is used when logging messages from .Xr ssh 1 . The possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of verbose output. .It Cm LogVerbose Specify one or more overrides to LogLevel. An override consists of one or more pattern lists that matches the source file, function and line number to force detailed logging for. For example, an override pattern of: .Bd -literal -offset indent kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* .Ed .Pp would enable detailed logging for line 1000 of .Pa kex.c , everything in the .Fn kex_exchange_identification function, and all code in the .Pa packet.c file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs Specifies the MAC (message authentication code) algorithms in order of preference. The MAC algorithm is used for data integrity protection. Multiple algorithms must be comma-separated. If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified algorithms will be placed at the head of the default set. .Pp The algorithms that contain .Qq -etm calculate the MAC after encryption (encrypt-then-mac). These are considered safer and their use recommended. .Pp The default is: .Bd -literal -offset indent umac-64-etm@openssh.com,umac-128-etm@openssh.com, hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, hmac-sha1-etm@openssh.com, umac-64@openssh.com,umac-128@openssh.com, hmac-sha2-256,hmac-sha2-512,hmac-sha1 .Ed .Pp The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm NoHostAuthenticationForLocalhost Disable host authentication for localhost (loopback addresses). The argument to this keyword must be .Cm yes or .Cm no (the default). .It Cm NumberOfPasswordPrompts Specifies the number of password prompts before giving up. The argument to this keyword must be an integer. The default is 3. .It Cm ObscureKeystrokeTiming Specifies whether .Xr ssh 1 should try to obscure inter-keystroke timings from passive observers of network traffic. If enabled, then for interactive sessions, .Xr ssh 1 will send keystrokes at fixed intervals of a few tens of milliseconds and will send fake keystroke packets for some time after typing ceases. The argument to this keyword must be .Cm yes , .Cm no or an interval specifier of the form .Cm interval:milliseconds (e.g.\& .Cm interval:80 for 80 milliseconds). The default is to obscure keystrokes using a 20ms packet interval. Note that smaller intervals will result in higher fake keystroke packet rates. .It Cm PasswordAuthentication Specifies whether to use password authentication. The argument to this keyword must be .Cm yes (the default) or .Cm no . .It Cm PermitLocalCommand Allow local command execution via the .Ic LocalCommand option or using the .Ic !\& Ns Ar command escape sequence in .Xr ssh 1 . The argument must be .Cm yes or .Cm no (the default). .It Cm PermitRemoteOpen Specifies the destinations to which remote TCP port forwarding is permitted when .Cm RemoteForward is used as a SOCKS proxy. The forwarding specification must be one of the following forms: .Pp .Bl -item -offset indent -compact .It .Cm PermitRemoteOpen .Sm off .Ar host : port .Sm on .It .Cm PermitRemoteOpen .Sm off .Ar IPv4_addr : port .Sm on .It .Cm PermitRemoteOpen .Sm off .Ar \&[ IPv6_addr \&] : port .Sm on .El .Pp Multiple forwards may be specified by separating them with whitespace. An argument of .Cm any can be used to remove all restrictions and permit any forwarding requests. An argument of .Cm none can be used to prohibit all forwarding requests. The wildcard .Sq * can be used for host or port to allow all hosts or ports respectively. Otherwise, no pattern matching or address lookups are performed on supplied names. .It Cm PKCS11Provider Specifies which PKCS#11 provider to use or .Cm none to indicate that no provider should be used (the default). The argument to this keyword is a path to the PKCS#11 shared library .Xr ssh 1 should use to communicate with a PKCS#11 token providing keys for user authentication. .It Cm Port Specifies the port number to connect on the remote host. The default is 22. .It Cm PreferredAuthentications Specifies the order in which the client should try authentication methods. This allows a client to prefer one method (e.g.\& .Cm keyboard-interactive ) over another method (e.g.\& .Cm password ) . The default is: .Bd -literal -offset indent gssapi-with-mic,hostbased,publickey, keyboard-interactive,password .Ed .It Cm ProxyCommand Specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed using the user's shell .Ql exec directive to avoid a lingering shell process. .Pp Arguments to .Cm ProxyCommand accept the tokens described in the .Sx TOKENS section. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an .Xr sshd 8 server running on some machine, or execute .Ic sshd -i somewhere. Host key management will be done using the .Cm Hostname of the host being connected (defaulting to the name typed by the user). Setting the command to .Cm none disables this option entirely. Note that .Cm CheckHostIP is not available for connects with a proxy command. .Pp This directive is useful in conjunction with .Xr nc 1 and its proxy support. For example, the following directive would connect via an HTTP proxy at 192.0.2.0: .Bd -literal -offset 3n ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p .Ed .It Cm ProxyJump Specifies one or more jump proxies as either .Sm off .Op Ar user No @ .Ar host .Op : Ns Ar port .Sm on or an ssh URI. Multiple proxies may be separated by comma characters and will be visited sequentially. Setting this option will cause .Xr ssh 1 to connect to the target host by first making a .Xr ssh 1 connection to the specified .Cm ProxyJump host and then establishing a TCP forwarding to the ultimate target from there. Setting the host to .Cm none disables this option entirely. .Pp Note that this option will compete with the .Cm ProxyCommand option - whichever is specified first will prevent later instances of the other from taking effect. .Pp Note also that the configuration for the destination host (either supplied via the command-line or the configuration file) is not generally applied to jump hosts. .Pa ~/.ssh/config should be used if specific configuration is required for jump hosts. .It Cm ProxyUseFdpass Specifies that .Cm ProxyCommand will pass a connected file descriptor back to .Xr ssh 1 instead of continuing to execute and pass data. The default is .Cm no . .It Cm PubkeyAcceptedAlgorithms Specifies the signature algorithms that will be used for public key authentication as a comma-separated list of patterns. If the specified list begins with a .Sq + character, then the algorithms after it will be appended to the default instead of replacing it. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified algorithms will be placed at the head of the default set. The default for this option is: .Bd -literal -offset 3n ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be .Cm yes (the default), .Cm no , .Cm unbound or .Cm host-bound . The final two options enable public key authentication while respectively disabling or enabling the OpenSSH host-bound authentication protocol extension required for restricted .Xr ssh-agent 1 forwarding. .It Cm RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of .Sq K , .Sq M , or .Sq G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between .Sq 1G and .Sq 4G , depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the TIME FORMATS section of .Xr sshd_config 5 . The default value for .Cm RekeyLimit is .Cm default none , which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. .It Cm RemoteCommand Specifies a command to execute on the remote machine after successfully connecting to the server. The command string extends to the end of the line, and is executed with the user's shell. Arguments to .Cm RemoteCommand accept the tokens described in the .Sx TOKENS section. .It Cm RemoteForward Specifies that a TCP port or Unix-domain socket on the remote machine be forwarded over the secure channel. The remote port may either be forwarded to a specified host and port or Unix-domain socket from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote client to connect to arbitrary destinations from the local machine. The first argument is the listening specification and may be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on or, if the remote host supports it, a Unix domain socket path. If forwarding to a specific destination then the second argument must be .Ar host : Ns Ar hostport or a Unix domain socket path, otherwise if no destination argument is specified then the remote forwarding will be established as a SOCKS proxy. When acting as a SOCKS proxy, the destination of the connection can be restricted by .Cm PermitRemoteOpen . .Pp IPv6 addresses can be specified by enclosing addresses in square brackets. .Pp If either argument contains a '/' in it, that argument will be interpreted as a Unix-domain socket (on the corresponding host) rather than a TCP port. .Pp Multiple forwardings may be specified, and additional forwardings can be given on the command line. Privileged ports can be forwarded only when logging in as root on the remote machine. Unix domain socket paths may use the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. .Pp If the .Ar port argument is 0, the listen port will be dynamically allocated on the server and reported to the client at run time. .Pp If the .Ar bind_address is not specified, the default is to only bind to loopback addresses. If the .Ar bind_address is .Ql * or an empty string, then the forwarding is requested to listen on all interfaces. Specifying a remote .Ar bind_address will only succeed if the server's .Cm GatewayPorts option is enabled (see .Xr sshd_config 5 ) . .It Cm RequestTTY Specifies whether to request a pseudo-tty for the session. The argument may be one of: .Cm no (never request a TTY), .Cm yes (always request a TTY when standard input is a TTY), .Cm force (always request a TTY) or .Cm auto (request a TTY when opening a login session). This option mirrors the .Fl t and .Fl T flags for .Xr ssh 1 . .It Cm RequiredRSASize Specifies the minimum RSA key size (in bits) that .Xr ssh 1 will accept. User authentication keys smaller than this limit will be ignored. Servers that present host keys smaller than this limit will cause the connection to be terminated. The default is .Cm 1024 bits. Note that this limit may only be raised from the default. .It Cm RevokedHostKeys Specifies revoked host public keys. Keys listed in this file will be refused for host authentication. Note that if this file does not exist or is not readable, then host authentication will be refused for all hosts. Keys may be specified as a text file, listing one public key per line, or as an OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . Arguments to .Cm RevokedHostKeys may use the tilde syntax to refer to a user's home directory, the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. .It Cm SecurityKeyProvider Specifies a path to a library that will be used when loading any FIDO authenticator-hosted keys, overriding the default of using the built-in USB HID support. .Pp If the specified value begins with a .Sq $ character, then it will be treated as an environment variable containing the path to the library. .It Cm SendEnv Specifies what variables from the local .Xr environ 7 should be sent to the server. The server must also support it, and the server must be configured to accept these environment variables. Note that the .Ev TERM environment variable is always sent whenever a pseudo-terminal is requested as it is required by the protocol. Refer to .Cm AcceptEnv in .Xr sshd_config 5 for how to configure the server. Variables are specified by name, which may contain wildcard characters. Multiple environment variables may be separated by whitespace or spread across multiple .Cm SendEnv directives. .Pp See .Sx PATTERNS for more information on patterns. .Pp It is possible to clear previously set .Cm SendEnv variable names by prefixing patterns with .Pa - . The default is not to send any environment variables. .It Cm ServerAliveCountMax Sets the number of server alive messages (see below) which may be sent without .Xr ssh 1 receiving any messages back from the server. If this threshold is reached while server alive messages are being sent, ssh will disconnect from the server, terminating the session. It is important to note that the use of server alive messages is very different from .Cm TCPKeepAlive (below). The server alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by .Cm TCPKeepAlive is spoofable. The server alive mechanism is valuable when the client or server depend on knowing when a connection has become unresponsive. .Pp The default value is 3. If, for example, .Cm ServerAliveInterval (see below) is set to 15 and .Cm ServerAliveCountMax is left at the default, if the server becomes unresponsive, ssh will disconnect after approximately 45 seconds. .It Cm ServerAliveInterval Sets a timeout interval in seconds after which if no data has been received from the server, .Xr ssh 1 will send a message through the encrypted channel to request a response from the server. The default is 0, indicating that these messages will not be sent to the server. .It Cm SessionType May be used to either request invocation of a subsystem on the remote system, or to prevent the execution of a remote command at all. The latter is useful for just forwarding ports. The argument to this keyword must be .Cm none (same as the .Fl N option), .Cm subsystem (same as the .Fl s option) or .Cm default (shell or command execution). .It Cm SetEnv Directly specify one or more environment variables and their contents to be sent to the server in the form .Dq NAME=VALUE . Similarly to .Cm SendEnv , with the exception of the .Ev TERM variable, the server must be prepared to accept the environment variable. .Pp The .Dq VALUE may use the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. .It Cm StdinNull Redirects stdin from .Pa /dev/null (actually, prevents reading from stdin). Either this or the equivalent .Fl n option must be used when .Nm ssh is run in the background. The argument to this keyword must be .Cm yes (same as the .Fl n option) or .Cm no (the default). .It Cm StreamLocalBindMask Sets the octal file creation mode mask .Pq umask used when creating a Unix-domain socket file for local or remote port forwarding. This option is only used for port forwarding to a Unix-domain socket file. .Pp The default value is 0177, which creates a Unix-domain socket file that is readable and writable only by the owner. Note that not all operating systems honor the file mode on Unix-domain socket files. .It Cm StreamLocalBindUnlink Specifies whether to remove an existing Unix-domain socket file for local or remote port forwarding before creating a new one. If the socket file already exists and .Cm StreamLocalBindUnlink is not enabled, .Nm ssh will be unable to forward the port to the Unix-domain socket file. This option is only used for port forwarding to a Unix-domain socket file. .Pp The argument must be .Cm yes or .Cm no (the default). .It Cm StrictHostKeyChecking If this flag is set to .Cm yes , .Xr ssh 1 will never automatically add host keys to the .Pa ~/.ssh/known_hosts file, and refuses to connect to hosts whose host key has changed. This provides maximum protection against man-in-the-middle (MITM) attacks, though it can be annoying when the .Pa /etc/ssh/ssh_known_hosts file is poorly maintained or when connections to new hosts are frequently made. This option forces the user to manually add all new hosts. .Pp If this flag is set to .Cm accept-new then ssh will automatically add new host keys to the user's .Pa known_hosts file, but will not permit connections to hosts with changed host keys. If this flag is set to .Cm no or .Cm off , ssh will automatically add new host keys to the user known hosts files and allow connections to hosts with changed hostkeys to proceed, subject to some restrictions. If this flag is set to .Cm ask (the default), new host keys will be added to the user known host files only after the user has confirmed that is what they really want to do, and ssh will refuse to connect to hosts whose host key has changed. The host keys of known hosts will be verified automatically in all cases. .It Cm SyslogFacility Gives the facility code that is used when logging messages from .Xr ssh 1 . The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is USER. .It Cm TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, this means that connections will die if the route is down temporarily, and some people find it annoying. .Pp The default is .Cm yes (to send TCP keepalive messages), and the client will notice if the network goes down or the remote host dies. This is important in scripts, and many users want it too. .Pp To disable TCP keepalive messages, the value should be set to .Cm no . See also .Cm ServerAliveInterval for protocol-level keepalives. .It Cm Tag Specify a configuration tag name that may be later used by a .Cm Match directive to select a block of configuration. .It Cm Tunnel Request .Xr tun 4 device forwarding between the client and the server. The argument must be .Cm yes , .Cm point-to-point (layer 3), .Cm ethernet (layer 2), or .Cm no (the default). Specifying .Cm yes requests the default tunnel mode, which is .Cm point-to-point . .It Cm TunnelDevice Specifies the .Xr tun 4 devices to open on the client .Pq Ar local_tun and the server .Pq Ar remote_tun . .Pp The argument must be .Sm off .Ar local_tun Op : Ar remote_tun . .Sm on The devices may be specified by numerical ID or the keyword .Cm any , which uses the next available tunnel device. If .Ar remote_tun is not specified, it defaults to .Cm any . The default is .Cm any:any . .It Cm UpdateHostKeys Specifies whether .Xr ssh 1 should accept notifications of additional hostkeys from the server sent after authentication has completed and add them to .Cm UserKnownHostsFile . The argument must be .Cm yes , .Cm no or .Cm ask . This option allows learning alternate hostkeys for a server and supports graceful key rotation by allowing a server to send replacement public keys before old ones are removed. .Pp Additional hostkeys are only accepted if the key used to authenticate the host was already trusted or explicitly accepted by the user, the host was authenticated via .Cm UserKnownHostsFile (i.e. not .Cm GlobalKnownHostsFile ) and the host was authenticated using a plain key and not a certificate. .Pp .Cm UpdateHostKeys is enabled by default if the user has not overridden the default .Cm UserKnownHostsFile setting and has not enabled .Cm VerifyHostKeyDNS , otherwise .Cm UpdateHostKeys will be set to .Cm no . .Pp If .Cm UpdateHostKeys is set to .Cm ask , then the user is asked to confirm the modifications to the known_hosts file. Confirmation is currently incompatible with .Cm ControlPersist , and will be disabled if it is enabled. .Pp Presently, only .Xr sshd 8 from OpenSSH 6.8 and greater support the .Qq hostkeys@openssh.com protocol extension used to inform the client of all the server's hostkeys. .It Cm User Specifies the user to log in as. This can be useful when a different user name is used on different machines. This saves the trouble of having to remember to give the user name on the command line. Arguments to .Cm User may use the tokens described in the .Sx TOKENS section (with the exception of %r and %C) and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. .It Cm UserKnownHostsFile Specifies one or more files to use for the user host key database, separated by whitespace. Each filename may use tilde notation to refer to the user's home directory, the tokens described in the .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. A value of .Cm none causes .Xr ssh 1 to ignore any user-specific known hosts files. The default is .Pa ~/.ssh/known_hosts , .Pa ~/.ssh/known_hosts2 . .It Cm VerifyHostKeyDNS Specifies whether to verify the remote key using DNS and SSHFP resource records. If this option is set to .Cm yes , the client will implicitly trust keys that match a secure fingerprint from DNS. Insecure fingerprints will be handled as if this option was set to .Cm ask . If this option is set to .Cm ask , information on fingerprint match will be displayed, but the user will still need to confirm new host keys according to the .Cm StrictHostKeyChecking option. The default is .Cm no . .Pp See also .Sx VERIFYING HOST KEYS in .Xr ssh 1 . .It Cm VersionAddendum Optionally specifies additional text to append to the SSH protocol banner sent by the client upon connection. The default is .Cm none . .It Cm VisualHostKey If this flag is set to .Cm yes , an ASCII art representation of the remote host key fingerprint is printed in addition to the fingerprint string at login and for unknown host keys. If this flag is set to .Cm no (the default), no fingerprint strings are printed at login and only the fingerprint string will be printed for unknown host keys. .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 program. The default is .Pa /usr/X11R6/bin/xauth . .El .Sh PATTERNS A .Em pattern consists of zero or more non-whitespace characters, .Sq * (a wildcard that matches zero or more characters), or .Sq ?\& (a wildcard that matches exactly one character). For example, to specify a set of declarations for any host in the .Qq .co.uk set of domains, the following pattern could be used: .Pp .Dl Host *.co.uk .Pp The following pattern would match any host in the 192.168.0.[0-9] network range: .Pp .Dl Host 192.168.0.? .Pp A .Em pattern-list is a comma-separated list of patterns. Patterns within pattern-lists may be negated by preceding them with an exclamation mark .Pq Sq !\& . For example, to allow a key to be used from anywhere within an organization except from the .Qq dialup pool, the following entry (in authorized_keys) could be used: .Pp .Dl from=\&"!*.dialup.example.com,*.example.com\&" .Pp Note that a negated match will never produce a positive result by itself. For example, attempting to match .Qq host3 against the following pattern-list will fail: .Pp .Dl from=\&"!host1,!host2\&" .Pp The solution here is to include a term that will yield a positive match, such as a wildcard: .Pp .Dl from=\&"!host1,!host2,*\&" .Sh TOKENS Arguments to some keywords can make use of tokens, which are expanded at runtime: .Pp .Bl -tag -width XXXX -offset indent -compact .It %% A literal .Sq % . .It \&%C Hash of %l%h%p%r%j. .It %d Local user's home directory. .It %f The fingerprint of the server's host key. .It %H The .Pa known_hosts hostname or address that is being searched for. .It %h The remote hostname. .It \%%I A string describing the reason for a .Cm KnownHostsCommand execution: either .Cm ADDRESS when looking up a host by address (only when .Cm CheckHostIP is enabled), .Cm HOSTNAME when searching by hostname, or .Cm ORDER when preparing the host key algorithm preference list to use for the destination host. .It %i The local user ID. .It %j The contents of the ProxyJump option, or the empty string if this option is unset. .It %K The base64 encoded host key. .It %k The host key alias if specified, otherwise the original remote hostname given on the command line. .It %L The local hostname. .It %l The local hostname, including the domain name. .It %n The original remote hostname, as given on the command line. .It %p The remote port. .It %r The remote username. .It \&%T The local .Xr tun 4 or .Xr tap 4 network interface assigned if tunnel forwarding was requested, or .Qq NONE otherwise. .It %t The type of the server host key, e.g. .Cm ssh-ed25519 . .It %u The local username. .El .Pp .Cm CertificateFile , .Cm ControlPath , .Cm IdentityAgent , .Cm IdentityFile , .Cm Include , .Cm KnownHostsCommand , .Cm LocalForward , .Cm Match exec , .Cm RemoteCommand , .Cm RemoteForward , .Cm RevokedHostKeys , .Cm UserKnownHostsFile and .Cm VersionAddendum accept the tokens %%, %C, %d, %h, %i, %j, %k, %L, %l, %n, %p, %r, and %u. .Pp .Cm KnownHostsCommand additionally accepts the tokens %f, %H, %I, %K and %t. .Pp .Cm Hostname accepts the tokens %% and %h. .Pp .Cm LocalCommand accepts all tokens. .Pp .Cm ProxyCommand and .Cm ProxyJump accept the tokens %%, %h, %n, %p, and %r. .Pp Note that some of these directives build commands for execution via the shell. Because .Xr ssh 1 performs no filtering or escaping of characters that have special meaning in shell commands (e.g. quotes), it is the user's responsibility to ensure that the arguments passed to .Xr ssh 1 do not contain such characters and that tokens are appropriately quoted when used. .Sh ENVIRONMENT VARIABLES Arguments to some keywords can be expanded at runtime from environment variables on the client by enclosing them in .Ic ${} , for example .Ic ${HOME}/.ssh would refer to the user's .ssh directory. If a specified environment variable does not exist then an error will be returned and the setting for that keyword will be ignored. .Pp The keywords .Cm CertificateFile , .Cm ControlPath , .Cm IdentityAgent , .Cm IdentityFile , .Cm Include , .Cm KnownHostsCommand , and .Cm UserKnownHostsFile support environment variables. The keywords .Cm LocalForward and .Cm RemoteForward support environment variables only for Unix domain socket paths. .Sh FILES .Bl -tag -width Ds .It Pa ~/.ssh/config This is the per-user configuration file. The format of this file is described above. This file is used by the SSH client. Because of the potential for abuse, this file must have strict permissions: read/write for the user, and not writable by others. .It Pa /etc/ssh/ssh_config Systemwide configuration file. This file provides defaults for those values that are not specified in the user's configuration file, and for those users who do not have a configuration file. This file must be world-readable. .El .Sh SEE ALSO .Xr ssh 1 .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , .An Niels Provos , Theo de Raadt and .An Dug Song removed many bugs, re-added newer features and created OpenSSH. .An Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. openssh-10.0p1/PaxHeaders.10889/sshbuf-getput-basic.c100644 001750 001750 0000000003614775415623 0017177xustar0030 atime=1744182234.860179474 openssh-10.0p1/sshbuf-getput-basic.c010064400017500001750000000303401477541562300155620ustar00djmdjm/* $OpenBSD: sshbuf-getput-basic.c,v 1.13 2022/05/25 06:03:44 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. */ #define SSHBUF_INTERNAL #include "includes.h" #include #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include "ssherr.h" #include "sshbuf.h" int sshbuf_get(struct sshbuf *buf, void *v, size_t len) { const u_char *p = sshbuf_ptr(buf); int r; if ((r = sshbuf_consume(buf, len)) < 0) return r; if (v != NULL && len != 0) memcpy(v, p, len); return 0; } int sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp) { const u_char *p = sshbuf_ptr(buf); int r; if ((r = sshbuf_consume(buf, 8)) < 0) return r; if (valp != NULL) *valp = PEEK_U64(p); return 0; } int sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp) { const u_char *p = sshbuf_ptr(buf); int r; if ((r = sshbuf_consume(buf, 4)) < 0) return r; if (valp != NULL) *valp = PEEK_U32(p); return 0; } int sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp) { const u_char *p = sshbuf_ptr(buf); int r; if ((r = sshbuf_consume(buf, 2)) < 0) return r; if (valp != NULL) *valp = PEEK_U16(p); return 0; } int sshbuf_get_u8(struct sshbuf *buf, u_char *valp) { const u_char *p = sshbuf_ptr(buf); int r; if ((r = sshbuf_consume(buf, 1)) < 0) return r; if (valp != NULL) *valp = (u_int8_t)*p; 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) { const u_char *val; size_t len; int r; if (valp != NULL) *valp = NULL; if (lenp != NULL) *lenp = 0; if ((r = sshbuf_get_string_direct(buf, &val, &len)) < 0) return r; if (valp != NULL) { if ((*valp = malloc(len + 1)) == NULL) { SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); return SSH_ERR_ALLOC_FAIL; } if (len != 0) memcpy(*valp, val, len); (*valp)[len] = '\0'; } if (lenp != NULL) *lenp = len; return 0; } int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp) { size_t len; const u_char *p; int r; if (valp != NULL) *valp = NULL; if (lenp != NULL) *lenp = 0; if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0) return r; if (valp != NULL) *valp = p; if (lenp != NULL) *lenp = len; if (sshbuf_consume(buf, len + 4) != 0) { /* Shouldn't happen */ SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); SSHBUF_ABORT(); return SSH_ERR_INTERNAL_ERROR; } return 0; } int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, size_t *lenp) { u_int32_t len; const u_char *p = sshbuf_ptr(buf); if (valp != NULL) *valp = NULL; if (lenp != NULL) *lenp = 0; if (sshbuf_len(buf) < 4) { SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); return SSH_ERR_MESSAGE_INCOMPLETE; } len = PEEK_U32(p); if (len > SSHBUF_SIZE_MAX - 4) { SSHBUF_DBG(("SSH_ERR_STRING_TOO_LARGE")); return SSH_ERR_STRING_TOO_LARGE; } if (sshbuf_len(buf) - 4 < len) { SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); return SSH_ERR_MESSAGE_INCOMPLETE; } if (valp != NULL) *valp = p + 4; if (lenp != NULL) *lenp = len; return 0; } int sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp) { size_t len; const u_char *p, *z; int r; if (valp != NULL) *valp = NULL; if (lenp != NULL) *lenp = 0; if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) return r; /* Allow a \0 only at the end of the string */ if (len > 0 && (z = memchr(p , '\0', len)) != NULL && z < p + len - 1) { SSHBUF_DBG(("SSH_ERR_INVALID_FORMAT")); return SSH_ERR_INVALID_FORMAT; } if ((r = sshbuf_skip_string(buf)) != 0) return -1; if (valp != NULL) { if ((*valp = malloc(len + 1)) == NULL) { SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); return SSH_ERR_ALLOC_FAIL; } if (len != 0) memcpy(*valp, p, len); (*valp)[len] = '\0'; } if (lenp != NULL) *lenp = (size_t)len; return 0; } int sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v) { u_int32_t len; u_char *p; int r; /* * Use sshbuf_peek_string_direct() to figure out if there is * a complete string in 'buf' and copy the string directly * into 'v'. */ if ((r = sshbuf_peek_string_direct(buf, NULL, NULL)) != 0 || (r = sshbuf_get_u32(buf, &len)) != 0 || (r = sshbuf_reserve(v, len, &p)) != 0 || (r = sshbuf_get(buf, p, len)) != 0) return r; return 0; } int sshbuf_put(struct sshbuf *buf, const void *v, size_t len) { u_char *p; int r; if ((r = sshbuf_reserve(buf, len, &p)) < 0) return r; if (len != 0) memcpy(p, v, len); return 0; } int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v) { if (v == NULL) return 0; return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v)); } int sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) { va_list ap; int r; va_start(ap, fmt); r = sshbuf_putfv(buf, fmt, ap); va_end(ap); return r; } int sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap) { va_list ap2; int r, len; u_char *p; VA_COPY(ap2, ap); if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (len == 0) { r = 0; goto out; /* Nothing to do */ } va_end(ap2); 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) { r = SSH_ERR_INTERNAL_ERROR; goto out; /* Shouldn't happen */ } /* Consume terminating \0 */ if ((r = sshbuf_consume_end(buf, 1)) != 0) goto out; r = 0; out: va_end(ap2); return r; } int sshbuf_put_u64(struct sshbuf *buf, u_int64_t val) { u_char *p; int r; if ((r = sshbuf_reserve(buf, 8, &p)) < 0) return r; POKE_U64(p, val); return 0; } int sshbuf_put_u32(struct sshbuf *buf, u_int32_t val) { u_char *p; int r; if ((r = sshbuf_reserve(buf, 4, &p)) < 0) return r; POKE_U32(p, val); return 0; } int sshbuf_put_u16(struct sshbuf *buf, u_int16_t val) { u_char *p; int r; if ((r = sshbuf_reserve(buf, 2, &p)) < 0) return r; POKE_U16(p, val); return 0; } int sshbuf_put_u8(struct sshbuf *buf, u_char val) { u_char *p; int r; if ((r = sshbuf_reserve(buf, 1, &p)) < 0) return r; p[0] = 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) { u_char *d; int r; if (len > SSHBUF_SIZE_MAX - 4) { SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); return SSH_ERR_NO_BUFFER_SPACE; } if ((r = sshbuf_reserve(buf, len + 4, &d)) < 0) return r; POKE_U32(d, len); if (len != 0) memcpy(d + 4, v, len); return 0; } int sshbuf_put_cstring(struct sshbuf *buf, const char *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)); } int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp) { const u_char *p; size_t len; struct sshbuf *ret; int r; if (buf == NULL || bufp == NULL) return SSH_ERR_INVALID_ARGUMENT; *bufp = NULL; if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) return r; if ((ret = sshbuf_from(p, len)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_consume(buf, len + 4)) != 0 || /* Shouldn't happen */ (r = sshbuf_set_parent(ret, buf)) != 0) { sshbuf_free(ret); return r; } *bufp = ret; return 0; } int sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len) { u_char *d; const u_char *s = (const u_char *)v; int r, prepend; if (len > SSHBUF_SIZE_MAX - 5) { SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); return SSH_ERR_NO_BUFFER_SPACE; } /* Skip leading zero bytes */ for (; len > 0 && *s == 0; len--, s++) ; /* * If most significant bit is set then prepend a zero byte to * avoid interpretation as a negative number. */ prepend = len > 0 && (s[0] & 0x80) != 0; if ((r = sshbuf_reserve(buf, len + 4 + prepend, &d)) < 0) return r; POKE_U32(d, len + prepend); if (prepend) d[4] = 0; if (len != 0) memcpy(d + 4 + prepend, s, len); return 0; } int sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp) { const u_char *d; size_t len, olen; int r; if ((r = sshbuf_peek_string_direct(buf, &d, &olen)) < 0) return r; len = olen; /* Refuse negative (MSB set) bignums */ if ((len != 0 && (*d & 0x80) != 0)) return SSH_ERR_BIGNUM_IS_NEGATIVE; /* Refuse overlong bignums, allow prepended \0 to avoid MSB set */ if (len > SSHBUF_MAX_BIGNUM + 1 || (len == SSHBUF_MAX_BIGNUM + 1 && *d != 0)) return SSH_ERR_BIGNUM_TOO_LARGE; /* Trim leading zeros */ while (len > 0 && *d == 0x00) { d++; len--; } if (valp != NULL) *valp = d; if (lenp != NULL) *lenp = len; if (sshbuf_consume(buf, olen + 4) != 0) { /* Shouldn't happen */ SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); SSHBUF_ABORT(); return SSH_ERR_INTERNAL_ERROR; } return 0; } openssh-10.0p1/PaxHeaders.10889/sshbuf-getput-crypto.c100644 001750 001750 0000000003614775415623 0017436xustar0030 atime=1744182234.860179474 openssh-10.0p1/sshbuf-getput-crypto.c010064400017500001750000000112111477541562300160150ustar00djmdjm/* $OpenBSD: sshbuf-getput-crypto.c,v 1.12 2024/08/15 00:51:51 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. */ #define SSHBUF_INTERNAL #include "includes.h" #include #include #include #include #ifdef WITH_OPENSSL #include #ifdef OPENSSL_HAS_ECC # include #endif /* OPENSSL_HAS_ECC */ #include "ssherr.h" #include "sshbuf.h" int 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 (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; } #ifdef OPENSSL_HAS_ECC static int get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g) { /* Refuse overlong bignums */ if (len == 0 || len > SSHBUF_MAX_ECPOINT) return SSH_ERR_ECPOINT_TOO_LARGE; /* Only handle uncompressed points */ if (*d != POINT_CONVERSION_UNCOMPRESSED) return SSH_ERR_INVALID_FORMAT; if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1) return SSH_ERR_INVALID_FORMAT; /* XXX assumption */ return 0; } int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g) { const u_char *d; size_t len; int r; if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) return r; if ((r = get_ec(d, len, v, g)) != 0) return r; /* Skip string */ if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { /* Shouldn't happen */ SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); SSHBUF_ABORT(); return SSH_ERR_INTERNAL_ERROR; } return 0; } int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v) { EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v)); int r; const u_char *d; size_t len; if (pt == NULL) { SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); return SSH_ERR_ALLOC_FAIL; } if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) { EC_POINT_free(pt); return r; } if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) { EC_POINT_free(pt); return r; } if (EC_KEY_set_public_key(v, pt) != 1) { EC_POINT_free(pt); return SSH_ERR_ALLOC_FAIL; /* XXX assumption */ } EC_POINT_free(pt); /* Skip string */ if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { /* Shouldn't happen */ SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); SSHBUF_ABORT(); return SSH_ERR_INTERNAL_ERROR; } return 0; } #endif /* OPENSSL_HAS_ECC */ int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v) { u_char d[SSHBUF_MAX_BIGNUM + 1]; int len = BN_num_bytes(v), prepend = 0, r; if (len < 0 || len > SSHBUF_MAX_BIGNUM) return SSH_ERR_INVALID_ARGUMENT; *d = '\0'; if (BN_bn2bin(v, d + 1) != len) return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ /* If MSB is set, prepend a \0 */ if (len > 0 && (d[1] & 0x80) != 0) prepend = 1; if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) { explicit_bzero(d, sizeof(d)); return r; } explicit_bzero(d, sizeof(d)); return 0; } #ifdef OPENSSL_HAS_ECC int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g) { u_char d[SSHBUF_MAX_ECPOINT]; size_t len; int ret; if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) > SSHBUF_MAX_ECPOINT) { return SSH_ERR_INVALID_ARGUMENT; } if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, d, len, NULL) != len) { return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ } ret = sshbuf_put_string(buf, d, len); explicit_bzero(d, len); return ret; } int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v) { return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v), EC_KEY_get0_group(v)); } int sshbuf_put_ec_pkey(struct sshbuf *buf, EVP_PKEY *pkey) { const EC_KEY *ec; if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) return SSH_ERR_LIBCRYPTO_ERROR; return sshbuf_put_eckey(buf, ec); } #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ openssh-10.0p1/PaxHeaders.10889/sshbuf-io.c100644 001750 001750 0000000003614775415623 0015217xustar0030 atime=1744182234.860179474 openssh-10.0p1/sshbuf-io.c010064400017500001750000000053711477541562300136100ustar00djmdjm/* $OpenBSD: sshbuf-io.c,v 1.2 2020/01/25 23:28:06 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include "ssherr.h" #include "sshbuf.h" #include "atomicio.h" /* Load a file from a fd into a buffer */ int sshbuf_load_fd(int fd, struct sshbuf **blobp) { u_char buf[4096]; size_t len; struct stat st; int r; struct sshbuf *blob; *blobp = NULL; if (fstat(fd, &st) == -1) return SSH_ERR_SYSTEM_ERROR; if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && st.st_size > SSHBUF_SIZE_MAX) return SSH_ERR_INVALID_FORMAT; if ((blob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; for (;;) { if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { if (errno == EPIPE) break; r = SSH_ERR_SYSTEM_ERROR; goto out; } if ((r = sshbuf_put(blob, buf, len)) != 0) goto out; if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) { r = SSH_ERR_INVALID_FORMAT; goto out; } } if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && st.st_size != (off_t)sshbuf_len(blob)) { r = SSH_ERR_FILE_CHANGED; goto out; } /* success */ *blobp = blob; blob = NULL; /* transferred */ r = 0; out: explicit_bzero(buf, sizeof(buf)); sshbuf_free(blob); return r; } int sshbuf_load_file(const char *path, struct sshbuf **bufp) { int r, fd, oerrno; *bufp = NULL; if ((fd = open(path, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; if ((r = sshbuf_load_fd(fd, bufp)) != 0) goto out; /* success */ r = 0; out: oerrno = errno; close(fd); if (r != 0) errno = oerrno; return r; } int sshbuf_write_file(const char *path, struct sshbuf *buf) { int fd, oerrno; if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) return SSH_ERR_SYSTEM_ERROR; if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf), sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) { oerrno = errno; close(fd); unlink(path); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } return 0; } openssh-10.0p1/PaxHeaders.10889/sshd.0100644 001750 001750 0000000003614775415623 0014176xustar0030 atime=1744182234.867015294 openssh-10.0p1/sshd.0010064400017500001750000001050751477541562300125710ustar00djmdjmSSHD(8) System Manager's Manual SSHD(8) NAME sshd M-bM-^@M-^S OpenSSH daemon SYNOPSIS sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_certificate_file] [-E log_file] [-f config_file] [-g login_grace_time] [-h host_key_file] [-o option] [-p port] [-u len] DESCRIPTION sshd (OpenSSH Daemon) is the daemon program for ssh(1). It provides 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. -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 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 -C options or as a comma-separated list. The keywords are M-bM-^@M-^\addrM-bM-^@M-^], 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-^\rdomainM-bM-^@M-^] and correspond to source address, user, resolved source host name, local address, local port number and routing domain respectively. Additionally the M-bM-^@M-^\invalid-userM-bM-^@M-^] flag (which does not take a value argument) may be specified to simulate a connection from an unrecognised username. -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(2) 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 Parse and print configuration file. 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. -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_ecdsa_key, /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key. It is possible to have multiple host key files for the different host key algorithms. -i Specifies that sshd is being run from inetd(8). -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. This is similar to the -G flag, but it includes the additional testing performed by the -t flag. -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 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. -V Display the version number and exit. AUTHENTICATION The OpenSSH SSH daemon supports SSH protocol 2 only. Each host has a host-specific key, used to identify the host. Whenever a client connects, the daemon responds with its public host key. The client compares the host key against its own database to verify that it has not changed. Forward 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. 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 (MAC). 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 dependent. 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 an interactive shell or execution of a non-interactive command, which sshd will execute via the user's shell using its -c option. The sides then enter session mode. In this mode, either side may send data at any time, and such data is forwarded to/from the shell or 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(1). 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. All commands are run under the user's login shell as specified in the system password database. 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 this option is not 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). Public keys consist of the following space- separated fields: options, keytype, base64-encoded key, comment. The options field is optional. The supported key types are: sk-ecdsa-sha2-nistp256@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 sk-ssh-ed25519@openssh.com ssh-ed25519 ssh-rsa The comment field is not used for anything (but may be convenient for the user to identify the key). 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 RSA keys up to 16 kilobits. You don't want to type them in; instead, copy the id_ecdsa.pub, id_ecdsa_sk.pub, id_ed25519.pub, id_ed25519_sk.pub, or the id_rsa.pub file and edit it. sshd enforces a minimum RSA key modulus size of 1024 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): agent-forwarding Enable authentication agent forwarding previously disabled by the restrict option. 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, e.g. using the restrict key option. The command originally supplied by the client is available in the SSH_ORIGINAL_COMMAND environment variable. Note that this option applies to shell, command or subsystem execution. Also note that this command may be superseded by a sshd_config(5) ForceCommand directive. 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. 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. expiry-time="timespec" Specifies a time after which the key will not be accepted. The time may be specified as a YYYYMMDD[Z] date or a YYYYMMDDHHMM[SS][Z] time. Dates and times will be interpreted in the system time zone unless suffixed by a Z character, in which case they will be interpreted in the UTC time zone. 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. permitlisten="[host:]port" Limit remote port forwarding with the ssh(1) -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 permitlisten options may be applied separated by commas. Hostnames may include wildcards as described in the PATTERNS section in ssh_config(5). A port specification of * matches any port. Note that the setting of GatewayPorts may further restrict listen addresses. Note that ssh(1) will send a hostname of M-bM-^@M-^\localhostM-bM-^@M-^] if a listen host was not specified when the forwarding was requested, and that this name is treated differently to the explicit localhost addresses M-bM-^@M-^\127.0.0.1M-bM-^@M-^] and M-bM-^@M-^\::1M-bM-^@M-^]. permitopen="host:port" Limit local port forwarding with the ssh(1) -L 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 permitopen options may be applied separated by commas. 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 * matches any port. port-forwarding Enable port forwarding previously disabled by the restrict option. 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. pty Permits tty allocation previously disabled by the restrict option. 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 ecdsa-sk and ed25519-sk. verify-required Require that signatures made using this key attest that they verified the user, e.g. via a PIN. This option only makes sense for the FIDO authenticator algorithms ecdsa-sk and ed25519-sk. restrict Enable all restrictions, i.e. disable port, agent and X11 forwarding, as well as disabling PTY allocation and execution of ~/.ssh/rc. If any future restriction capabilities are added to authorized_keys files, they will be included in this set. 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. user-rc Enables execution of ~/.ssh/rc previously disabled by the restrict option. X11-forwarding Permits X11 forwarding previously disabled by the restrict option. An example authorized_keys file: # Comments are allowed at start of line. Blank lines are allowed. # Plain key, no restrictions ssh-rsa ... # Forced command, disable PTY and all forwarding restrict,command="dump /home" ssh-rsa ... # Restriction of ssh -L forwarding destinations permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-rsa ... # Restriction of ssh -R forwarding listeners permitlisten="localhost:8080",permitlisten="[::1]:22000" ssh-rsa ... # Configuration for tunnel forwarding tunnel="0",command="sh /etc/netstart tun0" ssh-rsa ... # Override of restriction to allow PTY allocation restrict,pty,command="nethack" ssh-rsa ... # Allow FIDO key without requiring touch no-touch-required sk-ecdsa-sha2-nistp256@openssh.com ... # Require user-verification (e.g. PIN or biometric) for FIDO key verify-required sk-ecdsa-sha2-nistp256@openssh.com ... # Trust CA key, allow touch-less FIDO if requested in certificate cert-authority,no-touch-required,principals="user_a" ssh-rsa ... 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 to an unknown host, its key is added to the per-user file. Each line in these files contains the following fields: marker (optional), hostnames, keytype, base64-encoded key, 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 host name. When sshd is authenticating a client, such as when using HostbasedAuthentication, this will be the canonical client host name. When ssh(1) is authenticating a server, this will be the host name given by the user, the value of the ssh(1) HostkeyAlias if it was specified, or the canonical server hostname if the ssh(1) CanonicalizeHostname option was used. 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. The keytype and base64-encoded key are taken directly from the host key; they can be obtained, for example, from /etc/ssh/ssh_host_rsa_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, for example, /etc/ssh/ssh_host_rsa_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 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 (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" key exchange method. The file format is described in moduli(5). If no usable groups are found in this file then fixed internal groups will be used. /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_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_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 7.6 September 15, 2024 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/sshbuf-misc.c100644 001750 001750 0000000003614775415623 0015543xustar0030 atime=1744182234.860179474 openssh-10.0p1/sshbuf-misc.c010064400017500001750000000160141477541562300141300ustar00djmdjm/* $OpenBSD: sshbuf-misc.c,v 1.18 2022/01/22 00:43:43 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #include #include "ssherr.h" #define SSHBUF_INTERNAL #include "sshbuf.h" void sshbuf_dump_data(const void *s, size_t len, FILE *f) { size_t i, j; const u_char *p = (const u_char *)s; for (i = 0; i < len; i += 16) { fprintf(f, "%.4zu: ", i); for (j = i; j < i + 16; j++) { if (j < len) fprintf(f, "%02x ", p[j]); else fprintf(f, " "); } fprintf(f, " "); for (j = i; j < i + 16; j++) { if (j < len) { if (isascii(p[j]) && isprint(p[j])) fprintf(f, "%c", p[j]); else fprintf(f, "."); } } fprintf(f, "\n"); } } void sshbuf_dump(const struct sshbuf *buf, FILE *f) { fprintf(f, "buffer len = %zu\n", sshbuf_len(buf)); sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f); } char * sshbuf_dtob16(struct sshbuf *buf) { size_t i, j, len = sshbuf_len(buf); const u_char *p = sshbuf_ptr(buf); char *ret; const char hex[] = "0123456789abcdef"; if (len == 0) return strdup(""); if (SIZE_MAX / 2 <= len || (ret = malloc(len * 2 + 1)) == NULL) return NULL; for (i = j = 0; i < len; i++) { ret[j++] = hex[(p[i] >> 4) & 0xf]; ret[j++] = hex[p[i] & 0xf]; } ret[j] = '\0'; 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_string(const struct sshbuf *buf, int wrap) { struct sshbuf *tmp; char *ret; if ((tmp = sshbuf_new()) == NULL) return NULL; if (sshbuf_dtob64(buf, tmp, wrap) != 0) { sshbuf_free(tmp); return NULL; } ret = sshbuf_dup_string(tmp); sshbuf_free(tmp); return ret; } int sshbuf_b64tod(struct sshbuf *buf, const char *b64) { size_t plen = strlen(b64); int nlen, r; u_char *p; if (plen == 0) return 0; if ((p = malloc(plen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((nlen = b64_pton(b64, p, plen)) < 0) { freezero(p, plen); return SSH_ERR_INVALID_FORMAT; } if ((r = sshbuf_put(buf, p, nlen)) < 0) { freezero(p, plen); return r; } freezero(p, plen); return 0; } int sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap) { int r = SSH_ERR_INTERNAL_ERROR; u_char *p; struct sshbuf *b = NULL; size_t i, l; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* Encode using regular base64; we'll transform it once done */ if ((r = sshbuf_dtob64(d, b, wrap)) != 0) goto out; /* remove padding from end of encoded string*/ for (;;) { l = sshbuf_len(b); if (l <= 1 || sshbuf_ptr(b) == NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if (sshbuf_ptr(b)[l - 1] != '=') break; if ((r = sshbuf_consume_end(b, 1)) != 0) goto out; } /* Replace characters with rfc4648 equivalents */ l = sshbuf_len(b); if ((p = sshbuf_mutable_ptr(b)) == NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } for (i = 0; i < l; i++) { if (p[i] == '+') p[i] = '-'; else if (p[i] == '/') p[i] = '_'; } r = sshbuf_putb(b64, b); out: sshbuf_free(b); return r; } char * sshbuf_dup_string(struct sshbuf *buf) { 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; } int sshbuf_read(int fd, struct sshbuf *buf, size_t maxlen, size_t *rlen) { int r, oerrno; size_t adjust; ssize_t rr; u_char *d; if (rlen != NULL) *rlen = 0; if ((r = sshbuf_reserve(buf, maxlen, &d)) != 0) return r; rr = read(fd, d, maxlen); oerrno = errno; /* Adjust the buffer to include only what was actually read */ if ((adjust = maxlen - (rr > 0 ? rr : 0)) != 0) { if ((r = sshbuf_consume_end(buf, adjust)) != 0) { /* avoid returning uninitialised data to caller */ memset(d + rr, '\0', adjust); return SSH_ERR_INTERNAL_ERROR; /* shouldn't happen */ } } if (rr < 0) { errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } else if (rr == 0) { errno = EPIPE; return SSH_ERR_SYSTEM_ERROR; } /* success */ if (rlen != NULL) *rlen = (size_t)rr; return 0; } openssh-10.0p1/PaxHeaders.10889/sshbuf.c100644 001750 001750 0000000003614775415623 0014612xustar0030 atime=1744182234.860179474 openssh-10.0p1/sshbuf.c010064400017500001750000000235011477541562300131760ustar00djmdjm/* $OpenBSD: sshbuf.c,v 1.23 2024/08/14 15:42:18 tobias Exp $ */ /* * Copyright (c) 2011 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include "ssherr.h" #define SSHBUF_INTERNAL #include "sshbuf.h" #include "misc.h" #ifdef SSHBUF_DEBUG # define SSHBUF_TELL(what) do { \ printf("%s:%d %s: %s size %zu alloc %zu off %zu max %zu\n", \ __FILE__, __LINE__, __func__, what, \ buf->size, buf->alloc, buf->off, buf->max_size); \ fflush(stdout); \ } while (0) #else # define SSHBUF_TELL(what) #endif struct sshbuf { u_char *d; /* Data */ const u_char *cd; /* Const data */ size_t off; /* First available byte is buf->d + buf->off */ size_t size; /* Last byte is buf->d + buf->size - 1 */ size_t max_size; /* Maximum size of buffer */ size_t alloc; /* Total bytes allocated to buf->d */ int readonly; /* Refers to external, const data */ u_int refcount; /* Tracks self and number of child buffers */ struct sshbuf *parent; /* If child, pointer to parent */ }; static inline int sshbuf_check_sanity(const struct sshbuf *buf) { SSHBUF_TELL("sanity"); if (__predict_false(buf == NULL || (!buf->readonly && buf->d != buf->cd) || buf->parent == buf || buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX || buf->cd == 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")); ssh_signal(SIGSEGV, SIG_DFL); raise(SIGSEGV); return SSH_ERR_INTERNAL_ERROR; } return 0; } static void sshbuf_maybe_pack(struct sshbuf *buf, int force) { SSHBUF_DBG(("force %d", force)); SSHBUF_TELL("pre-pack"); if (buf->off == 0 || buf->readonly || buf->refcount > 1) return; if (force || (buf->off >= SSHBUF_PACK_MIN && buf->off >= buf->size / 2)) { memmove(buf->d, buf->d + buf->off, buf->size - buf->off); buf->size -= buf->off; buf->off = 0; SSHBUF_TELL("packed"); } } struct sshbuf * sshbuf_new(void) { struct sshbuf *ret; if ((ret = calloc(1, sizeof(*ret))) == NULL) return NULL; ret->alloc = SSHBUF_SIZE_INIT; ret->max_size = SSHBUF_SIZE_MAX; ret->readonly = 0; ret->refcount = 1; ret->parent = NULL; if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) { free(ret); return NULL; } return ret; } struct sshbuf * sshbuf_from(const void *blob, size_t len) { struct sshbuf *ret; if (blob == NULL || len > SSHBUF_SIZE_MAX || (ret = calloc(1, sizeof(*ret))) == NULL) return NULL; ret->alloc = ret->size = ret->max_size = len; ret->readonly = 1; ret->refcount = 1; ret->parent = NULL; ret->cd = blob; ret->d = NULL; return ret; } int sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent) { int r; if ((r = sshbuf_check_sanity(child)) != 0 || (r = sshbuf_check_sanity(parent)) != 0) return r; if ((child->parent != NULL && child->parent != parent) || child == parent) return SSH_ERR_INTERNAL_ERROR; child->parent = parent; child->parent->refcount++; return 0; } struct sshbuf * sshbuf_fromb(struct sshbuf *buf) { struct sshbuf *ret; if (sshbuf_check_sanity(buf) != 0) return NULL; if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL) return NULL; if (sshbuf_set_parent(ret, buf) != 0) { sshbuf_free(ret); return NULL; } return ret; } void sshbuf_free(struct sshbuf *buf) { if (buf == NULL) return; /* * The following will leak on insane buffers, but this is the safest * course of action - an invalid pointer or already-freed pointer may * have been passed to us and continuing to scribble over memory would * be bad. */ if (sshbuf_check_sanity(buf) != 0) return; /* * 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 * refcount to 0 and trigger the actual free. */ buf->refcount--; if (buf->refcount > 0) return; /* * If we are a child, then free our parent to decrement its reference * count and possibly free it. */ sshbuf_free(buf->parent); buf->parent = NULL; if (!buf->readonly) freezero(buf->d, buf->alloc); freezero(buf, sizeof(*buf)); } void sshbuf_reset(struct sshbuf *buf) { u_char *d; if (buf->readonly || buf->refcount > 1) { /* Nonsensical. Just make buffer appear empty */ buf->off = buf->size; return; } if (sshbuf_check_sanity(buf) != 0) return; buf->off = buf->size = 0; if (buf->alloc != SSHBUF_SIZE_INIT) { 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, buf->alloc); } size_t sshbuf_max_size(const struct sshbuf *buf) { return buf->max_size; } size_t sshbuf_alloc(const struct sshbuf *buf) { return buf->alloc; } const struct sshbuf * sshbuf_parent(const struct sshbuf *buf) { return buf->parent; } u_int sshbuf_refcount(const struct sshbuf *buf) { return buf->refcount; } int sshbuf_set_max_size(struct sshbuf *buf, size_t max_size) { size_t rlen; u_char *dp; int r; SSHBUF_DBG(("set max buf = %p len = %zu", buf, max_size)); if ((r = sshbuf_check_sanity(buf)) != 0) return r; if (max_size == buf->max_size) return 0; if (buf->readonly || buf->refcount > 1) return SSH_ERR_BUFFER_READ_ONLY; if (max_size > SSHBUF_SIZE_MAX) return SSH_ERR_NO_BUFFER_SPACE; /* pack and realloc if necessary */ sshbuf_maybe_pack(buf, max_size < buf->size); if (max_size < buf->alloc && max_size > buf->size) { if (buf->size < SSHBUF_SIZE_INIT) rlen = SSHBUF_SIZE_INIT; else rlen = ROUNDUP(buf->size, SSHBUF_SIZE_INC); if (rlen > max_size) rlen = max_size; SSHBUF_DBG(("new alloc = %zu", rlen)); if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL) return SSH_ERR_ALLOC_FAIL; buf->cd = buf->d = dp; buf->alloc = rlen; } SSHBUF_TELL("new-max"); if (max_size < buf->alloc) return SSH_ERR_NO_BUFFER_SPACE; buf->max_size = max_size; return 0; } size_t sshbuf_len(const struct sshbuf *buf) { if (sshbuf_check_sanity(buf) != 0) return 0; return buf->size - buf->off; } size_t sshbuf_avail(const struct sshbuf *buf) { if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) return 0; return buf->max_size - (buf->size - buf->off); } const u_char * sshbuf_ptr(const struct sshbuf *buf) { if (sshbuf_check_sanity(buf) != 0) return NULL; return buf->cd + buf->off; } u_char * sshbuf_mutable_ptr(const struct sshbuf *buf) { if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) return NULL; return buf->d + buf->off; } int sshbuf_check_reserve(const struct sshbuf *buf, size_t len) { int r; if ((r = sshbuf_check_sanity(buf)) != 0) return r; if (buf->readonly || buf->refcount > 1) return SSH_ERR_BUFFER_READ_ONLY; SSHBUF_TELL("check"); /* Check that len is reasonable and that max_size + available < len */ if (len > buf->max_size || buf->max_size - len < buf->size - buf->off) return SSH_ERR_NO_BUFFER_SPACE; return 0; } int sshbuf_allocate(struct sshbuf *buf, size_t len) { size_t rlen, need; u_char *dp; int r; SSHBUF_DBG(("allocate buf = %p len = %zu", buf, len)); if ((r = sshbuf_check_reserve(buf, len)) != 0) return r; /* * If the requested allocation appended would push us past max_size * then pack the buffer, zeroing buf->off. */ sshbuf_maybe_pack(buf, buf->size + len > buf->max_size); 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; if (dpp != NULL) *dpp = dp; return 0; } int sshbuf_consume(struct sshbuf *buf, size_t len) { int r; SSHBUF_DBG(("len = %zu", len)); if ((r = sshbuf_check_sanity(buf)) != 0) return r; if (len == 0) return 0; 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; } int sshbuf_consume_end(struct sshbuf *buf, size_t len) { int r; SSHBUF_DBG(("len = %zu", len)); if ((r = sshbuf_check_sanity(buf)) != 0) return r; if (len == 0) return 0; if (len > sshbuf_len(buf)) return SSH_ERR_MESSAGE_INCOMPLETE; buf->size -= len; SSHBUF_TELL("done"); return 0; } openssh-10.0p1/PaxHeaders.10889/sshbuf.h100644 001750 001750 0000000003614775415623 0014617xustar0030 atime=1744182234.860179474 openssh-10.0p1/sshbuf.h010064400017500001750000000331141477541562300132040ustar00djmdjm/* $OpenBSD: sshbuf.h,v 1.29 2024/08/15 00:51:51 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. */ #ifndef _SSHBUF_H #define _SSHBUF_H #include #include #include #ifdef WITH_OPENSSL # include # include # ifdef OPENSSL_HAS_ECC # include # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ #define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */ #define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */ #define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */ #define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */ struct sshbuf; /* * Create a new sshbuf buffer. * Returns pointer to buffer on success, or NULL on allocation failure. */ struct sshbuf *sshbuf_new(void); /* * Create a new, read-only sshbuf buffer from existing data. * Returns pointer to buffer on success, or NULL on allocation failure. */ struct sshbuf *sshbuf_from(const void *blob, size_t len); /* * Create a new, read-only sshbuf buffer from the contents of an existing * buffer. The contents of "buf" must not change in the lifetime of the * resultant buffer. * Returns pointer to buffer on success, or NULL on allocation failure. */ struct sshbuf *sshbuf_fromb(struct sshbuf *buf); /* * Create a new, read-only sshbuf buffer from the contents of a string in * an existing buffer (the string is consumed in the process). * The contents of "buf" must not change in the lifetime of the resultant * buffer. * Returns pointer to buffer on success, or NULL on allocation failure. */ int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp); /* * Clear and free buf */ void sshbuf_free(struct sshbuf *buf); /* * Reset buf, clearing its contents. NB. max_size is preserved. */ void sshbuf_reset(struct sshbuf *buf); /* * Return the maximum size of buf */ size_t sshbuf_max_size(const struct sshbuf *buf); /* * Set the maximum size of buf * Returns 0 on success, or a negative SSH_ERR_* error code on failure. */ int sshbuf_set_max_size(struct sshbuf *buf, size_t max_size); /* * Returns the length of data in buf */ size_t sshbuf_len(const struct sshbuf *buf); /* * Returns number of bytes left in buffer before hitting max_size. */ size_t sshbuf_avail(const struct sshbuf *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 data in buf, or * NULL if the buffer is read-only. */ u_char *sshbuf_mutable_ptr(const struct sshbuf *buf); /* * Check whether a reservation of size len will succeed in buf * Safer to use than direct comparisons again sshbuf_avail as it copes * with unsigned overflows correctly. * Returns 0 on success, or a negative SSH_ERR_* error code on failure. */ 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. */ int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp); /* * Consume len bytes from the start of buf * Returns 0 on success, or a negative SSH_ERR_* error code on failure. */ int sshbuf_consume(struct sshbuf *buf, size_t len); /* * Consume len bytes from the end of buf * Returns 0 on success, or a negative SSH_ERR_* error code on failure. */ int sshbuf_consume_end(struct sshbuf *buf, size_t len); /* Extract or deposit some bytes */ int sshbuf_get(struct sshbuf *buf, void *v, size_t len); int sshbuf_put(struct sshbuf *buf, const void *v, size_t len); int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v); /* Append using a printf(3) format */ int sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) __attribute__((format(printf, 2, 3))); int sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap); /* Functions to extract or store big-endian words of various sizes */ int sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp); int sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp); int sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp); int sshbuf_get_u8(struct sshbuf *buf, u_char *valp); int sshbuf_put_u64(struct sshbuf *buf, u_int64_t val); 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. * Caller must free *valp. */ int sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp); int sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp); int sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v); int sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len); int sshbuf_put_cstring(struct sshbuf *buf, const char *v); int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v); /* * "Direct" variant of sshbuf_get_string, returns pointer into the sshbuf to * avoid an malloc+memcpy. The pointer is guaranteed to be valid until the * next sshbuf-modifying function call. Caller does not free. */ int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp); /* Skip past a string */ #define sshbuf_skip_string(buf) sshbuf_get_string_direct(buf, NULL, NULL) /* Another variant: "peeks" into the buffer without modifying it */ int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, size_t *lenp); /* * Functions to extract or store SSH wire encoded bignums and elliptic * curve points. */ 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 **valp); int sshbuf_put_bignum2(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); int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g); int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v); int sshbuf_put_ec_pkey(struct sshbuf *buf, EVP_PKEY *pkey); # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ /* Dump the contents of the buffer in a human-readable format */ void sshbuf_dump(const struct sshbuf *buf, FILE *f); /* Dump specified memory in a human-readable format */ void sshbuf_dump_data(const void *s, size_t len, FILE *f); /* Return the hexadecimal representation of the contents of the buffer */ char *sshbuf_dtob16(struct sshbuf *buf); /* Encode the contents of the buffer as base64 */ char *sshbuf_dtob64_string(const struct sshbuf *buf, int wrap); int sshbuf_dtob64(const struct sshbuf *d, struct sshbuf *b64, int wrap); /* RFC4648 "base64url" encoding variant */ int sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap); /* Decode base64 data and append it to the buffer */ int sshbuf_b64tod(struct sshbuf *buf, const char *b64); /* * 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))); /* Read up to maxlen bytes from a fd directly to a buffer */ int sshbuf_read(int, struct sshbuf *, size_t, size_t *) __attribute__((__nonnull__ (2))); /* Macros for decoding/encoding integers */ #define PEEK_U64(p) \ (((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)(((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)(((const u_char *)(p))[0]) << 8) | \ (u_int16_t)(((const u_char *)(p))[1])) #define POKE_U64(p, v) \ do { \ 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 { \ 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 { \ 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 */ #ifdef SSHBUF_INTERNAL /* * Return the allocation size of buf */ size_t sshbuf_alloc(const struct sshbuf *buf); /* * Increment the reference count of buf. */ int sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent); /* * Return the parent buffer of buf, or NULL if it has no parent. */ const struct sshbuf *sshbuf_parent(const struct sshbuf *buf); /* * Return the reference count of buf */ u_int sshbuf_refcount(const struct sshbuf *buf); # define SSHBUF_SIZE_INIT 256 /* Initial allocation */ # define SSHBUF_SIZE_INC 256 /* Preferred increment length */ # define SSHBUF_PACK_MIN 8192 /* Minimum packable offset */ /* # define SSHBUF_ABORT abort */ /* # define SSHBUF_DEBUG */ # ifndef SSHBUF_ABORT # define SSHBUF_ABORT() # endif # ifdef SSHBUF_DEBUG # define SSHBUF_DBG(x) do { \ printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ printf x; \ printf("\n"); \ fflush(stdout); \ } while (0) # else # define SSHBUF_DBG(x) # endif #endif /* SSHBUF_INTERNAL */ #endif /* _SSHBUF_H */ openssh-10.0p1/PaxHeaders.10889/sshconnect.c100644 001750 001750 0000000003614775415623 0015467xustar0030 atime=1744182234.862134512 openssh-10.0p1/sshconnect.c010064400017500001750000001437461477541562300140710ustar00djmdjm/* $OpenBSD: sshconnect.c,v 1.369 2024/12/06 16:21:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Code to connect to a remote host, and to perform the client side of the * login (authentication) dialog. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #ifdef HAVE_IFADDRS_H # include #endif #include "xmalloc.h" #include "hostfile.h" #include "ssh.h" #include "sshbuf.h" #include "packet.h" #include "sshkey.h" #include "sshconnect.h" #include "log.h" #include "match.h" #include "misc.h" #include "readconf.h" #include "atomicio.h" #include "dns.h" #include "monitor_fdpass.h" #include "ssh2.h" #include "version.h" #include "authfile.h" #include "ssherr.h" #include "authfd.h" #include "kex.h" struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; static pid_t proxy_command_pid = 0; /* import */ extern int debug_flag; extern Options options; extern char *__progname; static int show_other_keys(struct hostkeys *, struct sshkey *); static void warn_changed_key(struct sshkey *); /* Expand a proxy command */ static char * expand_proxy_command(const char *proxy_command, const char *user, const char *host, const char *host_arg, int port) { char *tmp, *ret, strport[NI_MAXSERV]; const char *keyalias = options.host_key_alias ? options.host_key_alias : host_arg; snprintf(strport, sizeof strport, "%d", port); xasprintf(&tmp, "exec %s", proxy_command); ret = percent_expand(tmp, "h", host, "k", keyalias, "n", host_arg, "p", strport, "r", options.user, (char *)NULL); free(tmp); return ret; } /* * Connect to the given ssh server using a proxy command that passes a * a connected fd back to us. */ static int ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, const char *host_arg, u_short port, const char *proxy_command) { char *command_string; int sp[2], sock; pid_t pid; char *shell; if ((shell = getenv("SHELL")) == NULL) shell = _PATH_BSHELL; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1) fatal("Could not create socketpair to communicate with " "proxy dialer: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, host, host_arg, port); debug("Executing proxy dialer command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; close(sp[1]); /* Redirect stdin and stdout. */ if (sp[0] != 0) { if (dup2(sp[0], 0) == -1) perror("dup2 stdin"); } if (sp[0] != 1) { if (dup2(sp[0], 1) == -1) perror("dup2 stdout"); } if (sp[0] >= 2) close(sp[0]); /* * Stderr is left for non-ControlPersist connections is so * error messages may be printed on the user's terminal. */ if (!debug_flag && options.control_path != NULL && options.control_persist && stdfd_devnull(0, 0, 1) == -1) error_f("stdfd_devnull failed"); argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* * Execute the proxy command. * Note that we gave up any extra privileges above. */ execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid == -1) fatal("fork failed: %.100s", strerror(errno)); close(sp[0]); free(command_string); if ((sock = mm_receive_fd(sp[1])) == -1) fatal("proxy dialer did not pass back a connection"); close(sp[1]); while (waitpid(pid, NULL, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for child: %s", strerror(errno)); /* Set the connection file descriptors. */ if (ssh_packet_set_connection(ssh, sock, sock) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } /* * Connect to the given ssh server using a proxy command. */ static int ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg, u_short port, const char *proxy_command) { char *command_string; int pin[2], pout[2]; pid_t pid; char *shell; if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; /* Create pipes for communicating with the proxy. */ if (pipe(pin) == -1 || pipe(pout) == -1) fatal("Could not create pipes to communicate with the proxy: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, host, host_arg, port); debug("Executing proxy command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; /* Redirect stdin and stdout. */ close(pin[1]); if (pin[0] != 0) { if (dup2(pin[0], 0) == -1) perror("dup2 stdin"); close(pin[0]); } close(pout[0]); if (dup2(pout[1], 1) == -1) perror("dup2 stdout"); /* Cannot be 1 because pin allocated two descriptors. */ close(pout[1]); /* * Stderr is left for non-ControlPersist connections is so * error messages may be printed on the user's terminal. */ if (!debug_flag && options.control_path != NULL && options.control_persist && stdfd_devnull(0, 0, 1) == -1) error_f("stdfd_devnull failed"); argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* * Execute the proxy command. Note that we gave up any * extra privileges above. */ ssh_signal(SIGPIPE, SIG_DFL); execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid == -1) fatal("fork failed: %.100s", strerror(errno)); else proxy_command_pid = pid; /* save pid to clean up later */ /* Close child side of the descriptors. */ close(pin[0]); close(pout[1]); /* Free the command name. */ free(command_string); /* Set the connection file descriptors. */ if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } void ssh_kill_proxy_command(void) { /* * Send SIGHUP to proxy command if used. We don't wait() in * case it hangs and instead rely on init to reap the child */ if (proxy_command_pid > 1) kill(proxy_command_pid, SIGHUP); } #ifdef HAVE_IFADDRS_H /* * Search a interface address list (returned from getifaddrs(3)) for an * address that matches the desired address family on the specified interface. * Returns 0 and fills in *resultp and *rlenp on success. Returns -1 on failure. */ static int check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs, struct sockaddr_storage *resultp, socklen_t *rlenp) { struct sockaddr_in6 *sa6; struct sockaddr_in *sa; struct in6_addr *v6addr; const struct ifaddrs *ifa; int allow_local; /* * Prefer addresses that are not loopback or linklocal, but use them * if nothing else matches. */ for (allow_local = 0; allow_local < 2; allow_local++) { for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0 || ifa->ifa_addr->sa_family != af || strcmp(ifa->ifa_name, options.bind_interface) != 0) continue; switch (ifa->ifa_addr->sa_family) { case AF_INET: sa = (struct sockaddr_in *)ifa->ifa_addr; if (!allow_local && sa->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) continue; if (*rlenp < sizeof(struct sockaddr_in)) { error_f("v4 addr doesn't fit"); return -1; } *rlenp = sizeof(struct sockaddr_in); memcpy(resultp, sa, *rlenp); return 0; case AF_INET6: sa6 = (struct sockaddr_in6 *)ifa->ifa_addr; v6addr = &sa6->sin6_addr; if (!allow_local && (IN6_IS_ADDR_LINKLOCAL(v6addr) || IN6_IS_ADDR_LOOPBACK(v6addr))) continue; if (*rlenp < sizeof(struct sockaddr_in6)) { error_f("v6 addr doesn't fit"); return -1; } *rlenp = sizeof(struct sockaddr_in6); memcpy(resultp, sa6, *rlenp); return 0; } } } return -1; } #endif /* * Creates a socket for use as the ssh connection. */ static int ssh_create_socket(struct addrinfo *ai) { int sock, r; struct sockaddr_storage bindaddr; socklen_t bindaddrlen = 0; struct addrinfo hints, *res = NULL; #ifdef HAVE_IFADDRS_H struct ifaddrs *ifaddrs = NULL; #endif char ntop[NI_MAXHOST]; sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { error("socket: %s", strerror(errno)); return -1; } (void)fcntl(sock, F_SETFD, FD_CLOEXEC); /* Use interactive QOS (if specified) until authentication completed */ if (options.ip_qos_interactive != INT_MAX) set_sock_tos(sock, options.ip_qos_interactive); /* Bind the socket to an alternative local IP address */ if (options.bind_address == NULL && options.bind_interface == NULL) return sock; if (options.bind_address != NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_family = ai->ai_family; hints.ai_socktype = ai->ai_socktype; hints.ai_protocol = ai->ai_protocol; hints.ai_flags = AI_PASSIVE; if ((r = getaddrinfo(options.bind_address, NULL, &hints, &res)) != 0) { error("getaddrinfo: %s: %s", options.bind_address, ssh_gai_strerror(r)); goto fail; } if (res == NULL) { error("getaddrinfo: no addrs"); goto fail; } memcpy(&bindaddr, res->ai_addr, res->ai_addrlen); bindaddrlen = res->ai_addrlen; } else if (options.bind_interface != NULL) { #ifdef HAVE_IFADDRS_H if ((r = getifaddrs(&ifaddrs)) != 0) { error("getifaddrs: %s: %s", options.bind_interface, strerror(errno)); goto fail; } bindaddrlen = sizeof(bindaddr); if (check_ifaddrs(options.bind_interface, ai->ai_family, ifaddrs, &bindaddr, &bindaddrlen) != 0) { logit("getifaddrs: %s: no suitable addresses", options.bind_interface); goto fail; } #else error("BindInterface not supported on this platform."); #endif } if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) { error_f("getnameinfo failed: %s", ssh_gai_strerror(r)); goto fail; } if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) { error("bind %s: %s", ntop, strerror(errno)); goto fail; } debug_f("bound to %s", ntop); /* success */ goto out; fail: close(sock); sock = -1; out: if (res != NULL) freeaddrinfo(res); #ifdef HAVE_IFADDRS_H if (ifaddrs != NULL) freeifaddrs(ifaddrs); #endif return sock; } /* * Opens a TCP/IP connection to the remote server on the given host. * The address of the remote host will be returned in hostaddr. * If port is 0, the default port will be used. * Connection_attempts specifies the maximum number of tries (one per * second). If proxy_command is non-NULL, it specifies the command (with %h * and %p substituted for host and port, respectively) to use to contact * the daemon. */ static int ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, struct sockaddr_storage *hostaddr, u_short port, int connection_attempts, int *timeout_ms, int want_keepalive) { int on = 1, saved_timeout_ms = *timeout_ms; int oerrno, sock = -1, attempt; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; struct addrinfo *ai; debug3_f("entering"); memset(ntop, 0, sizeof(ntop)); memset(strport, 0, sizeof(strport)); for (attempt = 0; attempt < connection_attempts; attempt++) { if (attempt > 0) { /* Sleep a moment before retrying. */ sleep(1); debug("Trying again..."); } /* * Loop through addresses for this host, and try each one in * sequence until the connection succeeds. */ for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { errno = EAFNOSUPPORT; continue; } if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { oerrno = errno; error_f("getnameinfo failed"); errno = oerrno; continue; } if (options.address_family != AF_UNSPEC && ai->ai_family != options.address_family) { debug2_f("skipping address [%s]:%s: " "wrong address family", ntop, strport); errno = EAFNOSUPPORT; continue; } debug("Connecting to %.200s [%.100s] port %s.", host, ntop, strport); /* Create a socket for connecting. */ sock = ssh_create_socket(ai); if (sock < 0) { /* Any error is already output */ errno = 0; continue; } *timeout_ms = saved_timeout_ms; if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, timeout_ms) >= 0) { /* Successful connection. */ memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); break; } else { oerrno = errno; debug("connect to address %s port %s: %s", ntop, strport, strerror(errno)); close(sock); sock = -1; errno = oerrno; } } if (sock != -1) break; /* Successful connection. */ } /* Return failure if we didn't get a successful connection. */ if (sock == -1) { error("ssh: connect to host %s port %s: %s", host, strport, errno == 0 ? "failure" : strerror(errno)); return -1; } debug("Connection established."); /* Set SO_KEEPALIVE if requested. */ if (want_keepalive && setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)) == -1) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); /* Set the connection. */ if (ssh_packet_set_connection(ssh, sock, sock) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } int ssh_connect(struct ssh *ssh, const char *host, const char *host_arg, struct addrinfo *addrs, struct sockaddr_storage *hostaddr, u_short port, int connection_attempts, int *timeout_ms, int want_keepalive) { int in, out; if (options.proxy_command == NULL) { return ssh_connect_direct(ssh, host, addrs, hostaddr, port, connection_attempts, timeout_ms, want_keepalive); } else if (strcmp(options.proxy_command, "-") == 0) { if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) { if (in >= 0) close(in); error_f("dup() in/out failed"); return -1; /* ssh_packet_set_connection logs error */ } if ((ssh_packet_set_connection(ssh, in, out)) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } else if (options.proxy_use_fdpass) { return ssh_proxy_fdpass_connect(ssh, host, host_arg, port, options.proxy_command); } return ssh_proxy_connect(ssh, host, host_arg, port, options.proxy_command); } /* defaults to 'no' */ static int confirm(const char *prompt, const char *fingerprint) { const char *msg, *again = "Please type 'yes' or 'no': "; const char *again_fp = "Please type 'yes', 'no' or the fingerprint: "; char *p, *cp; int ret = -1; if (options.batch_mode) return 0; for (msg = prompt;;msg = fingerprint ? again_fp : again) { cp = p = read_passphrase(msg, RP_ECHO); if (p == NULL) return 0; p += strspn(p, " \t"); /* skip leading whitespace */ p[strcspn(p, " \t\n")] = '\0'; /* remove trailing whitespace */ if (p[0] == '\0' || strcasecmp(p, "no") == 0) ret = 0; else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL && strcmp(p, fingerprint) == 0)) ret = 1; free(cp); if (ret != -1) return ret; } } static int sockaddr_is_local(struct sockaddr *hostaddr) { switch (hostaddr->sa_family) { case AF_INET: return (ntohl(((struct sockaddr_in *)hostaddr)-> sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; case AF_INET6: return IN6_IS_ADDR_LOOPBACK( &(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); default: return 0; } } /* * Prepare the hostname and ip address strings that are used to lookup * host keys in known_hosts files. These may have a port number appended. */ void get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, u_short port, char **hostfile_hostname, char **hostfile_ipaddr) { char ntop[NI_MAXHOST]; socklen_t addrlen; switch (hostaddr == NULL ? -1 : hostaddr->sa_family) { case -1: addrlen = 0; break; case AF_INET: addrlen = sizeof(struct sockaddr_in); break; case AF_INET6: addrlen = sizeof(struct sockaddr_in6); break; default: addrlen = sizeof(struct sockaddr); break; } /* * We don't have the remote ip-address for connections * using a proxy command */ if (hostfile_ipaddr != NULL) { if (options.proxy_command == NULL) { if (getnameinfo(hostaddr, addrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) fatal_f("getnameinfo failed"); *hostfile_ipaddr = put_host_port(ntop, port); } else { *hostfile_ipaddr = xstrdup(""); } } /* * Allow the user to record the key under a different name or * differentiate a non-standard port. This is useful for ssh * tunneling over forwarded connections or if you run multiple * sshd's on different ports on the same machine. */ if (hostfile_hostname != NULL) { if (options.host_key_alias != NULL) { *hostfile_hostname = xstrdup(options.host_key_alias); debug("using hostkeyalias: %s", *hostfile_hostname); } else { *hostfile_hostname = put_host_port(hostname, port); } } } /* returns non-zero if path appears in hostfiles, or 0 if not. */ static int path_in_hostfiles(const char *path, char **hostfiles, u_int num_hostfiles) { u_int i; for (i = 0; i < num_hostfiles; i++) { if (strcmp(path, hostfiles[i]) == 0) return 1; } return 0; } struct find_by_key_ctx { const char *host, *ip; const struct sshkey *key; char **names; u_int nnames; }; /* Try to replace home directory prefix (per $HOME) with a ~/ sequence */ static char * try_tilde_unexpand(const char *path) { char *home, *ret = NULL; size_t l; if (*path != '/') return xstrdup(path); if ((home = getenv("HOME")) == NULL || (l = strlen(home)) == 0) return xstrdup(path); if (strncmp(path, home, l) != 0) return xstrdup(path); /* * ensure we have matched on a path boundary: either the $HOME that * we just compared ends with a '/' or the next character of the path * must be a '/'. */ if (home[l - 1] != '/' && path[l] != '/') return xstrdup(path); if (path[l] == '/') l++; xasprintf(&ret, "~/%s", path + l); return ret; } /* * Returns non-zero if the key is accepted by HostkeyAlgorithms. * Made slightly less trivial by the multiple RSA signature algorithm names. */ int hostkey_accepted_by_hostkeyalgs(const struct sshkey *key) { const char *ktype = sshkey_ssh_name(key); const char *hostkeyalgs = options.hostkeyalgorithms; if (key->type == KEY_UNSPEC) return 0; if (key->type == KEY_RSA && (match_pattern_list("rsa-sha2-256", hostkeyalgs, 0) == 1 || match_pattern_list("rsa-sha2-512", hostkeyalgs, 0) == 1)) return 1; if (key->type == KEY_RSA_CERT && (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", hostkeyalgs, 0) == 1 || match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", hostkeyalgs, 0) == 1)) return 1; return match_pattern_list(ktype, hostkeyalgs, 0) == 1; } static int hostkeys_find_by_key_cb(struct hostkey_foreach_line *l, void *_ctx) { struct find_by_key_ctx *ctx = (struct find_by_key_ctx *)_ctx; char *path; /* we are looking for keys with names that *do not* match */ if ((l->match & HKF_MATCH_HOST) != 0) return 0; /* not interested in marker lines */ if (l->marker != MRK_NONE) return 0; /* we are only interested in exact key matches */ if (l->key == NULL || !sshkey_equal(ctx->key, l->key)) return 0; path = try_tilde_unexpand(l->path); debug_f("found matching key in %s:%lu", path, l->linenum); ctx->names = xrecallocarray(ctx->names, ctx->nnames, ctx->nnames + 1, sizeof(*ctx->names)); xasprintf(&ctx->names[ctx->nnames], "%s:%lu: %s", path, l->linenum, strncmp(l->hosts, HASH_MAGIC, strlen(HASH_MAGIC)) == 0 ? "[hashed name]" : l->hosts); ctx->nnames++; free(path); return 0; } static int hostkeys_find_by_key_hostfile(const char *file, const char *which, struct find_by_key_ctx *ctx) { int r; debug3_f("trying %s hostfile \"%s\"", which, file); if ((r = hostkeys_foreach(file, hostkeys_find_by_key_cb, ctx, ctx->host, ctx->ip, HKF_WANT_PARSE_KEY, 0)) != 0) { if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { debug_f("hostkeys file %s does not exist", file); return 0; } error_fr(r, "hostkeys_foreach failed for %s", file); return r; } return 0; } /* * Find 'key' in known hosts file(s) that do not match host/ip. * Used to display also-known-as information for previously-unseen hostkeys. */ static void hostkeys_find_by_key(const char *host, const char *ip, const struct sshkey *key, char **user_hostfiles, u_int num_user_hostfiles, char **system_hostfiles, u_int num_system_hostfiles, char ***names, u_int *nnames) { struct find_by_key_ctx ctx = {0, 0, 0, 0, 0}; u_int i; *names = NULL; *nnames = 0; if (key == NULL || sshkey_is_cert(key)) return; ctx.host = host; ctx.ip = ip; ctx.key = key; for (i = 0; i < num_user_hostfiles; i++) { if (hostkeys_find_by_key_hostfile(user_hostfiles[i], "user", &ctx) != 0) goto fail; } for (i = 0; i < num_system_hostfiles; i++) { if (hostkeys_find_by_key_hostfile(system_hostfiles[i], "system", &ctx) != 0) goto fail; } /* success */ *names = ctx.names; *nnames = ctx.nnames; ctx.names = NULL; ctx.nnames = 0; return; fail: for (i = 0; i < ctx.nnames; i++) free(ctx.names[i]); free(ctx.names); } #define MAX_OTHER_NAMES 8 /* Maximum number of names to list */ static char * other_hostkeys_message(const char *host, const char *ip, const struct sshkey *key, char **user_hostfiles, u_int num_user_hostfiles, char **system_hostfiles, u_int num_system_hostfiles) { char *ret = NULL, **othernames = NULL; u_int i, n, num_othernames = 0; hostkeys_find_by_key(host, ip, key, user_hostfiles, num_user_hostfiles, system_hostfiles, num_system_hostfiles, &othernames, &num_othernames); if (num_othernames == 0) return xstrdup("This key is not known by any other names."); xasprintf(&ret, "This host key is known by the following other " "names/addresses:"); n = num_othernames; if (n > MAX_OTHER_NAMES) n = MAX_OTHER_NAMES; for (i = 0; i < n; i++) { xextendf(&ret, "\n", " %s", othernames[i]); } if (n < num_othernames) { xextendf(&ret, "\n", " (%d additional names omitted)", num_othernames - n); } for (i = 0; i < num_othernames; i++) free(othernames[i]); free(othernames); return ret; } void load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template, const char *invocation, const struct ssh_conn_info *cinfo, const struct sshkey *host_key, const char *hostfile_hostname) { int r, i, ac = 0; char *key_fp = NULL, *keytext = NULL, *tmp; char *command = NULL, *tag = NULL, **av = NULL; FILE *f = NULL; pid_t pid; void (*osigchld)(int); xasprintf(&tag, "KnownHostsCommand-%s", invocation); if (host_key != NULL) { if ((key_fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); if ((r = sshkey_to_base64(host_key, &keytext)) != 0) fatal_fr(r, "sshkey_to_base64 failed"); } /* * NB. all returns later this function should go via "out" to * ensure the original SIGCHLD handler is restored properly. */ osigchld = ssh_signal(SIGCHLD, SIG_DFL); /* Turn the command into an argument vector */ if (argv_split(command_template, &ac, &av, 0) != 0) { error("%s \"%s\" contains invalid quotes", tag, command_template); goto out; } if (ac == 0) { error("%s \"%s\" yielded no arguments", tag, command_template); goto out; } for (i = 1; i < ac; i++) { tmp = percent_dollar_expand(av[i], DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), "H", hostfile_hostname, "I", invocation, "t", host_key == NULL ? "NONE" : sshkey_ssh_name(host_key), "f", key_fp == NULL ? "NONE" : key_fp, "K", keytext == NULL ? "NONE" : keytext, (char *)NULL); if (tmp == NULL) fatal_f("percent_expand failed"); free(av[i]); av[i] = tmp; } /* Prepare a printable command for logs, etc. */ command = argv_assemble(ac, av); if ((pid = subprocess(tag, command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) goto out; load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); if (exited_cleanly(pid, tag, command, 0) != 0) fatal("KnownHostsCommand failed"); out: if (f != NULL) fclose(f); ssh_signal(SIGCHLD, osigchld); for (i = 0; i < ac; i++) free(av[i]); free(av); free(tag); free(command); free(key_fp); free(keytext); } /* * check whether the supplied host key is valid, return -1 if the key * is not valid. user_hostfile[0] will not be updated if 'readonly' is true. */ #define RDRW 0 #define RDONLY 1 #define ROQUIET 2 static int check_host_key(char *hostname, const struct ssh_conn_info *cinfo, struct sockaddr *hostaddr, u_short port, struct sshkey *host_key, int readonly, int clobber_port, char **user_hostfiles, u_int num_user_hostfiles, char **system_hostfiles, u_int num_system_hostfiles, const char *hostfile_command) { HostStatus host_status = -1, ip_status = -1; struct sshkey *raw_key = NULL; char *ip = NULL, *host = NULL; char hostline[1000], *hostp, *fp, *ra; char msg[1024]; const char *type, *fail_reason = NULL; const struct hostkey_entry *host_found = NULL, *ip_found = NULL; int len, cancelled_forwarding = 0, confirmed; int local = sockaddr_is_local(hostaddr); int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0; int hostkey_trusted = 0; /* Known or explicitly accepted by user */ struct hostkeys *host_hostkeys, *ip_hostkeys; u_int i; /* * Force accepting of the host key for loopback/localhost. The * problem is that if the home directory is NFS-mounted to multiple * machines, localhost will refer to a different machine in each of * them, and the user will get bogus HOST_CHANGED warnings. This * essentially disables host authentication for localhost; however, * this is probably not a real problem. */ if (options.no_host_authentication_for_localhost == 1 && local && options.host_key_alias == NULL) { debug("Forcing accepting of host key for " "loopback/localhost."); options.update_hostkeys = 0; return 0; } /* * Don't ever try to write an invalid name to a known hosts file. * Note: do this before get_hostfile_hostname_ipaddr() to catch * '[' or ']' in the name before they are added. */ if (strcspn(hostname, "@?*#[]|'\'\"\\") != strlen(hostname)) { debug_f("invalid hostname \"%s\"; will not record: %s", hostname, fail_reason); readonly = RDONLY; } /* * Prepare the hostname and address strings used for hostkey lookup. * In some cases, these will have a port number appended. */ get_hostfile_hostname_ipaddr(hostname, hostaddr, clobber_port ? 0 : port, &host, &ip); /* * Turn off check_host_ip if the connection is to localhost, via proxy * command or if we don't have a hostname to compare with */ if (options.check_host_ip && (local || strcmp(hostname, ip) == 0 || options.proxy_command != NULL)) options.check_host_ip = 0; host_hostkeys = init_hostkeys(); for (i = 0; i < num_user_hostfiles; i++) load_hostkeys(host_hostkeys, host, user_hostfiles[i], 0); for (i = 0; i < num_system_hostfiles; i++) load_hostkeys(host_hostkeys, host, system_hostfiles[i], 0); if (hostfile_command != NULL && !clobber_port) { load_hostkeys_command(host_hostkeys, hostfile_command, "HOSTNAME", cinfo, host_key, host); } ip_hostkeys = NULL; if (!want_cert && options.check_host_ip) { ip_hostkeys = init_hostkeys(); for (i = 0; i < num_user_hostfiles; i++) load_hostkeys(ip_hostkeys, ip, user_hostfiles[i], 0); for (i = 0; i < num_system_hostfiles; i++) load_hostkeys(ip_hostkeys, ip, system_hostfiles[i], 0); if (hostfile_command != NULL && !clobber_port) { load_hostkeys_command(ip_hostkeys, hostfile_command, "ADDRESS", cinfo, host_key, ip); } } retry: if (!hostkey_accepted_by_hostkeyalgs(host_key)) { error("host key %s not permitted by HostkeyAlgorithms", sshkey_ssh_name(host_key)); goto fail; } /* Reload these as they may have changed on cert->key downgrade */ want_cert = sshkey_is_cert(host_key); type = sshkey_type(host_key); /* * Check if the host key is present in the user's list of known * hosts or in the systemwide list. */ host_status = check_key_in_hostkeys(host_hostkeys, host_key, &host_found); /* * If there are no hostfiles, or if the hostkey was found via * KnownHostsCommand, then don't try to touch the disk. */ if (!readonly && (num_user_hostfiles == 0 || (host_found != NULL && host_found->note != 0))) readonly = RDONLY; /* * Also perform check for the ip address, skip the check if we are * localhost, looking for a certificate, or the hostname was an ip * address to begin with. */ if (!want_cert && ip_hostkeys != NULL) { ip_status = check_key_in_hostkeys(ip_hostkeys, host_key, &ip_found); if (host_status == HOST_CHANGED && (ip_status != HOST_CHANGED || (ip_found != NULL && !sshkey_equal(ip_found->key, host_found->key)))) host_ip_differ = 1; } else ip_status = host_status; switch (host_status) { case HOST_OK: /* The host is known and the key matches. */ debug("Host '%.200s' is known and matches the %s host %s.", host, type, want_cert ? "certificate" : "key"); debug("Found %s in %s:%lu", want_cert ? "CA key" : "key", host_found->file, host_found->line); if (want_cert) { if (sshkey_cert_check_host(host_key, options.host_key_alias == NULL ? hostname : options.host_key_alias, 0, options.ca_sign_algorithms, &fail_reason) != 0) { error("%s", fail_reason); goto fail; } /* * Do not attempt hostkey update if a certificate was * successfully matched. */ if (options.update_hostkeys != 0) { options.update_hostkeys = 0; debug3_f("certificate host key in use; " "disabling UpdateHostkeys"); } } /* Turn off UpdateHostkeys if key was in system known_hosts */ if (options.update_hostkeys != 0 && (path_in_hostfiles(host_found->file, system_hostfiles, num_system_hostfiles) || (ip_status == HOST_OK && ip_found != NULL && path_in_hostfiles(ip_found->file, system_hostfiles, num_system_hostfiles)))) { options.update_hostkeys = 0; debug3_f("host key found in GlobalKnownHostsFile; " "disabling UpdateHostkeys"); } if (options.update_hostkeys != 0 && host_found->note) { options.update_hostkeys = 0; debug3_f("host key found via KnownHostsCommand; " "disabling UpdateHostkeys"); } if (options.check_host_ip && ip_status == HOST_NEW) { if (readonly || want_cert) logit("%s host key for IP address " "'%.128s' not in list of known hosts.", type, ip); else if (!add_host_to_hostfile(user_hostfiles[0], ip, host_key, options.hash_known_hosts)) logit("Failed to add the %s host key for IP " "address '%.128s' to the list of known " "hosts (%.500s).", type, ip, user_hostfiles[0]); else logit("Warning: Permanently added the %s host " "key for IP address '%.128s' to the list " "of known hosts.", type, ip); } else if (options.visual_host_key) { fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); ra = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal_f("sshkey_fingerprint failed"); logit("Host key fingerprint is %s\n%s", fp, ra); free(ra); free(fp); } hostkey_trusted = 1; break; case HOST_NEW: if (options.host_key_alias == NULL && port != 0 && port != SSH_DEFAULT_PORT && !clobber_port) { debug("checking without port identifier"); if (check_host_key(hostname, cinfo, hostaddr, 0, host_key, ROQUIET, 1, user_hostfiles, num_user_hostfiles, system_hostfiles, num_system_hostfiles, hostfile_command) == 0) { debug("found matching key w/out port"); break; } } if (readonly || want_cert) goto fail; /* The host is new. */ if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_YES) { /* * User has requested strict host key checking. We * will not add the host key automatically. The only * alternative left is to abort. */ error("No %s host key is known for %.200s and you " "have requested strict checking.", type, host); goto fail; } else if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_ASK) { char *msg1 = NULL, *msg2 = NULL; xasprintf(&msg1, "The authenticity of host " "'%.200s (%s)' can't be established", host, ip); if (show_other_keys(host_hostkeys, host_key)) { xextendf(&msg1, "\n", "but keys of different " "type are already known for this host."); } else xextendf(&msg1, "", "."); fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); ra = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal_f("sshkey_fingerprint failed"); xextendf(&msg1, "\n", "%s key fingerprint is %s.", type, fp); if (options.visual_host_key) xextendf(&msg1, "\n", "%s", ra); if (options.verify_host_key_dns) { xextendf(&msg1, "\n", "%s host key fingerprint found in DNS.", matching_host_key_dns ? "Matching" : "No matching"); } /* msg2 informs for other names matching this key */ if ((msg2 = other_hostkeys_message(host, ip, host_key, user_hostfiles, num_user_hostfiles, system_hostfiles, num_system_hostfiles)) != NULL) xextendf(&msg1, "\n", "%s", msg2); xextendf(&msg1, "\n", "Are you sure you want to continue connecting " "(yes/no/[fingerprint])? "); confirmed = confirm(msg1, fp); free(ra); free(fp); free(msg1); free(msg2); if (!confirmed) goto fail; hostkey_trusted = 1; /* user explicitly confirmed */ } /* * If in "new" or "off" strict mode, add the key automatically * to the local known_hosts file. */ if (options.check_host_ip && ip_status == HOST_NEW) { snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); hostp = hostline; if (options.hash_known_hosts) { /* Add hash of host and IP separately */ r = add_host_to_hostfile(user_hostfiles[0], host, host_key, options.hash_known_hosts) && add_host_to_hostfile(user_hostfiles[0], ip, host_key, options.hash_known_hosts); } else { /* Add unhashed "host,ip" */ r = add_host_to_hostfile(user_hostfiles[0], hostline, host_key, options.hash_known_hosts); } } else { r = add_host_to_hostfile(user_hostfiles[0], host, host_key, options.hash_known_hosts); hostp = host; } if (!r) logit("Failed to add the host to the list of known " "hosts (%.500s).", user_hostfiles[0]); else logit("Warning: Permanently added '%.200s' (%s) to the " "list of known hosts.", hostp, type); break; case HOST_REVOKED: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REVOKED HOST KEY DETECTED! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("The %s host key for %s is marked as revoked.", type, host); error("This could mean that a stolen key is being used to"); error("impersonate this host."); /* * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ if (options.strict_host_key_checking != SSH_STRICT_HOSTKEY_OFF) { error("%s host key for %.200s was revoked and you have " "requested strict checking.", type, host); goto fail; } goto continue_unsafe; case HOST_CHANGED: if (want_cert) { /* * This is only a debug() since it is valid to have * CAs with wildcard DNS matches that don't match * all hosts that one might visit. */ debug("Host certificate authority does not " "match %s in %s:%lu", CA_MARKER, host_found->file, host_found->line); goto fail; } if (readonly == ROQUIET) goto fail; if (options.check_host_ip && host_ip_differ) { char *key_msg; if (ip_status == HOST_NEW) key_msg = "is unknown"; else if (ip_status == HOST_OK) key_msg = "is unchanged"; else key_msg = "has a different value"; error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("The %s host key for %s has changed,", type, host); error("and the key for the corresponding IP address %s", ip); error("%s. This could either mean that", key_msg); error("DNS SPOOFING is happening or the IP address for the host"); error("and its host key have changed at the same time."); if (ip_status != HOST_NEW) error("Offending key for IP in %s:%lu", ip_found->file, ip_found->line); } /* The host key has changed. */ warn_changed_key(host_key); if (num_user_hostfiles > 0 || num_system_hostfiles > 0) { error("Add correct host key in %.100s to get rid " "of this message.", num_user_hostfiles > 0 ? user_hostfiles[0] : system_hostfiles[0]); } error("Offending %s key in %s:%lu", sshkey_type(host_found->key), host_found->file, host_found->line); /* * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ if (options.strict_host_key_checking != SSH_STRICT_HOSTKEY_OFF) { error("Host key for %.200s has changed and you have " "requested strict checking.", host); goto fail; } continue_unsafe: /* * If strict host key checking has not been requested, allow * the connection but without MITM-able authentication or * forwarding. */ if (options.password_authentication) { error("Password authentication is disabled to avoid " "man-in-the-middle attacks."); options.password_authentication = 0; cancelled_forwarding = 1; } if (options.kbd_interactive_authentication) { error("Keyboard-interactive authentication is disabled" " to avoid man-in-the-middle attacks."); options.kbd_interactive_authentication = 0; cancelled_forwarding = 1; } if (options.forward_agent) { error("Agent forwarding is disabled to avoid " "man-in-the-middle attacks."); options.forward_agent = 0; cancelled_forwarding = 1; } if (options.forward_x11) { error("X11 forwarding is disabled to avoid " "man-in-the-middle attacks."); options.forward_x11 = 0; cancelled_forwarding = 1; } if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) { error("Port forwarding is disabled to avoid " "man-in-the-middle attacks."); options.num_local_forwards = options.num_remote_forwards = 0; cancelled_forwarding = 1; } if (options.tun_open != SSH_TUNMODE_NO) { error("Tunnel forwarding is disabled to avoid " "man-in-the-middle attacks."); options.tun_open = SSH_TUNMODE_NO; cancelled_forwarding = 1; } if (options.update_hostkeys != 0) { error("UpdateHostkeys is disabled because the host " "key is not trusted."); options.update_hostkeys = 0; } if (options.exit_on_forward_failure && cancelled_forwarding) fatal("Error: forwarding disabled due to host key " "check failure"); /* * XXX Should permit the user to change to use the new id. * This could be done by converting the host key to an * identifying sentence, tell that the host identifies itself * by that sentence, and ask the user if they wish to * accept the authentication. */ break; case HOST_FOUND: fatal("internal error"); break; } if (options.check_host_ip && host_status != HOST_CHANGED && ip_status == HOST_CHANGED) { snprintf(msg, sizeof(msg), "Warning: the %s host key for '%.200s' " "differs from the key for the IP address '%.128s'" "\nOffending key for IP in %s:%lu", type, host, ip, ip_found->file, ip_found->line); if (host_status == HOST_OK) { len = strlen(msg); snprintf(msg + len, sizeof(msg) - len, "\nMatching host key in %s:%lu", host_found->file, host_found->line); } if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_ASK) { strlcat(msg, "\nAre you sure you want " "to continue connecting (yes/no)? ", sizeof(msg)); if (!confirm(msg, NULL)) goto fail; } else if (options.strict_host_key_checking != SSH_STRICT_HOSTKEY_OFF) { logit("%s", msg); error("Exiting, you have requested strict checking."); goto fail; } else { logit("%s", msg); } } if (!hostkey_trusted && options.update_hostkeys) { debug_f("hostkey not known or explicitly trusted: " "disabling UpdateHostkeys"); options.update_hostkeys = 0; } free(ip); free(host); if (host_hostkeys != NULL) free_hostkeys(host_hostkeys); if (ip_hostkeys != NULL) free_hostkeys(ip_hostkeys); return 0; fail: if (want_cert && host_status != HOST_REVOKED) { /* * No matching certificate. Downgrade cert to raw key and * search normally. */ debug("No matching CA found. Retry with plain key"); if ((r = sshkey_from_private(host_key, &raw_key)) != 0) fatal_fr(r, "decode key"); if ((r = sshkey_drop_cert(raw_key)) != 0) fatal_r(r, "Couldn't drop certificate"); host_key = raw_key; goto retry; } sshkey_free(raw_key); free(ip); free(host); if (host_hostkeys != NULL) free_hostkeys(host_hostkeys); if (ip_hostkeys != NULL) free_hostkeys(ip_hostkeys); return -1; } /* returns 0 if key verifies or -1 if key does NOT verify */ int verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key, const struct ssh_conn_info *cinfo) { u_int i; int r = -1, flags = 0; char valid[64], *fp = NULL, *cafp = NULL; struct sshkey *plain = NULL; if ((fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_fr(r, "fingerprint host key"); r = -1; goto out; } if (sshkey_is_cert(host_key)) { if ((cafp = sshkey_fingerprint(host_key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_fr(r, "fingerprint CA key"); r = -1; goto out; } sshkey_format_cert_validity(host_key->cert, valid, sizeof(valid)); debug("Server host certificate: %s %s, serial %llu " "ID \"%s\" CA %s %s valid %s", sshkey_ssh_name(host_key), fp, (unsigned long long)host_key->cert->serial, host_key->cert->key_id, sshkey_ssh_name(host_key->cert->signature_key), cafp, valid); for (i = 0; i < host_key->cert->nprincipals; i++) { debug2("Server host certificate hostname: %s", host_key->cert->principals[i]); } } else { debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp); } if (sshkey_equal(previous_host_key, host_key)) { debug2_f("server host key %s %s matches cached key", sshkey_type(host_key), fp); r = 0; goto out; } /* Check in RevokedHostKeys file if specified */ if (options.revoked_host_keys != NULL) { r = sshkey_check_revoked(host_key, options.revoked_host_keys); switch (r) { case 0: break; /* not revoked */ case SSH_ERR_KEY_REVOKED: error("Host key %s %s revoked by file %s", sshkey_type(host_key), fp, options.revoked_host_keys); r = -1; goto out; default: error_r(r, "Error checking host key %s %s in " "revoked keys file %s", sshkey_type(host_key), fp, options.revoked_host_keys); r = -1; goto out; } } if (options.verify_host_key_dns) { /* * XXX certs are not yet supported for DNS, so downgrade * them and try the plain key. */ if ((r = sshkey_from_private(host_key, &plain)) != 0) goto out; if (sshkey_is_cert(plain)) sshkey_drop_cert(plain); if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { if (flags & DNS_VERIFY_FOUND) { if (options.verify_host_key_dns == 1 && flags & DNS_VERIFY_MATCH && flags & DNS_VERIFY_SECURE) { r = 0; goto out; } if (flags & DNS_VERIFY_MATCH) { matching_host_key_dns = 1; } else { warn_changed_key(plain); error("Update the SSHFP RR in DNS " "with the new host key to get rid " "of this message."); } } } } r = check_host_key(host, cinfo, hostaddr, options.port, host_key, RDRW, 0, options.user_hostfiles, options.num_user_hostfiles, options.system_hostfiles, options.num_system_hostfiles, options.known_hosts_command); out: sshkey_free(plain); free(fp); free(cafp); if (r == 0 && host_key != NULL) { sshkey_free(previous_host_key); r = sshkey_from_private(host_key, &previous_host_key); } return r; } /* * Starts a dialog with the server, and authenticates the current user on the * server. This does not need any extra privileges. The basic connection * to the server must already have been established before this is called. * If login fails, this function prints an error and never returns. * This function does not require super-user privileges. */ void ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms, const struct ssh_conn_info *cinfo) { char *host; char *server_user, *local_user; int r; local_user = xstrdup(pw->pw_name); server_user = options.user ? options.user : local_user; /* Convert the user-supplied hostname into all lowercase. */ host = xstrdup(orighost); lowercase(host); /* Exchange protocol version identification strings with the server. */ if ((r = kex_exchange_identification(ssh, timeout_ms, options.version_addendum)) != 0) sshpkt_fatal(ssh, r, "banner exchange"); /* Put the connection into non-blocking mode. */ ssh_packet_set_nonblocking(ssh); /* key exchange */ /* authenticate user */ debug("Authenticating to %s:%d as '%s'", host, port, server_user); ssh_kex2(ssh, host, hostaddr, port, cinfo); ssh_userauth2(ssh, local_user, server_user, host, sensitive); free(local_user); free(host); } /* print all known host keys for a given host, but skip keys of given type */ static int show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) { int type[] = { KEY_RSA, #ifdef WITH_DSA KEY_DSA, #endif KEY_ECDSA, KEY_ED25519, KEY_XMSS, -1 }; int i, ret = 0; char *fp, *ra; const struct hostkey_entry *found; for (i = 0; type[i] != -1; i++) { if (type[i] == key->type) continue; if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], -1, &found)) continue; fp = sshkey_fingerprint(found->key, options.fingerprint_hash, SSH_FP_DEFAULT); ra = sshkey_fingerprint(found->key, options.fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal_f("sshkey_fingerprint fail"); logit("WARNING: %s key found for host %s\n" "in %s:%lu\n" "%s key fingerprint %s.", sshkey_type(found->key), found->host, found->file, found->line, sshkey_type(found->key), fp); if (options.visual_host_key) logit("%s", ra); free(ra); free(fp); ret = 1; } return ret; } static void warn_changed_key(struct sshkey *host_key) { char *fp; fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); if (fp == NULL) fatal_f("sshkey_fingerprint fail"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); error("It is also possible that a host key has just been changed."); error("The fingerprint for the %s key sent by the remote host is\n%s.", sshkey_type(host_key), fp); error("Please contact your system administrator."); free(fp); } /* * Execute a local command */ int ssh_local_cmd(const char *args) { char *shell; pid_t pid; int status; void (*osighand)(int); if (!options.permit_local_command || args == NULL || !*args) return (1); if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; osighand = ssh_signal(SIGCHLD, SIG_DFL); pid = fork(); if (pid == 0) { ssh_signal(SIGPIPE, SIG_DFL); debug3("Executing %s -c \"%s\"", shell, args); execl(shell, shell, "-c", args, (char *)NULL); error("Couldn't execute %s -c \"%s\": %s", shell, args, strerror(errno)); _exit(1); } else if (pid == -1) fatal("fork failed: %.100s", strerror(errno)); while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for child: %s", strerror(errno)); ssh_signal(SIGCHLD, osighand); if (!WIFEXITED(status)) return (1); return (WEXITSTATUS(status)); } void maybe_add_key_to_agent(const char *authfile, struct sshkey *private, const char *comment, const char *passphrase) { int auth_sock = -1, r; const char *skprovider = NULL; if (options.add_keys_to_agent == 0) return; if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { debug3("no authentication agent, not adding key"); return; } if (options.add_keys_to_agent == 2 && !ask_permission("Add key %s (%s) to agent?", authfile, comment)) { debug3("user denied adding this key"); close(auth_sock); return; } if (sshkey_is_sk(private)) skprovider = options.sk_provider; if ((r = ssh_add_identity_constrained(auth_sock, private, comment == NULL ? authfile : comment, options.add_keys_to_agent_lifespan, (options.add_keys_to_agent == 3), 0, skprovider, NULL, 0)) == 0) debug("identity added to agent: %s", authfile); else debug("could not add identity to agent: %s (%d)", authfile, r); close(auth_sock); } openssh-10.0p1/PaxHeaders.10889/sshconnect.h100644 001750 001750 0000000003614775415623 0015474xustar0030 atime=1744182234.862134512 openssh-10.0p1/sshconnect.h010064400017500001750000000066711477541562300140710ustar00djmdjm/* $OpenBSD: sshconnect.h,v 1.49 2025/03/01 06:11:26 dtucker 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. */ struct sshkey; typedef struct Sensitive Sensitive; struct Sensitive { struct sshkey **keys; int nkeys; }; struct ssh_conn_info { char *conn_hash_hex; char *shorthost; char *uidstr; char *keyalias; char *thishost; char *host_arg; char *portstr; char *remhost; char *remuser; char *homedir; char *locuser; char *jmphost; }; struct addrinfo; struct ssh; struct hostkeys; struct ssh_conn_info; /* default argument for client percent expansions, minus remote user */ #define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS_NOUSER(conn_info) \ "L", conn_info->shorthost, \ "i", conn_info->uidstr, \ "k", conn_info->keyalias, \ "l", conn_info->thishost, \ "n", conn_info->host_arg, \ "p", conn_info->portstr, \ "d", conn_info->homedir, \ "h", conn_info->remhost, \ "u", conn_info->locuser, \ "j", conn_info->jmphost /* same plus remote user and hash which has user as a component */ #define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(conn_info) \ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS_NOUSER(conn_info), \ "C", conn_info->conn_hash_hex, \ "r", conn_info->remuser int ssh_connect(struct ssh *, const char *, const char *, struct addrinfo *, struct sockaddr_storage *, u_short, int, int *, int); void ssh_kill_proxy_command(void); void ssh_login(struct ssh *, Sensitive *, const char *, struct sockaddr *, u_short, struct passwd *, int, const struct ssh_conn_info *); int verify_host_key(char *, struct sockaddr *, struct sshkey *, const struct ssh_conn_info *); void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, char **, char **); void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short, const struct ssh_conn_info *); void ssh_userauth2(struct ssh *ssh, const char *, const char *, char *, Sensitive *); int ssh_local_cmd(const char *); void maybe_add_key_to_agent(const char *, struct sshkey *, const char *, const char *); void load_hostkeys_command(struct hostkeys *, const char *, const char *, const struct ssh_conn_info *, const struct sshkey *, const char *); int hostkey_accepted_by_hostkeyalgs(const struct sshkey *); openssh-10.0p1/PaxHeaders.10889/sshconnect2.c100644 001750 001750 0000000003614775415623 0015551xustar0030 atime=1744182234.863110438 openssh-10.0p1/sshconnect2.c010064400017500001750000002020331477541562300141340ustar00djmdjm/* $OpenBSD: sshconnect2.c,v 1.377 2025/02/18 08:02:48 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) #include #endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshbuf.h" #include "packet.h" #include "compat.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "sshconnect.h" #include "authfile.h" #include "dh.h" #include "authfd.h" #include "log.h" #include "misc.h" #include "readconf.h" #include "match.h" #include "dispatch.h" #include "canohost.h" #include "msg.h" #include "pathnames.h" #include "uidswap.h" #include "hostfile.h" #include "ssherr.h" #include "utf8.h" #include "ssh-sk.h" #include "sk-api.h" #ifdef GSSAPI #include "ssh-gss.h" #endif /* import */ extern Options options; /* * SSH2 key exchange */ static char *xxx_host; static struct sockaddr *xxx_hostaddr; static const struct ssh_conn_info *xxx_conn_info; static int verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) { int r; if ((r = sshkey_check_rsa_length(hostkey, options.required_rsa_size)) != 0) fatal_r(r, "Bad server host key"); if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, xxx_conn_info) != 0) fatal("Host key verification failed."); return 0; } /* Returns the first item from a comma-separated algorithm list */ static char * first_alg(const char *algs) { char *ret, *cp; ret = xstrdup(algs); if ((cp = strchr(ret, ',')) != NULL) *cp = '\0'; return ret; } static char * order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) { char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL; char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL; size_t maxlen; struct hostkeys *hostkeys = NULL; int ktype; u_int i; /* Find all hostkeys for this hostname */ get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL); hostkeys = init_hostkeys(); for (i = 0; i < options.num_user_hostfiles; i++) load_hostkeys(hostkeys, hostname, options.user_hostfiles[i], 0); for (i = 0; i < options.num_system_hostfiles; i++) { load_hostkeys(hostkeys, hostname, options.system_hostfiles[i], 0); } if (options.known_hosts_command != NULL) { load_hostkeys_command(hostkeys, options.known_hosts_command, "ORDER", cinfo, NULL, hostname); } /* * If a plain public key exists that matches the type of the best * preference HostkeyAlgorithms, then use the whole list as is. * Note that we ignore whether the best preference algorithm is a * certificate type, as sshconnect.c will downgrade certs to * plain keys if necessary. */ best = first_alg(options.hostkeyalgorithms); if (lookup_key_in_hostkeys_by_type(hostkeys, sshkey_type_plain(sshkey_type_from_name(best)), sshkey_ecdsa_nid_from_name(best), NULL)) { debug3_f("have matching best-preference key type %s, " "using HostkeyAlgorithms verbatim", best); ret = xstrdup(options.hostkeyalgorithms); goto out; } /* * Otherwise, prefer the host key algorithms that match known keys * while keeping the ordering of HostkeyAlgorithms as much as possible. */ oavail = avail = xstrdup(options.hostkeyalgorithms); maxlen = strlen(avail) + 1; first = xmalloc(maxlen); last = xmalloc(maxlen); *first = *last = '\0'; #define ALG_APPEND(to, from) \ do { \ if (*to != '\0') \ strlcat(to, ",", maxlen); \ strlcat(to, from, maxlen); \ } while (0) while ((alg = strsep(&avail, ",")) && *alg != '\0') { if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) fatal_f("unknown alg %s", alg); /* * If we have a @cert-authority marker in known_hosts then * prefer all certificate algorithms. */ if (sshkey_type_is_cert(ktype) && lookup_marker_in_hostkeys(hostkeys, MRK_CA)) { ALG_APPEND(first, alg); continue; } /* If the key appears in known_hosts then prefer it */ if (lookup_key_in_hostkeys_by_type(hostkeys, sshkey_type_plain(ktype), sshkey_ecdsa_nid_from_name(alg), NULL)) { ALG_APPEND(first, alg); continue; } /* Otherwise, put it last */ ALG_APPEND(last, alg); } #undef ALG_APPEND xasprintf(&ret, "%s%s%s", first, (*first == '\0' || *last == '\0') ? "" : ",", last); if (*first != '\0') debug3_f("prefer hostkeyalgs: %s", first); else debug3_f("no algorithms matched; accept original"); out: free(best); free(first); free(last); free(hostname); free(oavail); free_hostkeys(hostkeys); return ret; } void ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) { char *myproposal[PROPOSAL_MAX]; char *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; xxx_host = host; xxx_hostaddr = hostaddr; xxx_conn_info = cinfo; if (options.rekey_limit || options.rekey_interval) ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); /* * If the user has not specified HostkeyAlgorithms, or has only * appended or removed algorithms from that list then prefer algorithms * that are in the list that are supported by known_hosts keys. */ if (options.hostkeyalgorithms == NULL || options.hostkeyalgorithms[0] == '-' || options.hostkeyalgorithms[0] == '+') use_known_hosts_order = 1; /* Expand or fill in HostkeyAlgorithms */ all_key = sshkey_alg_list(0, 0, 1, ','); if ((r = kex_assemble_names(&options.hostkeyalgorithms, kex_default_pk_alg(), all_key)) != 0) fatal_fr(r, "kex_assemble_namelist"); free(all_key); if (use_known_hosts_order) hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms, options.ciphers, options.macs, compression_alg_list(options.compression), hkalgs ? hkalgs : options.hostkeyalgorithms); free(hkalgs); /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); #ifdef WITH_OPENSSL ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); kex_proposal_free_entries(myproposal); #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || (r = sshpkt_put_cstring(ssh, "markus")) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send packet"); #endif } /* * Authenticate user */ typedef struct cauthctxt Authctxt; typedef struct cauthmethod Authmethod; typedef struct identity Identity; typedef struct idlist Idlist; struct identity { TAILQ_ENTRY(identity) next; int agent_fd; /* >=0 if agent supports key */ struct sshkey *key; /* public/private key */ char *filename; /* comment for agent-only keys */ int tried; int isprivate; /* key points to the private key */ int userprovided; }; TAILQ_HEAD(idlist, identity); struct cauthctxt { const char *server_user; const char *local_user; const char *host; const char *service; struct cauthmethod *method; sig_atomic_t success; char *authlist; #ifdef GSSAPI /* gssapi */ gss_OID_set gss_supported_mechs; u_int mech_tried; #endif /* pubkey */ struct idlist keys; int agent_fd; /* hostbased */ Sensitive *sensitive; char *oktypes, *ktypes; const char *active_ktype; /* kbd-interactive */ int info_req_seen; int attempt_kbdint; /* password */ int attempt_passwd; /* generic */ void *methoddata; }; struct cauthmethod { char *name; /* string to compare against server's list */ int (*userauth)(struct ssh *ssh); void (*cleanup)(struct ssh *ssh); int *enabled; /* flag in option struct that enables method */ int *batch_flag; /* flag in option struct that disables method */ }; static int input_userauth_service_accept(int, u_int32_t, struct ssh *); static int input_userauth_success(int, u_int32_t, struct ssh *); static int input_userauth_failure(int, u_int32_t, struct ssh *); static int input_userauth_banner(int, u_int32_t, struct ssh *); static int input_userauth_error(int, u_int32_t, struct ssh *); static int input_userauth_info_req(int, u_int32_t, struct ssh *); static int input_userauth_pk_ok(int, u_int32_t, struct ssh *); static int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); static int userauth_none(struct ssh *); static int userauth_pubkey(struct ssh *); static int userauth_passwd(struct ssh *); static int userauth_kbdint(struct ssh *); static int userauth_hostbased(struct ssh *); #ifdef GSSAPI static int userauth_gssapi(struct ssh *); static void userauth_gssapi_cleanup(struct ssh *); static int input_gssapi_response(int type, u_int32_t, struct ssh *); static int input_gssapi_token(int type, u_int32_t, struct ssh *); static int input_gssapi_error(int, u_int32_t, struct ssh *); static int input_gssapi_errtok(int, u_int32_t, struct ssh *); #endif void userauth(struct ssh *, char *); static void pubkey_cleanup(struct ssh *); static int sign_and_send_pubkey(struct ssh *ssh, Identity *); static void pubkey_prepare(struct ssh *, Authctxt *); static void pubkey_reset(Authctxt *); static struct sshkey *load_identity_file(Identity *); static Authmethod *authmethod_get(char *authlist); static Authmethod *authmethod_lookup(const char *name); static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI {"gssapi-with-mic", userauth_gssapi, userauth_gssapi_cleanup, &options.gss_authentication, NULL}, #endif {"hostbased", userauth_hostbased, NULL, &options.hostbased_authentication, NULL}, {"publickey", userauth_pubkey, NULL, &options.pubkey_authentication, NULL}, {"keyboard-interactive", userauth_kbdint, NULL, &options.kbd_interactive_authentication, &options.batch_mode}, {"password", userauth_passwd, NULL, &options.password_authentication, &options.batch_mode}, {"none", userauth_none, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL} }; void ssh_userauth2(struct ssh *ssh, const char *local_user, const char *server_user, char *host, Sensitive *sensitive) { Authctxt authctxt; int r; if (options.preferred_authentications == NULL) options.preferred_authentications = authmethods_get(); /* setup authentication context */ memset(&authctxt, 0, sizeof(authctxt)); authctxt.server_user = server_user; authctxt.local_user = local_user; authctxt.host = host; authctxt.service = "ssh-connection"; /* service name */ authctxt.success = 0; authctxt.method = authmethod_lookup("none"); authctxt.authlist = NULL; authctxt.methoddata = NULL; authctxt.sensitive = sensitive; authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; authctxt.info_req_seen = 0; authctxt.attempt_kbdint = 0; authctxt.attempt_passwd = 0; #if GSSAPI authctxt.gss_supported_mechs = NULL; authctxt.mech_tried = 0; #endif authctxt.agent_fd = -1; if (authctxt.method == NULL) fatal_f("internal error: cannot send userauth none request"); if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); ssh->authctxt = &authctxt; ssh_dispatch_init(ssh, &input_userauth_error); ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ pubkey_cleanup(ssh); #ifdef GSSAPI if (authctxt.gss_supported_mechs != NULL) { u_int ms; gss_release_oid_set(&ms, &authctxt.gss_supported_mechs); authctxt.gss_supported_mechs = NULL; } #endif ssh->authctxt = NULL; ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); if (!authctxt.success) fatal("Authentication failed."); if (ssh_packet_connection_is_on_socket(ssh)) { verbose("Authenticated to %s ([%s]:%d) using \"%s\".", host, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), authctxt.method->name); } else { verbose("Authenticated to %s (via proxy) using \"%s\".", host, authctxt.method->name); } } static int input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) { int r; if (ssh_packet_remaining(ssh) > 0) { char *reply; if ((r = sshpkt_get_cstring(ssh, &reply, NULL)) != 0) goto out; debug2("service_accept: %s", reply); free(reply); } else { debug2("buggy server: service_accept w/o service"); } if ((r = sshpkt_get_end(ssh)) != 0) goto out; debug("SSH2_MSG_SERVICE_ACCEPT received"); /* initial userauth request */ userauth_none(ssh); /* accept EXT_INFO at any time during userauth */ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, ssh->kex->ext_info_s ? &kex_input_ext_info : &input_userauth_error); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); r = 0; out: return r; } void userauth(struct ssh *ssh, char *authlist) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; if (authctxt->method != NULL && authctxt->method->cleanup != NULL) authctxt->method->cleanup(ssh); free(authctxt->methoddata); authctxt->methoddata = NULL; if (authlist == NULL) { authlist = authctxt->authlist; } else { free(authctxt->authlist); authctxt->authlist = authlist; } for (;;) { Authmethod *method = authmethod_get(authlist); if (method == NULL) fatal("%s@%s: Permission denied (%s).", authctxt->server_user, authctxt->host, authlist); authctxt->method = method; /* reset the per method handler */ ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_PER_METHOD_MIN, SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL); /* and try new method */ if (method->userauth(ssh) != 0) { debug2("we sent a %s packet, wait for reply", method->name); break; } else { debug2("we did not send a packet, disable method"); method->enabled = NULL; } } } static int input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { fatal_f("bad message during authentication: type %d", type); return 0; } static int input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) { char *msg = NULL; size_t len; int r; debug3_f("entering"); if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) goto out; if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) fmprintf(stderr, "%s", msg); r = 0; out: free(msg); return r; } static int input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal_f("no authentication context"); free(authctxt->authlist); authctxt->authlist = NULL; if (authctxt->method != NULL && authctxt->method->cleanup != NULL) authctxt->method->cleanup(ssh); free(authctxt->methoddata); authctxt->methoddata = NULL; authctxt->success = 1; /* break out */ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error); return 0; } #if 0 static int input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal_f("no authentication context"); fatal("Unexpected authentication success during %s.", authctxt->method->name); return 0; } #endif static int input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *authlist = NULL; u_char partial; if (authctxt == NULL) fatal("input_userauth_failure: no authentication context"); if (sshpkt_get_cstring(ssh, &authlist, NULL) != 0 || sshpkt_get_u8(ssh, &partial) != 0 || sshpkt_get_end(ssh) != 0) goto out; if (partial != 0) { verbose("Authenticated using \"%s\" with partial success.", authctxt->method->name); /* reset state */ pubkey_reset(authctxt); } debug("Authentications that can continue: %s", authlist); userauth(ssh, authlist); authlist = NULL; out: free(authlist); return 0; } /* * Format an identity for logging including filename, key type, fingerprint * and location (agent, etc.). Caller must free. */ static char * format_identity(Identity *id) { char *fp = NULL, *ret = NULL; const char *note = ""; if (id->key != NULL) { fp = sshkey_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT); } if (id->key) { if ((id->key->flags & SSHKEY_FLAG_EXT) != 0) note = " token"; else if (sshkey_is_sk(id->key)) note = " authenticator"; } xasprintf(&ret, "%s %s%s%s%s%s%s", id->filename, id->key ? sshkey_type(id->key) : "", id->key ? " " : "", fp ? fp : "", id->userprovided ? " explicit" : "", note, id->agent_fd != -1 ? " agent" : ""); free(fp); return ret; } static int input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; struct sshkey *key = NULL; Identity *id = NULL; int pktype, found = 0, sent = 0; size_t blen; char *pkalg = NULL, *fp = NULL, *ident = NULL; u_char *pkblob = NULL; int r; if (authctxt == NULL) fatal("input_userauth_pk_ok: no authentication context"); if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto done; if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { debug_f("server sent unknown pkalg %s", pkalg); r = SSH_ERR_INVALID_FORMAT; goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { debug_r(r, "no key from blob. pkalg %s", pkalg); goto done; } if (key->type != pktype) { error("input_userauth_pk_ok: type mismatch " "for decoded key (received %d, expected %d)", key->type, pktype); r = SSH_ERR_INVALID_FORMAT; goto done; } /* * search keys in the reverse order, because last candidate has been * moved to the end of the queue. this also avoids confusion by * duplicate keys */ TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) { if (sshkey_equal(key, id->key)) { found = 1; break; } } if (!found || id == NULL) { fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); error_f("server replied with unknown key: %s %s", sshkey_type(key), fp == NULL ? "" : fp); r = SSH_ERR_INVALID_FORMAT; goto done; } ident = format_identity(id); debug("Server accepts key: %s", ident); sent = sign_and_send_pubkey(ssh, id); r = 0; done: sshkey_free(key); free(ident); free(fp); free(pkalg); free(pkblob); /* try another method if we did not send a packet */ if (r == 0 && sent == 0) userauth(ssh, NULL); return r; } #ifdef GSSAPI static int userauth_gssapi(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Gssctxt *gssctxt = NULL; OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; /* Try one GSSAPI method at a time, rather than sending them all at * once. */ if (authctxt->gss_supported_mechs == NULL) gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && !ok) { mech = &authctxt->gss_supported_mechs-> elements[authctxt->mech_tried]; /* My DER encoding requires length<128 */ if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, mech, authctxt->host)) { ok = 1; /* Mechanism works */ } else { authctxt->mech_tried++; } } if (!ok || mech == NULL) return 0; authctxt->methoddata=(void *)gssctxt; if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u32(ssh, 1)) != 0 || (r = sshpkt_put_u32(ssh, (mech->length) + 2)) != 0 || (r = sshpkt_put_u8(ssh, SSH_GSS_OIDTYPE)) != 0 || (r = sshpkt_put_u8(ssh, mech->length)) != 0 || (r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); authctxt->mech_tried++; /* Move along to next candidate */ return 1; } static void userauth_gssapi_cleanup(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Gssctxt *gssctxt = (Gssctxt *)authctxt->methoddata; ssh_gssapi_delete_ctx(&gssctxt); authctxt->methoddata = NULL; } static OM_uint32 process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt = authctxt->methoddata; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; gss_buffer_desc gssbuf; OM_uint32 status, ms, flags; int r; status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, recv_tok, &send_tok, &flags); if (send_tok.length > 0) { u_char type = GSS_ERROR(status) ? SSH2_MSG_USERAUTH_GSSAPI_ERRTOK : SSH2_MSG_USERAUTH_GSSAPI_TOKEN; if ((r = sshpkt_start(ssh, type)) != 0 || (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send %u packet", type); gss_release_buffer(&ms, &send_tok); } if (status == GSS_S_COMPLETE) { /* send either complete or MIC, depending on mechanism */ if (!(flags & GSS_C_INTEG_FLAG)) { if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send completion"); } else { struct sshbuf *b; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, "gssapi-with-mic", ssh->kex->session_id); if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) fatal_f("sshbuf_mutable_ptr failed"); gssbuf.length = sshbuf_len(b); status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic); if (!GSS_ERROR(status)) { if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC)) != 0 || (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send MIC"); } sshbuf_free(b); gss_release_buffer(&ms, &mic); } } return status; } static int input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; size_t oidlen; u_char *oidv = NULL; int r; if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); gssctxt = authctxt->methoddata; /* Setup our OID */ if ((r = sshpkt_get_string(ssh, &oidv, &oidlen)) != 0) goto done; if (oidlen <= 2 || oidv[0] != SSH_GSS_OIDTYPE || oidv[1] != oidlen - 2) { debug("Badly encoded mechanism OID received"); userauth(ssh, NULL); goto ok; } if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) fatal("Server returned different OID than expected"); if ((r = sshpkt_get_end(ssh)) != 0) goto done; if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) { /* Start again with next method on list */ debug("Trying to start again"); userauth(ssh, NULL); goto ok; } ok: r = 0; done: free(oidv); return r; } static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; gss_buffer_desc recv_tok; u_char *p = NULL; size_t len; OM_uint32 status; int r; if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; recv_tok.value = p; recv_tok.length = len; status = process_gssapi_token(ssh, &recv_tok); /* Start again with the next method in the list */ if (GSS_ERROR(status)) { userauth(ssh, NULL); /* ok */ } r = 0; out: free(p); return r; } static int input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; OM_uint32 ms; u_char *p = NULL; size_t len; int r; if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { free(p); return r; } /* Stick it into GSSAPI and see what it says */ recv_tok.value = p; recv_tok.length = len; (void)ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, &recv_tok, &send_tok, NULL); free(p); gss_release_buffer(&ms, &send_tok); /* Server will be returning a failed packet after this one */ return 0; } static int input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) { char *msg = NULL; char *lang = NULL; int r; if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* maj */ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* min */ (r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) goto out; r = sshpkt_get_end(ssh); debug("Server GSSAPI Error:\n%s", msg); out: free(msg); free(lang); return r; } #endif /* GSSAPI */ static int userauth_none(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; int r; /* initial userauth request */ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); return 1; } static int userauth_passwd(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; char *password, *prompt = NULL; const char *host = options.host_key_alias ? options.host_key_alias : authctxt->host; int r; if (authctxt->attempt_passwd++ >= options.number_of_password_prompts) return 0; if (authctxt->attempt_passwd != 1) error("Permission denied, please try again."); xasprintf(&prompt, "%s@%s's password: ", authctxt->server_user, host); password = read_passphrase(prompt, 0); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_put_cstring(ssh, password)) != 0 || (r = sshpkt_add_padding(ssh, 64)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); free(prompt); if (password != NULL) freezero(password, strlen(password)); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, &input_userauth_passwd_changereq); return 1; } /* * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST */ static int input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *info = NULL, *lang = NULL, *password = NULL, *retype = NULL; char prompt[256]; const char *host; int r; debug2("input_userauth_passwd_changereq"); if (authctxt == NULL) fatal("input_userauth_passwd_changereq: " "no authentication context"); host = options.host_key_alias ? options.host_key_alias : authctxt->host; if ((r = sshpkt_get_cstring(ssh, &info, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) goto out; if (strlen(info) > 0) logit("%s", info); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0) /* additional info */ goto out; snprintf(prompt, sizeof(prompt), "Enter %.30s@%.128s's old password: ", authctxt->server_user, host); password = read_passphrase(prompt, 0); if ((r = sshpkt_put_cstring(ssh, password)) != 0) goto out; freezero(password, strlen(password)); password = NULL; while (password == NULL) { snprintf(prompt, sizeof(prompt), "Enter %.30s@%.128s's new password: ", authctxt->server_user, host); password = read_passphrase(prompt, RP_ALLOW_EOF); if (password == NULL) { /* bail out */ r = 0; goto out; } snprintf(prompt, sizeof(prompt), "Retype %.30s@%.128s's new password: ", authctxt->server_user, host); retype = read_passphrase(prompt, 0); if (strcmp(password, retype) != 0) { freezero(password, strlen(password)); logit("Mismatch; try again, EOF to quit."); password = NULL; } freezero(retype, strlen(retype)); } if ((r = sshpkt_put_cstring(ssh, password)) != 0 || (r = sshpkt_add_padding(ssh, 64)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, &input_userauth_passwd_changereq); r = 0; out: if (password) freezero(password, strlen(password)); free(info); free(lang); return r; } /* * Select an algorithm for publickey signatures. * Returns algorithm (caller must free) or NULL if no mutual algorithm found. * * Call with ssh==NULL to ignore server-sig-algs extension list and * only attempt with the key's base signature type. */ static char * key_sig_algorithm(struct ssh *ssh, const struct sshkey *key) { char *allowed, *oallowed, *cp, *tmp, *alg = NULL; const char *server_sig_algs; /* * The signature algorithm will only differ from the key algorithm * for RSA keys/certs and when the server advertises support for * newer (SHA2) algorithms. */ if (ssh == NULL || ssh->kex->server_sig_algs == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || (key->type == KEY_RSA_CERT && (ssh->compat & SSH_BUG_SIGTYPE))) { /* Filter base key signature alg against our configuration */ return match_list(sshkey_ssh_name(key), options.pubkey_accepted_algos, NULL); } /* * Workaround OpenSSH 7.4 bug: this version supports RSA/SHA-2 but * fails to advertise it via SSH2_MSG_EXT_INFO. */ server_sig_algs = ssh->kex->server_sig_algs; if (key->type == KEY_RSA && (ssh->compat & SSH_BUG_SIGTYPE74)) server_sig_algs = "rsa-sha2-256,rsa-sha2-512"; /* * For RSA keys/certs, since these might have a different sig type: * find the first entry in PubkeyAcceptedAlgorithms of the right type * that also appears in the supported signature algorithms list from * the server. */ oallowed = allowed = xstrdup(options.pubkey_accepted_algos); while ((cp = strsep(&allowed, ",")) != NULL) { if (sshkey_type_from_name(cp) != key->type) continue; tmp = match_list(sshkey_sigalg_by_name(cp), server_sig_algs, NULL); if (tmp != NULL) alg = xstrdup(cp); free(tmp); if (alg != NULL) break; } free(oallowed); return alg; } static int identity_sign(struct identity *id, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat, const char *alg) { struct sshkey *sign_key = NULL, *prv = NULL; int is_agent = 0, retried = 0, r = SSH_ERR_INTERNAL_ERROR; struct notifier_ctx *notifier = NULL; char *fp = NULL, *pin = NULL, *prompt = NULL; *sigp = NULL; *lenp = 0; /* The agent supports this key. */ if (id->key != NULL && id->agent_fd != -1) { return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, data, datalen, alg, compat); } /* * We have already loaded the private key or the private key is * stored in external hardware. */ if (id->key != NULL && (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) { sign_key = id->key; is_agent = 1; } else { /* Load the private key from the file. */ if ((prv = load_identity_file(id)) == NULL) return SSH_ERR_KEY_NOT_FOUND; if (id->key != NULL && !sshkey_equal_public(prv, id->key)) { error_f("private key %s contents do not match public", id->filename); r = SSH_ERR_KEY_NOT_FOUND; goto out; } sign_key = prv; } retry_pin: /* Prompt for touch for non-agent FIDO keys that request UP */ if (!is_agent && sshkey_is_sk(sign_key) && (sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { /* XXX should batch mode just skip these? */ if ((fp = sshkey_fingerprint(sign_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); notifier = notify_start(options.batch_mode, "Confirm user presence for key %s %s", sshkey_type(sign_key), fp); free(fp); } if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, alg, options.sk_provider, pin, compat)) != 0) { debug_fr(r, "sshkey_sign"); if (!retried && pin == NULL && !is_agent && sshkey_is_sk(sign_key) && r == SSH_ERR_KEY_WRONG_PASSPHRASE) { notify_complete(notifier, NULL); notifier = NULL; xasprintf(&prompt, "Enter PIN for %s key %s: ", sshkey_type(sign_key), id->filename); pin = read_passphrase(prompt, 0); retried = 1; goto retry_pin; } goto out; } /* * PKCS#11 tokens may not support all signature algorithms, * so check what we get back. */ if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) { debug_fr(r, "sshkey_check_sigtype"); goto out; } /* success */ r = 0; out: free(prompt); if (pin != NULL) freezero(pin, strlen(pin)); notify_complete(notifier, r == 0 ? "User presence confirmed" : NULL); sshkey_free(prv); return r; } static int id_filename_matches(Identity *id, Identity *private_id) { static const char * const suffixes[] = { ".pub", "-cert.pub", NULL }; size_t len = strlen(id->filename), plen = strlen(private_id->filename); size_t i, slen; if (strcmp(id->filename, private_id->filename) == 0) return 1; for (i = 0; suffixes[i]; i++) { slen = strlen(suffixes[i]); if (len > slen && plen == len - slen && strcmp(id->filename + (len - slen), suffixes[i]) == 0 && memcmp(id->filename, private_id->filename, plen) == 0) return 1; } return 0; } static int sign_and_send_pubkey(struct ssh *ssh, Identity *id) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; struct sshbuf *b = NULL; Identity *private_id, *sign_id = NULL; u_char *signature = NULL; size_t slen = 0, skip = 0; int r, fallback_sigtype, sent = 0; char *alg = NULL, *fp = NULL; const char *loc = "", *method = "publickey"; int hostbound = 0; /* prefer host-bound pubkey signatures if supported by server */ if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0 && (options.pubkey_authentication & SSH_PUBKEY_AUTH_HBOUND) != 0) { hostbound = 1; method = "publickey-hostbound-v00@openssh.com"; } if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) return 0; debug3_f("using %s with %s %s", method, sshkey_type(id->key), fp); /* * If the key is an certificate, try to find a matching private key * and use it to complete the signature. * If no such private key exists, fall back to trying the certificate * key itself in case it has a private half already loaded. * This will try to set sign_id to the private key that will perform * the signature. */ if (sshkey_is_cert(id->key)) { TAILQ_FOREACH(private_id, &authctxt->keys, next) { if (sshkey_equal_public(id->key, private_id->key) && id->key->type != private_id->key->type) { sign_id = private_id; break; } } /* * Exact key matches are preferred, but also allow * filename matches for non-PKCS#11/agent keys that * didn't load public keys. This supports the case * of keeping just a private key file and public * certificate on disk. */ if (sign_id == NULL && !id->isprivate && id->agent_fd == -1 && (id->key->flags & SSHKEY_FLAG_EXT) == 0) { TAILQ_FOREACH(private_id, &authctxt->keys, next) { if (private_id->key == NULL && id_filename_matches(id, private_id)) { sign_id = private_id; break; } } } if (sign_id != NULL) { debug2_f("using private key \"%s\"%s for " "certificate", sign_id->filename, sign_id->agent_fd != -1 ? " from agent" : ""); } else { debug_f("no separate private key for certificate " "\"%s\"", id->filename); } } /* * If the above didn't select another identity to do the signing * then default to the one we started with. */ if (sign_id == NULL) sign_id = id; /* assemble and sign data */ for (fallback_sigtype = 0; fallback_sigtype <= 1; fallback_sigtype++) { free(alg); slen = 0; signature = NULL; if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, id->key)) == NULL) { error_f("no mutual signature supported"); goto out; } debug3_f("signing using %s %s", alg, fp); sshbuf_free(b); if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (ssh->compat & SSH_OLD_SESSIONID) { if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0) fatal_fr(r, "sshbuf_putb"); } else { if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0) fatal_fr(r, "sshbuf_put_stringb"); } skip = sshbuf_len(b); if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || (r = sshbuf_put_cstring(b, method)) != 0 || (r = sshbuf_put_u8(b, 1)) != 0 || (r = sshbuf_put_cstring(b, alg)) != 0 || (r = sshkey_puts(id->key, b)) != 0) { fatal_fr(r, "assemble signed data"); } if (hostbound) { if (ssh->kex->initial_hostkey == NULL) { fatal_f("internal error: initial hostkey " "not recorded"); } if ((r = sshkey_puts(ssh->kex->initial_hostkey, b)) != 0) fatal_fr(r, "assemble %s hostkey", method); } /* generate signature */ r = identity_sign(sign_id, &signature, &slen, sshbuf_ptr(b), sshbuf_len(b), ssh->compat, alg); if (r == 0) break; else if (r == SSH_ERR_KEY_NOT_FOUND) goto out; /* soft failure */ else if (r == SSH_ERR_SIGN_ALG_UNSUPPORTED && !fallback_sigtype) { if (sign_id->agent_fd != -1) loc = "agent "; else if ((sign_id->key->flags & SSHKEY_FLAG_EXT) != 0) loc = "token "; logit("%skey %s %s returned incorrect signature type", loc, sshkey_type(id->key), fp); continue; } error_fr(r, "signing failed for %s \"%s\"%s", sshkey_type(sign_id->key), sign_id->filename, id->agent_fd != -1 ? " from agent" : ""); goto out; } if (slen == 0 || signature == NULL) /* shouldn't happen */ fatal_f("no signature"); /* append signature */ if ((r = sshbuf_put_string(b, signature, slen)) != 0) fatal_fr(r, "append signature"); #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif /* skip session id and packet type */ if ((r = sshbuf_consume(b, skip + 1)) != 0) fatal_fr(r, "consume"); /* put remaining data from buffer into packet */ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_putb(ssh, b)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "enqueue request"); /* success */ sent = 1; out: free(fp); free(alg); sshbuf_free(b); freezero(signature, slen); return sent; } static int send_pubkey_test(struct ssh *ssh, Identity *id) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; u_char *blob = NULL; char *alg = NULL; size_t bloblen; u_int have_sig = 0; int sent = 0, r; if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) { debug_f("no mutual signature algorithm"); goto out; } if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) { /* we cannot handle this key */ debug3_f("cannot handle key"); goto out; } /* register callback for USERAUTH_PK_OK message */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u8(ssh, have_sig)) != 0 || (r = sshpkt_put_cstring(ssh, alg)) != 0 || (r = sshpkt_put_string(ssh, blob, bloblen)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); sent = 1; out: free(alg); free(blob); return sent; } static struct sshkey * load_identity_file(Identity *id) { struct sshkey *private = NULL; char prompt[300], *passphrase, *comment; int r, quit = 0, i; struct stat st; if (stat(id->filename, &st) == -1) { do_log2(id->userprovided ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_DEBUG3, "no such identity: %s: %s", id->filename, strerror(errno)); return NULL; } snprintf(prompt, sizeof prompt, "Enter passphrase for key '%.100s': ", id->filename); for (i = 0; i <= options.number_of_password_prompts; i++) { if (i == 0) passphrase = ""; else { passphrase = read_passphrase(prompt, 0); if (*passphrase == '\0') { debug2("no passphrase given, try next key"); free(passphrase); break; } } switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename, passphrase, &private, &comment))) { case 0: break; case SSH_ERR_KEY_WRONG_PASSPHRASE: if (options.batch_mode) { quit = 1; break; } if (i != 0) debug2("bad passphrase given, try again..."); break; case SSH_ERR_SYSTEM_ERROR: if (errno == ENOENT) { debug2_r(r, "Load key \"%s\"", id->filename); quit = 1; break; } /* FALLTHROUGH */ default: error_r(r, "Load key \"%s\"", id->filename); quit = 1; break; } if (private != NULL && sshkey_is_sk(private) && options.sk_provider == NULL) { debug("key \"%s\" is an authenticator-hosted key, " "but no provider specified", id->filename); sshkey_free(private); private = NULL; quit = 1; } if (!quit && (r = sshkey_check_rsa_length(private, options.required_rsa_size)) != 0) { debug_fr(r, "Skipping key %s", id->filename); sshkey_free(private); private = NULL; quit = 1; } if (!quit && private != NULL && id->agent_fd == -1 && !(id->key && id->isprivate)) maybe_add_key_to_agent(id->filename, private, comment, passphrase); if (i > 0) freezero(passphrase, strlen(passphrase)); free(comment); if (private != NULL || quit) break; } return private; } static int key_type_allowed_by_config(struct sshkey *key) { if (match_pattern_list(sshkey_ssh_name(key), options.pubkey_accepted_algos, 0) == 1) return 1; /* RSA keys/certs might be allowed by alternate signature types */ switch (key->type) { case KEY_RSA: if (match_pattern_list("rsa-sha2-512", options.pubkey_accepted_algos, 0) == 1) return 1; if (match_pattern_list("rsa-sha2-256", options.pubkey_accepted_algos, 0) == 1) return 1; break; case KEY_RSA_CERT: if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", options.pubkey_accepted_algos, 0) == 1) return 1; if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", options.pubkey_accepted_algos, 0) == 1) return 1; break; } return 0; } /* obtain a list of keys from the agent */ static int get_agent_identities(struct ssh *ssh, int *agent_fdp, struct ssh_identitylist **idlistp) { int r, agent_fd; struct ssh_identitylist *idlist; if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { if (r != SSH_ERR_AGENT_NOT_PRESENT) debug_fr(r, "ssh_get_authentication_socket"); return r; } if ((r = ssh_agent_bind_hostkey(agent_fd, ssh->kex->initial_hostkey, ssh->kex->session_id, ssh->kex->initial_sig, 0)) == 0) debug_f("bound agent to hostkey"); else debug2_fr(r, "ssh_agent_bind_hostkey"); if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { debug_fr(r, "ssh_fetch_identitylist"); close(agent_fd); return r; } /* success */ *agent_fdp = agent_fd; *idlistp = idlist; debug_f("agent returned %zu keys", idlist->nkeys); return 0; } /* * try keys in the following order: * 1. certificates listed in the config file * 2. other input certificates * 3. agent keys that are found in the config file * 4. other agent keys * 5. keys that are only listed in the config file */ static void pubkey_prepare(struct ssh *ssh, Authctxt *authctxt) { struct identity *id, *id2, *tmp; struct idlist agent, files, *preferred; struct sshkey *key; int disallowed, agent_fd = -1, i, r, found; size_t j; struct ssh_identitylist *idlist; char *cp, *ident; TAILQ_INIT(&agent); /* keys from the agent */ TAILQ_INIT(&files); /* keys from the config file */ preferred = &authctxt->keys; TAILQ_INIT(preferred); /* preferred order of keys */ /* list of keys stored in the filesystem and PKCS#11 */ for (i = 0; i < options.num_identity_files; i++) { key = options.identity_keys[i]; if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER) { debug_f("ignoring certificate %s: not a user " "certificate", options.identity_files[i]); continue; } if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { debug_f("ignoring authenticator-hosted key %s as no " "SecurityKeyProvider has been specified", options.identity_files[i]); continue; } options.identity_keys[i] = NULL; id = xcalloc(1, sizeof(*id)); id->agent_fd = -1; id->key = key; id->filename = xstrdup(options.identity_files[i]); id->userprovided = options.identity_file_userprovided[i]; TAILQ_INSERT_TAIL(&files, id, next); } /* list of certificates specified by user */ for (i = 0; i < options.num_certificate_files; i++) { key = options.certificates[i]; if (!sshkey_is_cert(key) || key->cert == NULL || key->cert->type != SSH2_CERT_TYPE_USER) { debug_f("ignoring certificate %s: not a user " "certificate", options.identity_files[i]); continue; } if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { debug_f("ignoring authenticator-hosted key " "certificate %s as no " "SecurityKeyProvider has been specified", options.identity_files[i]); continue; } id = xcalloc(1, sizeof(*id)); id->agent_fd = -1; id->key = key; id->filename = xstrdup(options.certificate_files[i]); id->userprovided = options.certificate_file_userprovided[i]; TAILQ_INSERT_TAIL(preferred, id, next); } /* list of keys supported by the agent */ if ((r = get_agent_identities(ssh, &agent_fd, &idlist)) == 0) { for (j = 0; j < idlist->nkeys; j++) { if ((r = sshkey_check_rsa_length(idlist->keys[j], options.required_rsa_size)) != 0) { debug_fr(r, "ignoring %s agent key", sshkey_ssh_name(idlist->keys[j])); continue; } found = 0; TAILQ_FOREACH(id, &files, next) { /* * agent keys from the config file are * preferred */ if (sshkey_equal(idlist->keys[j], id->key)) { TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); id->agent_fd = agent_fd; found = 1; break; } } if (!found && !options.identities_only) { id = xcalloc(1, sizeof(*id)); /* XXX "steals" key/comment from idlist */ id->key = idlist->keys[j]; id->filename = idlist->comments[j]; idlist->keys[j] = NULL; idlist->comments[j] = NULL; id->agent_fd = agent_fd; TAILQ_INSERT_TAIL(&agent, id, next); } } ssh_free_identitylist(idlist); /* append remaining agent keys */ TAILQ_CONCAT(preferred, &agent, next); authctxt->agent_fd = agent_fd; } /* Prefer PKCS11 keys that are explicitly listed */ TAILQ_FOREACH_SAFE(id, &files, next, tmp) { if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0) continue; found = 0; TAILQ_FOREACH(id2, &files, next) { if (id2->key == NULL || (id2->key->flags & SSHKEY_FLAG_EXT) != 0) continue; if (sshkey_equal(id->key, id2->key)) { TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); found = 1; break; } } /* If IdentitiesOnly set and key not found then don't use it */ if (!found && options.identities_only) { TAILQ_REMOVE(&files, id, next); freezero(id, sizeof(*id)); } } /* append remaining keys from the config file */ TAILQ_CONCAT(preferred, &files, next); /* finally, filter by PubkeyAcceptedAlgorithms */ TAILQ_FOREACH_SAFE(id, preferred, next, id2) { disallowed = 0; cp = NULL; if (id->key == NULL) continue; if (!key_type_allowed_by_config(id->key)) { debug("Skipping %s key %s - corresponding algorithm " "not in PubkeyAcceptedAlgorithms", sshkey_ssh_name(id->key), id->filename); disallowed = 1; } else if (ssh->kex->server_sig_algs != NULL && (cp = key_sig_algorithm(ssh, id->key)) == NULL) { debug("Skipping %s key %s - corresponding algorithm " "not supported by server", sshkey_ssh_name(id->key), id->filename); disallowed = 1; } free(cp); if (!disallowed) continue; /* remove key */ TAILQ_REMOVE(preferred, id, next); sshkey_free(id->key); free(id->filename); memset(id, 0, sizeof(*id)); } /* List the keys we plan on using */ TAILQ_FOREACH_SAFE(id, preferred, next, id2) { ident = format_identity(id); debug("Will attempt key: %s", ident); free(ident); } debug2_f("done"); } static void pubkey_cleanup(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Identity *id; if (authctxt->agent_fd != -1) { ssh_close_authentication_socket(authctxt->agent_fd); authctxt->agent_fd = -1; } for (id = TAILQ_FIRST(&authctxt->keys); id; id = TAILQ_FIRST(&authctxt->keys)) { TAILQ_REMOVE(&authctxt->keys, id, next); sshkey_free(id->key); free(id->filename); free(id); } } static void pubkey_reset(Authctxt *authctxt) { Identity *id; TAILQ_FOREACH(id, &authctxt->keys, next) id->tried = 0; } static int userauth_pubkey(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Identity *id; int sent = 0; char *ident; static int prepared; if (!prepared) { pubkey_prepare(ssh, authctxt); prepared = 1; } while ((id = TAILQ_FIRST(&authctxt->keys))) { if (id->tried++) return (0); /* move key to the end of the queue */ TAILQ_REMOVE(&authctxt->keys, id, next); TAILQ_INSERT_TAIL(&authctxt->keys, id, next); /* * send a test message if we have the public key. for * encrypted keys we cannot do this and have to load the * private key instead */ if (id->key != NULL) { ident = format_identity(id); debug("Offering public key: %s", ident); free(ident); sent = send_pubkey_test(ssh, id); } else { debug("Trying private key: %s", id->filename); id->key = load_identity_file(id); if (id->key != NULL) { id->isprivate = 1; sent = sign_and_send_pubkey(ssh, id); sshkey_free(id->key); id->key = NULL; id->isprivate = 0; } } if (sent) return (sent); } return (0); } /* * Send userauth request message specifying keyboard-interactive method. */ static int userauth_kbdint(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; int r; if (authctxt->attempt_kbdint++ >= options.number_of_password_prompts) return 0; /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ if (authctxt->attempt_kbdint > 1 && !authctxt->info_req_seen) { debug3("userauth_kbdint: disable: no info_req_seen"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); return 0; } debug2("userauth_kbdint"); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* lang */ (r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ? options.kbd_interactive_devices : "")) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); return 1; } /* * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ static int input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *name = NULL, *inst = NULL, *lang = NULL, *prompt = NULL; char *display_prompt = NULL, *response = NULL; u_char echo = 0; u_int num_prompts, i; int r; debug2_f("entering"); if (authctxt == NULL) fatal_f("no authentication context"); authctxt->info_req_seen = 1; if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &inst, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) goto out; if (strlen(name) > 0) logit("%s", name); if (strlen(inst) > 0) logit("%s", inst); if ((r = sshpkt_get_u32(ssh, &num_prompts)) != 0) goto out; /* * Begin to build info response packet based on prompts requested. * We commit to providing the correct number of responses, so if * further on we run into a problem that prevents this, we have to * be sure and clean this up and send a correct error response. */ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE)) != 0 || (r = sshpkt_put_u32(ssh, num_prompts)) != 0) goto out; debug2_f("num_prompts %d", num_prompts); for (i = 0; i < num_prompts; i++) { if ((r = sshpkt_get_cstring(ssh, &prompt, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &echo)) != 0) goto out; if (asmprintf(&display_prompt, INT_MAX, NULL, "(%s@%s) %s", authctxt->server_user, options.host_key_alias ? options.host_key_alias : authctxt->host, prompt) == -1) fatal_f("asmprintf failed"); response = read_passphrase(display_prompt, echo ? RP_ECHO : 0); if ((r = sshpkt_put_cstring(ssh, response)) != 0) goto out; freezero(response, strlen(response)); free(prompt); free(display_prompt); display_prompt = response = prompt = NULL; } /* done with parsing incoming message. */ if ((r = sshpkt_get_end(ssh)) != 0 || (r = sshpkt_add_padding(ssh, 64)) != 0) goto out; r = sshpkt_send(ssh); out: if (response) freezero(response, strlen(response)); free(prompt); free(display_prompt); free(name); free(inst); free(lang); return r; } static int ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen) { struct sshbuf *b; struct stat st; pid_t pid; int r, to[2], from[2], status; int sock = ssh_packet_get_connection_in(ssh); u_char rversion = 0, version = 2; void (*osigchld)(int); *sigp = NULL; *lenp = 0; if (stat(_PATH_SSH_KEY_SIGN, &st) == -1) { error_f("not installed: %s", strerror(errno)); return -1; } if (fflush(stdout) != 0) { error_f("fflush: %s", strerror(errno)); return -1; } if (pipe(to) == -1) { error_f("pipe: %s", strerror(errno)); return -1; } if (pipe(from) == -1) { error_f("pipe: %s", strerror(errno)); return -1; } if ((pid = fork()) == -1) { error_f("fork: %s", strerror(errno)); return -1; } osigchld = ssh_signal(SIGCHLD, SIG_DFL); if (pid == 0) { close(from[0]); if (dup2(from[1], STDOUT_FILENO) == -1) fatal_f("dup2: %s", strerror(errno)); close(to[1]); if (dup2(to[0], STDIN_FILENO) == -1) fatal_f("dup2: %s", strerror(errno)); close(from[1]); close(to[0]); if (dup2(sock, STDERR_FILENO + 1) == -1) fatal_f("dup2: %s", strerror(errno)); sock = STDERR_FILENO + 1; if (fcntl(sock, F_SETFD, 0) == -1) /* keep the socket on exec */ debug3_f("fcntl F_SETFD: %s", strerror(errno)); closefrom(sock + 1); debug3_f("[child] pid=%ld, exec %s", (long)getpid(), _PATH_SSH_KEY_SIGN); execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *)NULL); fatal_f("exec(%s): %s", _PATH_SSH_KEY_SIGN, strerror(errno)); } close(from[1]); close(to[0]); sock = STDERR_FILENO + 1; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* send # of sock, data to be signed */ if ((r = sshbuf_put_u32(b, sock)) != 0 || (r = sshbuf_put_string(b, data, datalen)) != 0) fatal_fr(r, "buffer error"); if (ssh_msg_send(to[1], version, b) == -1) fatal_f("couldn't send request"); sshbuf_reset(b); r = ssh_msg_recv(from[0], b); close(from[0]); close(to[1]); if (r < 0) { error_f("no reply"); goto fail; } errno = 0; while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { error_f("waitpid %ld: %s", (long)pid, strerror(errno)); goto fail; } } if (!WIFEXITED(status)) { error_f("exited abnormally"); goto fail; } if (WEXITSTATUS(status) != 0) { error_f("exited with status %d", WEXITSTATUS(status)); goto fail; } if ((r = sshbuf_get_u8(b, &rversion)) != 0) { error_fr(r, "buffer error"); goto fail; } if (rversion != version) { error_f("bad version"); goto fail; } if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { error_fr(r, "buffer error"); fail: ssh_signal(SIGCHLD, osigchld); sshbuf_free(b); return -1; } ssh_signal(SIGCHLD, osigchld); sshbuf_free(b); return 0; } static int userauth_hostbased(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; struct sshkey *private = NULL; struct sshbuf *b = NULL; u_char *sig = NULL, *keyblob = NULL; char *fp = NULL, *chost = NULL, *lname = NULL; size_t siglen = 0, keylen = 0; int i, r, success = 0; if (authctxt->ktypes == NULL) { authctxt->oktypes = xstrdup(options.hostbased_accepted_algos); authctxt->ktypes = authctxt->oktypes; } /* * Work through each listed type pattern in HostbasedAcceptedAlgorithms, * trying each hostkey that matches the type in turn. */ for (;;) { if (authctxt->active_ktype == NULL) authctxt->active_ktype = strsep(&authctxt->ktypes, ","); if (authctxt->active_ktype == NULL || *authctxt->active_ktype == '\0') break; debug3_f("trying key type %s", authctxt->active_ktype); /* check for a useful key */ private = NULL; for (i = 0; i < authctxt->sensitive->nkeys; i++) { if (authctxt->sensitive->keys[i] == NULL || authctxt->sensitive->keys[i]->type == KEY_UNSPEC) continue; if (!sshkey_match_keyname_to_sigalgs( sshkey_ssh_name(authctxt->sensitive->keys[i]), authctxt->active_ktype)) continue; /* we take and free the key */ private = authctxt->sensitive->keys[i]; authctxt->sensitive->keys[i] = NULL; break; } /* Found one */ if (private != NULL) break; /* No more keys of this type; advance */ authctxt->active_ktype = NULL; } if (private == NULL) { free(authctxt->oktypes); authctxt->oktypes = authctxt->ktypes = NULL; authctxt->active_ktype = NULL; debug("No more client hostkeys for hostbased authentication."); goto out; } if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_f("sshkey_fingerprint failed"); goto out; } debug_f("trying hostkey %s %s using sigalg %s", sshkey_ssh_name(private), fp, authctxt->active_ktype); /* figure out a name for the client host */ lname = get_local_name(ssh_packet_get_connection_in(ssh)); if (lname == NULL) { error_f("cannot get local ipaddr/name"); goto out; } /* XXX sshbuf_put_stringf? */ xasprintf(&chost, "%s.", lname); debug2_f("chost %s", chost); /* construct data */ if ((b = sshbuf_new()) == NULL) { error_f("sshbuf_new failed"); goto out; } if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { error_fr(r, "sshkey_to_blob"); goto out; } if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || (r = sshbuf_put_cstring(b, authctxt->active_ktype)) != 0 || (r = sshbuf_put_string(b, keyblob, keylen)) != 0 || (r = sshbuf_put_cstring(b, chost)) != 0 || (r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { error_fr(r, "buffer error"); goto out; } #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif if ((r = ssh_keysign(ssh, private, &sig, &siglen, sshbuf_ptr(b), sshbuf_len(b))) != 0) { error("sign using hostkey %s %s failed", sshkey_ssh_name(private), fp); goto out; } if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->active_ktype)) != 0 || (r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 || (r = sshpkt_put_cstring(ssh, chost)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || (r = sshpkt_put_string(ssh, sig, siglen)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_fr(r, "packet error"); goto out; } success = 1; out: if (sig != NULL) freezero(sig, siglen); free(keyblob); free(lname); free(fp); free(chost); sshkey_free(private); sshbuf_free(b); return success; } /* find auth method */ /* * given auth method name, if configurable options permit this method fill * in auth_ident field and return true, otherwise return false. */ static int authmethod_is_enabled(Authmethod *method) { if (method == NULL) return 0; /* return false if options indicate this method is disabled */ if (method->enabled == NULL || *method->enabled == 0) return 0; /* return false if batch mode is enabled but method needs interactive mode */ if (method->batch_flag != NULL && *method->batch_flag != 0) return 0; return 1; } static Authmethod * authmethod_lookup(const char *name) { Authmethod *method = NULL; if (name != NULL) for (method = authmethods; method->name != NULL; method++) if (strcmp(name, method->name) == 0) return method; debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); return NULL; } /* XXX internal state */ static Authmethod *current = NULL; static char *supported = NULL; static char *preferred = NULL; /* * Given the authentication method list sent by the server, return the * next method we should try. If the server initially sends a nil list, * use a built-in default list. */ static Authmethod * authmethod_get(char *authlist) { char *name = NULL; u_int next; /* Use a suitable default if we're passed a nil list. */ if (authlist == NULL || strlen(authlist) == 0) authlist = options.preferred_authentications; if (supported == NULL || strcmp(authlist, supported) != 0) { debug3("start over, passed a different list %s", authlist); free(supported); supported = xstrdup(authlist); preferred = options.preferred_authentications; debug3("preferred %s", preferred); current = NULL; } else if (current != NULL && authmethod_is_enabled(current)) return current; for (;;) { if ((name = match_list(preferred, supported, &next)) == NULL) { debug("No more authentication methods to try."); current = NULL; return NULL; } preferred += next; debug3("authmethod_lookup %s", name); debug3("remaining preferred: %s", preferred); if ((current = authmethod_lookup(name)) != NULL && authmethod_is_enabled(current)) { debug3("authmethod_is_enabled %s", name); debug("Next authentication method: %s", name); free(name); return current; } free(name); } } static char * authmethods_get(void) { Authmethod *method = NULL; struct sshbuf *b; char *list; int r; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (method = authmethods; method->name != NULL; method++) { if (authmethod_is_enabled(method)) { if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", method->name)) != 0) fatal_fr(r, "buffer error"); } } if ((list = sshbuf_dup_string(b)) == NULL) fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); return list; } openssh-10.0p1/PaxHeaders.10889/sshd-auth.c100644 001750 001750 0000000003614775415623 0015220xustar0030 atime=1744182234.864087807 openssh-10.0p1/sshd-auth.c010064400017500001750000000550041477541562300136070ustar00djmdjm/* $OpenBSD: sshd-auth.c,v 1.3 2025/01/16 06:37:10 dtucker Exp $ */ /* * SSH2 implementation: * Privilege Separation: * * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #endif #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshpty.h" #include "packet.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "match.h" #include "servconf.h" #include "uidswap.h" #include "compat.h" #include "cipher.h" #include "digest.h" #include "sshkey.h" #include "kex.h" #include "authfile.h" #include "pathnames.h" #include "atomicio.h" #include "canohost.h" #include "hostfile.h" #include "auth.h" #include "authfd.h" #include "msg.h" #include "dispatch.h" #include "channels.h" #include "session.h" #include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "auth-options.h" #include "version.h" #include "ssherr.h" #include "sk-api.h" #include "srclimit.h" #include "ssh-sandbox.h" #include "dh.h" /* Privsep fds */ #define PRIVSEP_MONITOR_FD (STDERR_FILENO + 1) #define PRIVSEP_LOG_FD (STDERR_FILENO + 2) #define PRIVSEP_MIN_FREE_FD (STDERR_FILENO + 3) extern char *__progname; /* Server configuration options. */ ServerOptions options; /* Name of the server configuration file. */ char *config_file_name = _PATH_SERVER_CONFIG_FILE; /* * Debug mode flag. This can be set on the command line. If debug * mode is enabled, extra debugging output will be sent to the system * log, the daemon will not go to background, and will exit after processing * the first connection. */ int debug_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ static int inetd_flag = 0; /* Saved arguments to main(). */ static char **saved_argv; static int saved_argc; /* Daemon's agent connection */ int auth_sock = -1; static int have_agent = 0; u_int num_hostkeys; struct sshkey **host_pubkeys; /* all public host keys */ struct sshkey **host_certificates; /* all public host certificates */ /* record remote hostname or ip */ u_int utmp_len = HOST_NAME_MAX+1; /* variables used for privilege separation */ struct monitor *pmonitor = NULL; int privsep_is_preauth = 1; static int privsep_chroot = 1; /* global connection state and authentication contexts */ Authctxt *the_authctxt = NULL; struct ssh *the_active_state; /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ struct sshauthopt *auth_opts = NULL; /* sshd_config buffer */ struct sshbuf *cfg; /* Included files from the configuration file */ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); /* message to be displayed after login */ struct sshbuf *loginmsg; /* Prototypes for various functions defined later in this file. */ static void do_ssh2_kex(struct ssh *); /* Unprivileged user */ struct passwd *privsep_pw = NULL; #ifndef HAVE_PLEDGE static struct ssh_sandbox *box; #endif /* XXX stub */ int mm_is_monitor(void) { return 0; } static void privsep_child_demote(void) { gid_t gidset[1]; #ifndef HAVE_PLEDGE if ((box = ssh_sandbox_init(pmonitor)) == NULL) fatal_f("ssh_sandbox_init failed"); #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 * NB. Can't use setusercontext() after chroot. */ 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); } /* sandbox ourselves */ #ifdef HAVE_PLEDGE if (pledge("stdio", NULL) == -1) fatal_f("pledge()"); #else ssh_sandbox_child(box); #endif } static void append_hostkey_type(struct sshbuf *b, const char *s) { int r; if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) { debug3_f("%s key not permitted by HostkeyAlgorithms", s); return; } if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0) fatal_fr(r, "sshbuf_putf"); } static char * list_hostkey_types(void) { struct sshbuf *b; struct sshkey *key; char *ret; u_int i; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (i = 0; i < options.num_host_key_files; i++) { key = host_pubkeys[i]; if (key == NULL) continue; switch (key->type) { case KEY_RSA: /* for RSA we also support SHA2 signatures */ append_hostkey_type(b, "rsa-sha2-512"); append_hostkey_type(b, "rsa-sha2-256"); /* FALLTHROUGH */ case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: case KEY_XMSS: append_hostkey_type(b, sshkey_ssh_name(key)); break; } /* If the private key has a cert peer, then list that too */ key = host_certificates[i]; if (key == NULL) continue; switch (key->type) { case KEY_RSA_CERT: /* for RSA we also support SHA2 signatures */ append_hostkey_type(b, "rsa-sha2-512-cert-v01@openssh.com"); append_hostkey_type(b, "rsa-sha2-256-cert-v01@openssh.com"); /* FALLTHROUGH */ case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: case KEY_XMSS_CERT: append_hostkey_type(b, sshkey_ssh_name(key)); break; } } if ((ret = sshbuf_dup_string(b)) == NULL) fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); debug_f("%s", ret); return ret; } struct sshkey * get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) { u_int i; struct sshkey *key; for (i = 0; i < options.num_host_key_files; i++) { switch (type) { case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: case KEY_XMSS_CERT: key = host_certificates[i]; break; default: key = host_pubkeys[i]; break; } if (key == NULL || key->type != type) continue; switch (type) { case KEY_ECDSA: case KEY_ECDSA_SK: case KEY_ECDSA_CERT: case KEY_ECDSA_SK_CERT: if (key->ecdsa_nid != nid) continue; /* FALLTHROUGH */ default: return key; } } return NULL; } /* XXX remove */ struct sshkey * get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) { return NULL; } /* XXX remove */ struct sshkey * get_hostkey_by_index(int ind) { return NULL; } struct sshkey * get_hostkey_public_by_index(int ind, struct ssh *ssh) { if (ind < 0 || (u_int)ind >= options.num_host_key_files) return (NULL); return host_pubkeys[ind]; } int get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) { u_int i; for (i = 0; i < options.num_host_key_files; i++) { if (sshkey_is_cert(key)) { if (key == host_certificates[i] || (compare && host_certificates[i] && sshkey_equal(key, host_certificates[i]))) return (i); } else { if (key == host_pubkeys[i] || (compare && host_pubkeys[i] && sshkey_equal(key, host_pubkeys[i]))) return (i); } } return (-1); } static void usage(void) { fprintf(stderr, "%s, %s\n", SSH_VERSION, SSH_OPENSSL_VERSION); fprintf(stderr, "usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n" " [-E log_file] [-f config_file] [-g login_grace_time]\n" " [-h host_key_file] [-o option] [-p port] [-u len]\n" ); exit(1); } static void parse_hostkeys(struct sshbuf *hostkeys) { int r; u_int num_keys = 0; struct sshkey *k; const u_char *cp; size_t len; while (sshbuf_len(hostkeys) != 0) { if (num_keys > 2048) fatal_f("too many hostkeys"); host_pubkeys = xrecallocarray(host_pubkeys, num_keys, num_keys + 1, sizeof(*host_pubkeys)); host_certificates = xrecallocarray(host_certificates, num_keys, num_keys + 1, sizeof(*host_certificates)); /* public key */ k = NULL; if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0) fatal_fr(r, "extract pubkey"); if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0) fatal_fr(r, "parse pubkey"); host_pubkeys[num_keys] = k; if (k) debug2_f("key %u: %s", num_keys, sshkey_ssh_name(k)); /* certificate */ k = NULL; if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0) fatal_fr(r, "extract pubkey"); if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0) fatal_fr(r, "parse pubkey"); host_certificates[num_keys] = k; if (k) debug2_f("cert %u: %s", num_keys, sshkey_ssh_name(k)); num_keys++; } num_hostkeys = num_keys; } static void recv_privsep_state(struct ssh *ssh, struct sshbuf *conf, uint64_t *timing_secretp) { struct sshbuf *hostkeys; debug3_f("begin"); mm_get_state(ssh, &includes, conf, NULL, timing_secretp, &hostkeys, NULL, NULL, NULL, NULL); parse_hostkeys(hostkeys); sshbuf_free(hostkeys); debug3_f("done"); } /* * Main program for the daemon. */ int main(int ac, char **av) { struct ssh *ssh = NULL; extern char *optarg; extern int optind; int r, opt, have_key = 0; int sock_in = -1, sock_out = -1, rexeced_flag = 0; char *line, *logfile = NULL; u_int i; mode_t new_umask; Authctxt *authctxt; struct connection_info *connection_info = NULL; sigset_t sigmask; uint64_t timing_secret = 0; closefrom(PRIVSEP_MIN_FREE_FD); sigemptyset(&sigmask); sigprocmask(SIG_SETMASK, &sigmask, NULL); #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); #endif __progname = ssh_get_progname(av[0]); /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; saved_argv = xcalloc(ac + 1, sizeof(*saved_argv)); for (i = 0; (int)i < ac; i++) saved_argv[i] = xstrdup(av[i]); saved_argv[i] = NULL; seed_rng(); #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ compat_init_setproctitle(ac, av); av = saved_argv; #endif /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* Initialize configuration options to their default values. */ initialize_server_options(&options); /* Parse command-line arguments. */ while ((opt = getopt(ac, av, "C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) { switch (opt) { case '4': options.address_family = AF_INET; break; case '6': options.address_family = AF_INET6; break; case 'f': config_file_name = optarg; break; case 'c': servconf_add_hostcert("[command-line]", 0, &options, optarg); break; case 'd': if (debug_flag == 0) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) options.log_level++; break; case 'D': /* ignore */ break; case 'E': logfile = optarg; /* FALLTHROUGH */ case 'e': /* ignore */ break; case 'i': inetd_flag = 1; break; case 'r': /* ignore */ break; case 'R': rexeced_flag = 1; break; case 'Q': /* ignored */ break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'b': /* protocol 1, ignored */ break; case 'p': options.ports_from_cmdline = 1; if (options.num_ports >= MAX_PORTS) { fprintf(stderr, "too many ports.\n"); exit(1); } options.ports[options.num_ports++] = a2port(optarg); if (options.ports[options.num_ports-1] <= 0) { fprintf(stderr, "Bad port number.\n"); exit(1); } break; case 'g': if ((options.login_grace_time = convtime(optarg)) == -1) { fprintf(stderr, "Invalid login grace time.\n"); exit(1); } break; case 'k': /* protocol 1, ignored */ break; case 'h': servconf_add_hostkey("[command-line]", 0, &options, optarg, 1); break; case 't': case 'T': case 'G': fatal("test/dump modes not supported"); break; case 'C': connection_info = server_get_connection_info(ssh, 0, 0); if (parse_server_match_testspec(connection_info, optarg) == -1) exit(1); break; case 'u': utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL); if (utmp_len > HOST_NAME_MAX+1) { fprintf(stderr, "Invalid utmp length.\n"); exit(1); } break; case 'o': line = xstrdup(optarg); if (process_server_config_line(&options, line, "command-line", 0, NULL, NULL, &includes) != 0) exit(1); free(line); break; case 'V': fprintf(stderr, "%s, %s\n", SSH_VERSION, SSH_OPENSSL_VERSION); exit(0); default: usage(); break; } } if (!rexeced_flag) fatal("sshd-auth should not be executed directly"); #ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); #endif /* If requested, redirect the logs to the specified logfile. */ if (logfile != NULL) { char *cp, pid_s[32]; snprintf(pid_s, sizeof(pid_s), "%ld", (unsigned long)getpid()); cp = percent_expand(logfile, "p", pid_s, "P", "sshd-auth", (char *)NULL); log_redirect_stderr_to(cp); free(cp); } log_init(__progname, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_AUTH : options.log_facility, 1); /* XXX can't use monitor_init(); it makes fds */ pmonitor = xcalloc(1, sizeof(*pmonitor)); pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; pmonitor->m_recvfd = PRIVSEP_MONITOR_FD; pmonitor->m_log_sendfd = PRIVSEP_LOG_FD; set_log_handler(mm_log_handler, pmonitor); /* Check that there are no remaining arguments. */ if (optind < ac) { fprintf(stderr, "Extra argument %s.\n", av[optind]); exit(1); } /* Connection passed by stdin/out */ if (inetd_flag) { /* * NB. must be different fd numbers for the !socket case, * as packet_connection_is_on_socket() depends on this. */ sock_in = dup(STDIN_FILENO); sock_out = dup(STDOUT_FILENO); } else { /* rexec case; accept()ed socket in ancestor listener */ sock_in = sock_out = dup(STDIN_FILENO); } if (stdfd_devnull(1, 1, 0) == -1) error("stdfd_devnull failed"); debug("network sockets: %d, %d", sock_in, sock_out); /* * Register our connection. This turns encryption off because we do * not have a key. */ if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) fatal("Unable to create connection"); the_active_state = ssh; ssh_packet_set_server(ssh); pmonitor->m_pkex = &ssh->kex; /* Fetch our configuration */ if ((cfg = sshbuf_new()) == NULL) fatal("sshbuf_new config buf failed"); setproctitle("%s", "[session-auth early]"); recv_privsep_state(ssh, cfg, &timing_secret); parse_server_config(&options, "rexec", cfg, &includes, NULL, 1); /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); options.timing_secret = timing_secret; /* XXX eliminate from unpriv */ /* Reinit logging in case config set Level, Facility or Verbose. */ log_init(__progname, options.log_level, options.log_facility, 1); debug("sshd-auth version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); /* Store privilege separation user for later use if required. */ privsep_chroot = (getuid() == 0 || geteuid() == 0); if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { if (privsep_chroot || options.kerberos_authentication) fatal("Privilege separation user %s does not exist", SSH_PRIVSEP_USER); } else { privsep_pw = pwcopy(privsep_pw); freezero(privsep_pw->pw_passwd, strlen(privsep_pw->pw_passwd)); privsep_pw->pw_passwd = xstrdup("*"); } endpwent(); #ifdef WITH_OPENSSL if (options.moduli_file != NULL) dh_set_moduli_file(options.moduli_file); #endif if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) setenv(SSH_AUTHSOCKET_ENV_NAME, options.host_key_agent, 1); if ((r = ssh_get_authentication_socket(NULL)) == 0) have_agent = 1; else error_r(r, "Could not connect to agent \"%s\"", options.host_key_agent); } if (options.num_host_key_files != num_hostkeys) { fatal("internal error: hostkeys confused (config %u recvd %u)", options.num_host_key_files, num_hostkeys); } for (i = 0; i < options.num_host_key_files; i++) { if (host_pubkeys[i] != NULL) { have_key = 1; break; } } if (!have_key) fatal("internal error: received no hostkeys"); /* Ensure that umask disallows at least group and world write */ new_umask = umask(0077) | 0022; (void) umask(new_umask); /* Initialize the log (it is reinitialized below in case we forked). */ log_init(__progname, options.log_level, options.log_facility, 1); set_log_handler(mm_log_handler, pmonitor); for (i = 0; i < options.num_log_verbose; i++) log_verbose_add(options.log_verbose[i]); /* * Chdir to the root directory so that the current disk can be * unmounted if desired. */ if (chdir("/") == -1) error("chdir(\"/\"): %s", strerror(errno)); /* This is the child authenticating a new connection. */ setproctitle("%s", "[session-auth]"); /* Executed child processes don't need these. */ fcntl(sock_out, F_SETFD, FD_CLOEXEC); fcntl(sock_in, F_SETFD, FD_CLOEXEC); ssh_signal(SIGPIPE, SIG_IGN); 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); /* Prepare the channels layer */ channel_init_channels(ssh); channel_set_af(ssh, options.address_family); server_process_channel_timeouts(ssh); server_process_permitopen(ssh); ssh_packet_set_nonblocking(ssh); /* allocate authentication context */ authctxt = xcalloc(1, sizeof(*authctxt)); ssh->authctxt = authctxt; /* XXX global for cleanup, access from other modules */ the_authctxt = authctxt; /* Set default key authentication options */ if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL) fatal("allocation failed"); /* prepare buffer to collect messages to display to user after login */ if ((loginmsg = sshbuf_new()) == NULL) fatal("sshbuf_new loginmsg failed"); auth_debug_reset(); /* Enable challenge-response authentication for privilege separation */ privsep_challenge_enable(); #ifdef GSSAPI /* Cache supported mechanism OIDs for later use */ ssh_gssapi_prepare_supported_oids(); #endif privsep_child_demote(); /* perform the key exchange */ /* authenticate user and start session */ do_ssh2_kex(ssh); do_authentication2(ssh); /* * The unprivileged child now transfers the current keystate and exits. */ mm_send_keystate(ssh, pmonitor); ssh_packet_clear_keys(ssh); exit(0); } int sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, struct sshkey *pubkey, u_char **signature, size_t *slenp, const u_char *data, size_t dlen, const char *alg) { if (privkey) { if (mm_sshkey_sign(ssh, privkey, signature, slenp, data, dlen, alg, options.sk_provider, NULL, ssh->compat) < 0) fatal_f("privkey sign failed"); } else { if (mm_sshkey_sign(ssh, pubkey, signature, slenp, data, dlen, alg, options.sk_provider, NULL, ssh->compat) < 0) fatal_f("pubkey sign failed"); } return 0; } /* SSH2 key exchange */ static void do_ssh2_kex(struct ssh *ssh) { char *hkalgs = NULL, *myproposal[PROPOSAL_MAX]; const char *compression = NULL; struct kex *kex; int r; if (options.rekey_limit || options.rekey_interval) ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); if (options.compression == COMP_NONE) compression = "none"; hkalgs = list_hostkey_types(); kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms, options.ciphers, options.macs, compression, hkalgs); free(hkalgs); /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos); kex = ssh->kex; #ifdef WITH_OPENSSL kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; kex->sign = sshd_hostkey_sign; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); kex_proposal_free_entries(myproposal); #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || (r = sshpkt_put_cstring(ssh, "markus")) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send test"); #endif debug("KEX done"); } /* server specific fatal cleanup */ void cleanup_exit(int i) { _exit(i); } openssh-10.0p1/PaxHeaders.10889/sshd-debug.sh100755 001750 001750 0000000003614775415623 0015540xustar0030 atime=1744182234.864087807 openssh-10.0p1/sshd-debug.sh010075500017500001750000000026651477541562300141340ustar00djmdjm#!/bin/sh # ssh-debug # A wrapper script around sshd to invoke when debugging to debug the # work-in-progress versions of sshd-auth and sshd-session, instead # of debugging the installed ones that probably don't have the change # you are working on. # # Placed in the Public Domain. unset DIR SSHD SSHD_AUTH SSHD_SESSION fatal() { echo >&2 $@ exit 1 } case "$0" in /*) DIR="`dirname $0`" ;; ./sshd-debug.sh) DIR="`pwd`" ;; *) echo "Need full path or working directory."; exit 1 ;; esac for i in sshd/obj/sshd sshd/sshd sshd; do if [ -f "${DIR}/$i" ] && [ -x "${DIR}/$i" ]; then SSHD="${DIR}/$i" fi done [ -z "${SSHD}" ] && fatal "Could not find sshd" for i in sshd-auth/obj/sshd-auth sshd-auth/sshd-auth sshd-auth; do if [ -f "${DIR}/$i" ] && [ -x "${DIR}/$i" ]; then SSHD_AUTH="${DIR}/$i" fi done [ -z "${SSHD_AUTH}" ] && fatal "Could not find sshd-auth" for i in sshd-session/obj/sshd-session sshd-session/sshd-session sshd-session; do if [ -f "${DIR}/$i" ] && [ -x "${DIR}/$i" ]; then SSHD_SESSION="${DIR}/$i" fi done [ -z "${SSHD_SESSION}" ] && fatal "Could not find sshd-session" echo >&2 Debugging ${SSHD} auth ${SSHD_AUTH} session ${SSHD_SESSION} # Append SshdSessionPath and SshdAuthPath pointing to the build directory. # If you explicitly specify these in the command line, the first-match # keyword semantics will override these. exec "${SSHD}" $@ \ -oSshdAuthPath="${SSHD_AUTH}" -oSshdSessionPath="${SSHD_SESSION}" openssh-10.0p1/PaxHeaders.10889/sshd-session.c100644 001750 001750 0000000003614775415623 0015742xustar0030 atime=1744182234.866040129 openssh-10.0p1/sshd-session.c010064400017500001750000001157321477541562300143360ustar00djmdjm/* $OpenBSD: sshd-session.c,v 1.12 2025/03/12 22:43:44 djm Exp $ */ /* * SSH2 implementation: * Privilege Separation: * * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" #include #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #include #include "openbsd-compat/openssl-compat.h" #endif #ifdef HAVE_SECUREWARE #include #include #endif #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshpty.h" #include "packet.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "match.h" #include "servconf.h" #include "uidswap.h" #include "compat.h" #include "cipher.h" #include "digest.h" #include "sshkey.h" #include "kex.h" #include "authfile.h" #include "pathnames.h" #include "atomicio.h" #include "canohost.h" #include "hostfile.h" #include "auth.h" #include "authfd.h" #include "msg.h" #include "dispatch.h" #include "channels.h" #include "session.h" #include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "auth-options.h" #include "version.h" #include "ssherr.h" #include "sk-api.h" #include "srclimit.h" #include "dh.h" /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 2) #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 3) /* Privsep fds */ #define PRIVSEP_MONITOR_FD (STDERR_FILENO + 1) #define PRIVSEP_LOG_FD (STDERR_FILENO + 2) #define PRIVSEP_MIN_FREE_FD (STDERR_FILENO + 3) extern char *__progname; /* Server configuration options. */ ServerOptions options; /* Name of the server configuration file. */ char *config_file_name = _PATH_SERVER_CONFIG_FILE; /* * Debug mode flag. This can be set on the command line. If debug * mode is enabled, extra debugging output will be sent to the system * log, the daemon will not go to background, and will exit after processing * the first connection. */ int debug_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ static int inetd_flag = 0; /* debug goes to stderr unless inetd_flag is set */ static int log_stderr = 0; /* Saved arguments to main(). */ static char **saved_argv; static int saved_argc; /* Daemon's agent connection */ int auth_sock = -1; static int have_agent = 0; /* * Any really sensitive data in the application is contained in this * structure. The idea is that this structure could be locked into memory so * that the pages do not get written into swap. However, there are some * problems. The private key contains BIGNUMs, and we do not (in principle) * have access to the internals of them, and locking just the structure is * not very useful. Currently, memory locking is not implemented. */ struct { u_int num_hostkeys; struct sshkey **host_keys; /* all private host keys */ struct sshkey **host_pubkeys; /* all public host keys */ struct sshkey **host_certificates; /* all public host certificates */ } sensitive_data; /* record remote hostname or ip */ u_int utmp_len = HOST_NAME_MAX+1; static int startup_pipe = -1; /* in child */ /* variables used for privilege separation */ struct monitor *pmonitor = NULL; int privsep_is_preauth = 1; static int privsep_chroot = 1; /* Unprivileged user */ struct passwd *privsep_pw = NULL; /* global connection state and authentication contexts */ Authctxt *the_authctxt = NULL; struct ssh *the_active_state; /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ struct sshauthopt *auth_opts = NULL; /* sshd_config buffer */ struct sshbuf *cfg; /* Included files from the configuration file */ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); /* message to be displayed after login */ struct sshbuf *loginmsg; /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); void demote_sensitive_data(void); /* XXX reduce to stub once postauth split */ int mm_is_monitor(void) { /* * m_pid is only set in the privileged part, and * points to the unprivileged child. */ return (pmonitor && pmonitor->m_pid > 0); } /* * Signal handler for the alarm after the login grace period has expired. * As usual, this may only take signal-safe actions, even though it is * terminal. */ static void grace_alarm_handler(int sig) { /* * Try to kill any processes that we have spawned, E.g. authorized * keys command helpers or privsep children. */ if (getpgid(0) == getpid()) { struct sigaction sa; /* mask all other signals while in handler */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigfillset(&sa.sa_mask); #if defined(SA_RESTART) sa.sa_flags = SA_RESTART; #endif (void)sigaction(SIGTERM, &sa, NULL); kill(0, SIGTERM); } _exit(EXIT_LOGIN_GRACE); } /* Destroy the host and server keys. They will no longer be needed. */ void destroy_sensitive_data(void) { u_int i; for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { sshkey_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = NULL; } if (sensitive_data.host_certificates[i]) { sshkey_free(sensitive_data.host_certificates[i]); sensitive_data.host_certificates[i] = NULL; } } } /* Demote private to public keys for network child */ void demote_sensitive_data(void) { struct sshkey *tmp; u_int i; int r; for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { if ((r = sshkey_from_private( sensitive_data.host_keys[i], &tmp)) != 0) fatal_r(r, "could not demote host %s key", sshkey_type(sensitive_data.host_keys[i])); sshkey_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = tmp; } /* Certs do not need demotion */ } } static void reseed_prngs(void) { u_int32_t rnd[256]; #ifdef WITH_OPENSSL RAND_poll(); #endif arc4random_stir(); /* noop on recent arc4random() implementations */ arc4random_buf(rnd, sizeof(rnd)); /* let arc4random notice PID change */ #ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); /* give libcrypto a chance to notice the PID change */ if ((RAND_bytes((u_char *)rnd, 1)) != 1) fatal("%s: RAND_bytes failed", __func__); #endif explicit_bzero(rnd, sizeof(rnd)); } struct sshbuf * pack_hostkeys(void) { struct sshbuf *keybuf = NULL, *hostkeys = NULL; int r; u_int i; if ((hostkeys = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* pack hostkeys into a string. Empty key slots get empty strings */ for (i = 0; i < options.num_host_key_files; i++) { /* public key */ if (sensitive_data.host_pubkeys[i] != NULL) { if ((r = sshkey_puts(sensitive_data.host_pubkeys[i], hostkeys)) != 0) fatal_fr(r, "compose hostkey public"); } else { if ((r = sshbuf_put_string(hostkeys, NULL, 0)) != 0) fatal_fr(r, "compose hostkey empty public"); } /* cert */ if (sensitive_data.host_certificates[i] != NULL) { if ((r = sshkey_puts( sensitive_data.host_certificates[i], hostkeys)) != 0) fatal_fr(r, "compose host cert"); } else { if ((r = sshbuf_put_string(hostkeys, NULL, 0)) != 0) fatal_fr(r, "compose host cert empty"); } } sshbuf_free(keybuf); return hostkeys; } static int privsep_preauth(struct ssh *ssh) { int status, r; pid_t pid; /* Set up unprivileged child process to deal with network data */ pmonitor = monitor_init(); /* Store a pointer to the kex for later rekeying */ pmonitor->m_pkex = &ssh->kex; if ((pid = fork()) == -1) fatal("fork of unprivileged child failed"); else if (pid != 0) { debug2("Network child is on pid %ld", (long)pid); pmonitor->m_pid = pid; if (have_agent) { r = ssh_get_authentication_socket(&auth_sock); if (r != 0) { error_r(r, "Could not get agent socket"); have_agent = 0; } } monitor_child_preauth(ssh, pmonitor); /* Wait for the child's exit status */ while (waitpid(pid, &status, 0) == -1) { if (errno == EINTR) continue; pmonitor->m_pid = -1; fatal_f("waitpid: %s", strerror(errno)); } privsep_is_preauth = 0; pmonitor->m_pid = -1; if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) fatal_f("preauth child exited with status %d", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) fatal_f("preauth child terminated by signal %d", WTERMSIG(status)); return 1; } else { /* child */ close(pmonitor->m_sendfd); close(pmonitor->m_log_recvfd); /* * Arrange unpriv-preauth child process fds: * 0, 1 network socket * 2 optional stderr * 3 reserved * 4 monitor message socket * 5 monitor logging socket * * We know that the monitor sockets will have fds > 4 because * of the reserved fds in main() */ if (ssh_packet_get_connection_in(ssh) != STDIN_FILENO && dup2(ssh_packet_get_connection_in(ssh), STDIN_FILENO) == -1) fatal("dup2 stdin failed: %s", strerror(errno)); if (ssh_packet_get_connection_out(ssh) != STDOUT_FILENO && dup2(ssh_packet_get_connection_out(ssh), STDOUT_FILENO) == -1) fatal("dup2 stdout failed: %s", strerror(errno)); /* leave stderr as-is */ log_redirect_stderr_to(NULL); /* dup can clobber log fd */ if (pmonitor->m_recvfd != PRIVSEP_MONITOR_FD && dup2(pmonitor->m_recvfd, PRIVSEP_MONITOR_FD) == -1) fatal("dup2 monitor fd: %s", strerror(errno)); if (pmonitor->m_log_sendfd != PRIVSEP_LOG_FD && dup2(pmonitor->m_log_sendfd, PRIVSEP_LOG_FD) == -1) fatal("dup2 log fd: %s", strerror(errno)); closefrom(PRIVSEP_MIN_FREE_FD); saved_argv[0] = options.sshd_auth_path; execv(options.sshd_auth_path, saved_argv); fatal_f("exec of %s failed: %s", options.sshd_auth_path, strerror(errno)); } } static void privsep_postauth(struct ssh *ssh, Authctxt *authctxt) { int skip_privdrop = 0; /* * Hack for systems that don't support FD passing: retain privileges * in the post-auth privsep process so it can allocate PTYs directly. * This is basically equivalent to what we did <= 9.7, which was to * disable post-auth privsep entriely. * Cygwin doesn't need to drop privs here although it doesn't support * fd passing, as AFAIK PTY allocation on this platform doesn't require * special privileges to begin with. */ #if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) skip_privdrop = 1; #endif /* New socket pair */ monitor_reinit(pmonitor); pmonitor->m_pid = fork(); if (pmonitor->m_pid == -1) fatal("fork of unprivileged child failed"); else if (pmonitor->m_pid != 0) { verbose("User child is on pid %ld", (long)pmonitor->m_pid); sshbuf_reset(loginmsg); monitor_clear_keystate(ssh, pmonitor); monitor_child_postauth(ssh, pmonitor); /* NEVERREACHED */ exit(0); } /* child */ close(pmonitor->m_sendfd); pmonitor->m_sendfd = -1; /* Demote the private keys to public keys. */ demote_sensitive_data(); reseed_prngs(); /* Drop privileges */ if (!skip_privdrop) do_setusercontext(authctxt->pw); /* It is safe now to apply the key state */ monitor_apply_keystate(ssh, pmonitor); /* * Tell the packet layer that authentication was successful, since * this information is not part of the key state. */ ssh_packet_set_authenticated(ssh); } static struct sshkey * get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) { u_int i; struct sshkey *key; for (i = 0; i < options.num_host_key_files; i++) { switch (type) { case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: case KEY_XMSS_CERT: key = sensitive_data.host_certificates[i]; break; default: key = sensitive_data.host_keys[i]; if (key == NULL && !need_private) key = sensitive_data.host_pubkeys[i]; break; } if (key == NULL || key->type != type) continue; switch (type) { case KEY_ECDSA: case KEY_ECDSA_SK: case KEY_ECDSA_CERT: case KEY_ECDSA_SK_CERT: if (key->ecdsa_nid != nid) continue; /* FALLTHROUGH */ default: return need_private ? sensitive_data.host_keys[i] : key; } } return NULL; } struct sshkey * get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 0, ssh); } struct sshkey * get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 1, ssh); } struct sshkey * get_hostkey_by_index(int ind) { if (ind < 0 || (u_int)ind >= options.num_host_key_files) return (NULL); return (sensitive_data.host_keys[ind]); } struct sshkey * get_hostkey_public_by_index(int ind, struct ssh *ssh) { if (ind < 0 || (u_int)ind >= options.num_host_key_files) return (NULL); return (sensitive_data.host_pubkeys[ind]); } int get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) { u_int i; for (i = 0; i < options.num_host_key_files; i++) { if (sshkey_is_cert(key)) { if (key == sensitive_data.host_certificates[i] || (compare && sensitive_data.host_certificates[i] && sshkey_equal(key, sensitive_data.host_certificates[i]))) return (i); } else { if (key == sensitive_data.host_keys[i] || (compare && sensitive_data.host_keys[i] && sshkey_equal(key, sensitive_data.host_keys[i]))) return (i); if (key == sensitive_data.host_pubkeys[i] || (compare && sensitive_data.host_pubkeys[i] && sshkey_equal(key, sensitive_data.host_pubkeys[i]))) return (i); } } return (-1); } /* Inform the client of all hostkeys */ static void notify_hostkeys(struct ssh *ssh) { struct sshbuf *buf; struct sshkey *key; u_int i, nkeys; int r; char *fp; /* Some clients cannot cope with the hostkeys message, skip those. */ if (ssh->compat & SSH_BUG_HOSTKEYS) return; if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); for (i = nkeys = 0; i < options.num_host_key_files; i++) { key = get_hostkey_public_by_index(i, ssh); if (key == NULL || key->type == KEY_UNSPEC || sshkey_is_cert(key)) continue; fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); debug3_f("key %d: %s %s", i, sshkey_ssh_name(key), fp); free(fp); if (nkeys == 0) { /* * Start building the request when we find the * first usable key. */ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "hostkeys-00@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0) /* want reply */ sshpkt_fatal(ssh, r, "%s: start request", __func__); } /* Append the key to the request */ sshbuf_reset(buf); if ((r = sshkey_putb(key, buf)) != 0) fatal_fr(r, "couldn't put hostkey %d", i); if ((r = sshpkt_put_stringb(ssh, buf)) != 0) sshpkt_fatal(ssh, r, "%s: append key", __func__); nkeys++; } debug3_f("sent %u hostkeys", nkeys); if (nkeys == 0) fatal_f("no hostkeys"); if ((r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } static void usage(void) { fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); fprintf(stderr, "usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n" " [-E log_file] [-f config_file] [-g login_grace_time]\n" " [-h host_key_file] [-o option] [-p port] [-u len]\n" ); exit(1); } static void parse_hostkeys(struct sshbuf *hostkeys) { int r; u_int num_keys = 0; struct sshkey *k; struct sshbuf *kbuf; const u_char *cp; size_t len; while (sshbuf_len(hostkeys) != 0) { if (num_keys > 2048) fatal_f("too many hostkeys"); sensitive_data.host_keys = xrecallocarray( sensitive_data.host_keys, num_keys, num_keys + 1, sizeof(*sensitive_data.host_pubkeys)); sensitive_data.host_pubkeys = xrecallocarray( sensitive_data.host_pubkeys, num_keys, num_keys + 1, sizeof(*sensitive_data.host_pubkeys)); sensitive_data.host_certificates = xrecallocarray( sensitive_data.host_certificates, num_keys, num_keys + 1, sizeof(*sensitive_data.host_certificates)); /* private key */ k = NULL; if ((r = sshbuf_froms(hostkeys, &kbuf)) != 0) fatal_fr(r, "extract privkey"); if (sshbuf_len(kbuf) != 0 && (r = sshkey_private_deserialize(kbuf, &k)) != 0) fatal_fr(r, "parse pubkey"); sensitive_data.host_keys[num_keys] = k; sshbuf_free(kbuf); if (k) debug2_f("privkey %u: %s", num_keys, sshkey_ssh_name(k)); /* public key */ k = NULL; if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0) fatal_fr(r, "extract pubkey"); if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0) fatal_fr(r, "parse pubkey"); sensitive_data.host_pubkeys[num_keys] = k; if (k) debug2_f("pubkey %u: %s", num_keys, sshkey_ssh_name(k)); /* certificate */ k = NULL; if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0) fatal_fr(r, "extract pubkey"); if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0) fatal_fr(r, "parse pubkey"); sensitive_data.host_certificates[num_keys] = k; if (k) debug2_f("cert %u: %s", num_keys, sshkey_ssh_name(k)); num_keys++; } sensitive_data.num_hostkeys = num_keys; } static void recv_rexec_state(int fd, struct sshbuf *conf, uint64_t *timing_secretp) { struct sshbuf *m, *inc, *hostkeys; u_char *cp, ver; size_t len; int r; struct include_item *item; debug3_f("entering fd = %d", fd); if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* receive config */ if (ssh_msg_recv(fd, m) == -1) fatal_f("ssh_msg_recv failed"); if ((r = sshbuf_get_u8(m, &ver)) != 0) fatal_fr(r, "parse version"); if (ver != 0) fatal_f("rexec version mismatch"); if ((r = sshbuf_get_string(m, &cp, &len)) != 0 || /* XXX _direct */ (r = sshbuf_get_u64(m, timing_secretp)) != 0 || (r = sshbuf_get_stringb(m, inc)) != 0) fatal_fr(r, "parse config"); if (conf != NULL && (r = sshbuf_put(conf, cp, len))) fatal_fr(r, "sshbuf_put"); while (sshbuf_len(inc) != 0) { item = xcalloc(1, sizeof(*item)); if ((item->contents = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 || (r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 || (r = sshbuf_get_stringb(inc, item->contents)) != 0) fatal_fr(r, "parse includes"); TAILQ_INSERT_TAIL(&includes, item, entry); } /* receive hostkeys */ sshbuf_reset(m); if (ssh_msg_recv(fd, m) == -1) fatal_f("ssh_msg_recv failed"); if ((r = sshbuf_get_u8(m, NULL)) != 0 || (r = sshbuf_froms(m, &hostkeys)) != 0) fatal_fr(r, "parse config"); parse_hostkeys(hostkeys); free(cp); sshbuf_free(m); sshbuf_free(hostkeys); sshbuf_free(inc); debug3_f("done"); } /* * 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); } #endif /* IP_OPTIONS */ } /* Set the routing domain for this process */ static void set_process_rdomain(struct ssh *ssh, const char *name) { #if defined(HAVE_SYS_SET_PROCESS_RDOMAIN) if (name == NULL) return; /* default */ if (strcmp(name, "%D") == 0) { /* "expands" to routing domain of connection */ if ((name = ssh_packet_rdomain_in(ssh)) == NULL) return; } /* NB. We don't pass 'ssh' to sys_set_process_rdomain() */ return sys_set_process_rdomain(name); #elif defined(__OpenBSD__) int rtable, ortable = getrtable(); const char *errstr; if (name == NULL) return; /* default */ if (strcmp(name, "%D") == 0) { /* "expands" to routing domain of connection */ if ((name = ssh_packet_rdomain_in(ssh)) == NULL) return; } rtable = (int)strtonum(name, 0, 255, &errstr); if (errstr != NULL) /* Shouldn't happen */ fatal("Invalid routing domain \"%s\": %s", name, errstr); if (rtable != ortable && setrtable(rtable) != 0) fatal("Unable to set routing domain %d: %s", rtable, strerror(errno)); debug_f("set routing domain %d (was %d)", rtable, ortable); #else /* defined(__OpenBSD__) */ fatal("Unable to set routing domain: not supported in this platform"); #endif } /* * Main program for the daemon. */ int main(int ac, char **av) { struct ssh *ssh = NULL; extern char *optarg; extern int optind; int devnull, r, opt, on = 1, remote_port; int sock_in = -1, sock_out = -1, rexeced_flag = 0, have_key = 0; const char *remote_ip, *rdomain; char *line, *laddr, *logfile = NULL; u_int i; u_int64_t ibytes, obytes; mode_t new_umask; Authctxt *authctxt; struct connection_info *connection_info = NULL; sigset_t sigmask; uint64_t timing_secret = 0; struct itimerval itv; sigemptyset(&sigmask); sigprocmask(SIG_SETMASK, &sigmask, NULL); #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); #endif __progname = ssh_get_progname(av[0]); /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; saved_argv = xcalloc(ac + 1, sizeof(*saved_argv)); for (i = 0; (int)i < ac; i++) saved_argv[i] = xstrdup(av[i]); saved_argv[i] = NULL; #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ compat_init_setproctitle(ac, av); av = saved_argv; #endif /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* Initialize configuration options to their default values. */ initialize_server_options(&options); /* Parse command-line arguments. */ while ((opt = getopt(ac, av, "C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) { switch (opt) { case '4': options.address_family = AF_INET; break; case '6': options.address_family = AF_INET6; break; case 'f': config_file_name = optarg; break; case 'c': servconf_add_hostcert("[command-line]", 0, &options, optarg); break; case 'd': if (debug_flag == 0) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) options.log_level++; break; case 'D': /* ignore */ break; case 'E': logfile = optarg; /* FALLTHROUGH */ case 'e': log_stderr = 1; break; case 'i': inetd_flag = 1; break; case 'r': /* ignore */ break; case 'R': rexeced_flag = 1; break; case 'Q': /* ignored */ break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'b': /* protocol 1, ignored */ break; case 'p': options.ports_from_cmdline = 1; if (options.num_ports >= MAX_PORTS) { fprintf(stderr, "too many ports.\n"); exit(1); } options.ports[options.num_ports++] = a2port(optarg); if (options.ports[options.num_ports-1] <= 0) { fprintf(stderr, "Bad port number.\n"); exit(1); } break; case 'g': if ((options.login_grace_time = convtime(optarg)) == -1) { fprintf(stderr, "Invalid login grace time.\n"); exit(1); } break; case 'k': /* protocol 1, ignored */ break; case 'h': servconf_add_hostkey("[command-line]", 0, &options, optarg, 1); break; case 't': case 'T': case 'G': fatal("test/dump modes not supported"); break; case 'C': connection_info = server_get_connection_info(ssh, 0, 0); if (parse_server_match_testspec(connection_info, optarg) == -1) exit(1); break; case 'u': utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL); if (utmp_len > HOST_NAME_MAX+1) { fprintf(stderr, "Invalid utmp length.\n"); exit(1); } break; case 'o': line = xstrdup(optarg); if (process_server_config_line(&options, line, "command-line", 0, NULL, NULL, &includes) != 0) exit(1); free(line); break; case 'V': fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); exit(0); default: usage(); break; } } /* Check that there are no remaining arguments. */ if (optind < ac) { fprintf(stderr, "Extra argument %s.\n", av[optind]); exit(1); } if (!rexeced_flag) fatal("sshd-session should not be executed directly"); closefrom(REEXEC_MIN_FREE_FD); platform_pre_session_start(); /* Reserve fds we'll need later for reexec things */ if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) fatal("open %s: %s", _PATH_DEVNULL, strerror(errno)); while (devnull < PRIVSEP_MIN_FREE_FD) { if ((devnull = dup(devnull)) == -1) fatal("dup %s: %s", _PATH_DEVNULL, strerror(errno)); } seed_rng(); /* If requested, redirect the logs to the specified logfile. */ if (logfile != NULL) { char *cp, pid_s[32]; snprintf(pid_s, sizeof(pid_s), "%ld", (unsigned long)getpid()); cp = percent_expand(logfile, "p", pid_s, "P", "sshd-session", (char *)NULL); log_redirect_stderr_to(cp); free(cp); } /* * Force logging to stderr until we have loaded the private host * key (unless started from inetd) */ log_init(__progname, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_AUTH : options.log_facility, log_stderr || !inetd_flag || debug_flag); /* Fetch our configuration */ if ((cfg = sshbuf_new()) == NULL) fatal("sshbuf_new config buf failed"); setproctitle("%s", "[rexeced]"); recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg, &timing_secret); parse_server_config(&options, "rexec", cfg, &includes, NULL, 1); /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); options.timing_secret = timing_secret; /* Reinit logging in case config set Level, Facility or Verbose. */ log_init(__progname, options.log_level, options.log_facility, log_stderr || !inetd_flag || debug_flag); debug("sshd-session version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); /* Store privilege separation user for later use if required. */ privsep_chroot = (getuid() == 0 || geteuid() == 0); if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { if (privsep_chroot || options.kerberos_authentication) fatal("Privilege separation user %s does not exist", SSH_PRIVSEP_USER); } else { privsep_pw = pwcopy(privsep_pw); freezero(privsep_pw->pw_passwd, strlen(privsep_pw->pw_passwd)); privsep_pw->pw_passwd = xstrdup("*"); } endpwent(); if (!debug_flag && !inetd_flag) { if ((startup_pipe = dup(REEXEC_CONFIG_PASS_FD)) == -1) fatal("internal error: no startup pipe"); /* * 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); } /* close the fd, but keep the slot reserved */ if (dup2(devnull, REEXEC_CONFIG_PASS_FD) == -1) fatal("dup2 devnull->config fd: %s", strerror(errno)); /* Check that options are sensible */ if (options.authorized_keys_command_user == NULL && (options.authorized_keys_command != NULL && strcasecmp(options.authorized_keys_command, "none") != 0)) fatal("AuthorizedKeysCommand set without " "AuthorizedKeysCommandUser"); if (options.authorized_principals_command_user == NULL && (options.authorized_principals_command != NULL && strcasecmp(options.authorized_principals_command, "none") != 0)) fatal("AuthorizedPrincipalsCommand set without " "AuthorizedPrincipalsCommandUser"); /* * Check whether there is any path through configured auth methods. * Unfortunately it is not possible to verify this generally before * daemonisation in the presence of Match block, but this catches * and warns for trivial misconfigurations that could break login. */ if (options.num_auth_methods != 0) { for (i = 0; i < options.num_auth_methods; i++) { if (auth2_methods_valid(options.auth_methods[i], 1) == 0) break; } if (i >= options.num_auth_methods) fatal("AuthenticationMethods cannot be satisfied by " "enabled authentication methods"); } #ifdef WITH_OPENSSL if (options.moduli_file != NULL) dh_set_moduli_file(options.moduli_file); #endif if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) setenv(SSH_AUTHSOCKET_ENV_NAME, options.host_key_agent, 1); if ((r = ssh_get_authentication_socket(NULL)) == 0) have_agent = 1; else error_r(r, "Could not connect to agent \"%s\"", options.host_key_agent); } if (options.num_host_key_files != sensitive_data.num_hostkeys) { fatal("internal error: hostkeys confused (config %u recvd %u)", options.num_host_key_files, sensitive_data.num_hostkeys); } for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i] != NULL || (have_agent && sensitive_data.host_pubkeys[i] != NULL)) { have_key = 1; break; } } if (!have_key) fatal("internal error: monitor received no hostkeys"); /* Ensure that umask disallows at least group and world write */ new_umask = umask(0077) | 0022; (void) umask(new_umask); /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag) log_stderr = 1; log_init(__progname, options.log_level, options.log_facility, log_stderr); for (i = 0; i < options.num_log_verbose; i++) log_verbose_add(options.log_verbose[i]); /* Reinitialize the log (because of the fork above). */ log_init(__progname, options.log_level, options.log_facility, log_stderr); /* * Chdir to the root directory so that the current disk can be * unmounted if desired. */ if (chdir("/") == -1) error("chdir(\"/\"): %s", strerror(errno)); /* ignore SIGPIPE */ ssh_signal(SIGPIPE, SIG_IGN); /* Get a connection, either from inetd or rexec */ if (inetd_flag) { /* * NB. must be different fd numbers for the !socket case, * as packet_connection_is_on_socket() depends on this. */ sock_in = dup(STDIN_FILENO); sock_out = dup(STDOUT_FILENO); } else { /* rexec case; accept()ed socket in ancestor listener */ sock_in = sock_out = dup(STDIN_FILENO); } /* * We intentionally do not close the descriptors 0, 1, and 2 * as our code for setting the descriptors won't work if * ttyfd happens to be one of those. */ if (stdfd_devnull(1, 1, !log_stderr) == -1) error("stdfd_devnull failed"); debug("network sockets: %d, %d", sock_in, sock_out); /* This is the child processing a new connection. */ setproctitle("%s", "[accepted]"); /* Executed child processes don't need these. */ fcntl(sock_out, F_SETFD, FD_CLOEXEC); fcntl(sock_in, F_SETFD, FD_CLOEXEC); /* We will not restart on SIGHUP since it no longer makes sense. */ ssh_signal(SIGALRM, SIG_DFL); ssh_signal(SIGHUP, SIG_DFL); ssh_signal(SIGTERM, SIG_DFL); ssh_signal(SIGQUIT, SIG_DFL); ssh_signal(SIGCHLD, SIG_DFL); ssh_signal(SIGINT, SIG_DFL); /* * Register our connection. This turns encryption off because we do * not have a key. */ if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) fatal("Unable to create connection"); the_active_state = ssh; ssh_packet_set_server(ssh); check_ip_options(ssh); /* Prepare the channels layer */ channel_init_channels(ssh); channel_set_af(ssh, options.address_family); server_process_channel_timeouts(ssh); server_process_permitopen(ssh); /* Set SO_KEEPALIVE if requested. */ if (options.tcp_keep_alive && ssh_packet_connection_is_on_socket(ssh) && setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); if ((remote_port = ssh_remote_port(ssh)) < 0) { debug("ssh_remote_port failed"); cleanup_exit(255); } /* * The rest of the code depends on the fact that * ssh_remote_ipaddr() caches the remote ip, even if * the socket goes away. */ remote_ip = ssh_remote_ipaddr(ssh); #ifdef SSH_AUDIT_EVENTS audit_connection_from(remote_ip, remote_port); #endif rdomain = ssh_packet_rdomain_in(ssh); /* Log the connection. */ laddr = get_local_ipaddr(sock_in); verbose("Connection from %s port %d on %s port %d%s%s%s", remote_ip, remote_port, laddr, ssh_local_port(ssh), rdomain == NULL ? "" : " rdomain \"", rdomain == NULL ? "" : rdomain, rdomain == NULL ? "" : "\""); free(laddr); /* * We don't want to listen forever unless the other side * successfully authenticates itself. So we set up an alarm which is * cleared after successful authentication. A limit of zero * indicates no limit. Note that we don't set the alarm in debugging * mode; it is just annoying to have the server exit just when you * are about to discover the bug. */ ssh_signal(SIGALRM, grace_alarm_handler); if (!debug_flag && options.login_grace_time > 0) { int ujitter = arc4random_uniform(4 * 1000000); timerclear(&itv.it_interval); itv.it_value.tv_sec = options.login_grace_time; itv.it_value.tv_sec += ujitter / 1000000; itv.it_value.tv_usec = ujitter % 1000000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) fatal("login grace time setitimer failed"); } if ((r = kex_exchange_identification(ssh, -1, options.version_addendum)) != 0) sshpkt_fatal(ssh, r, "banner exchange"); ssh_packet_set_nonblocking(ssh); /* allocate authentication context */ authctxt = xcalloc(1, sizeof(*authctxt)); ssh->authctxt = authctxt; /* XXX global for cleanup, access from other modules */ the_authctxt = authctxt; /* Set default key authentication options */ if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL) fatal("allocation failed"); /* prepare buffer to collect messages to display to user after login */ if ((loginmsg = sshbuf_new()) == NULL) fatal("sshbuf_new loginmsg failed"); auth_debug_reset(); if (privsep_preauth(ssh) != 1) fatal("privsep_preauth failed"); /* Now user is authenticated */ /* * Cancel the alarm we set to limit the time taken for * authentication. */ timerclear(&itv.it_interval); timerclear(&itv.it_value); if (setitimer(ITIMER_REAL, &itv, NULL) == -1) fatal("login grace time clear failed"); ssh_signal(SIGALRM, SIG_DFL); authctxt->authenticated = 1; if (startup_pipe != -1) { /* signal listener that authentication completed successfully */ (void)atomicio(vwrite, startup_pipe, "\001", 1); close(startup_pipe); startup_pipe = -1; } if (options.routing_domain != NULL) set_process_rdomain(ssh, options.routing_domain); #ifdef SSH_AUDIT_EVENTS audit_event(ssh, SSH_AUTH_SUCCESS); #endif #ifdef GSSAPI if (options.gss_authentication) { temporarily_use_uid(authctxt->pw); ssh_gssapi_storecreds(); restore_uid(); } #endif #ifdef USE_PAM if (options.use_pam) { do_pam_setcred(); do_pam_session(ssh); } #endif /* * In privilege separation, we fork another child and prepare * file descriptor passing. */ privsep_postauth(ssh, authctxt); /* the monitor process [priv] will not return */ ssh_packet_set_timeout(ssh, options.client_alive_interval, options.client_alive_count_max); /* Try to send all our hostkeys to the client */ notify_hostkeys(ssh); /* Start session. */ do_authenticated(ssh, authctxt); /* The connection has been terminated. */ ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); verbose("Closing connection to %.500s port %d", remote_ip, remote_port); #ifdef USE_PAM if (options.use_pam) finish_pam(); #endif /* USE_PAM */ #ifdef SSH_AUDIT_EVENTS mm_audit_event(ssh, SSH_CONNECTION_CLOSE); #endif ssh_packet_close(ssh); mm_terminate(); exit(0); } int sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, struct sshkey *pubkey, u_char **signature, size_t *slenp, const u_char *data, size_t dlen, const char *alg) { if (privkey) { if (mm_sshkey_sign(ssh, privkey, signature, slenp, data, dlen, alg, options.sk_provider, NULL, ssh->compat) < 0) fatal_f("privkey sign failed"); } else { if (mm_sshkey_sign(ssh, pubkey, signature, slenp, data, dlen, alg, options.sk_provider, NULL, ssh->compat) < 0) fatal_f("pubkey sign failed"); } return 0; } /* server specific fatal cleanup */ void cleanup_exit(int i) { extern int auth_attempted; /* monitor.c */ if (the_active_state != NULL && the_authctxt != NULL) { do_cleanup(the_active_state, the_authctxt); if (privsep_is_preauth && pmonitor != NULL && pmonitor->m_pid > 1) { debug("Killing privsep child %d", pmonitor->m_pid); if (kill(pmonitor->m_pid, SIGKILL) != 0 && errno != ESRCH) { error_f("kill(%d): %s", pmonitor->m_pid, strerror(errno)); } } } #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ if (the_active_state != NULL && mm_is_monitor()) audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif /* Override default fatal exit value when auth was attempted */ if (i == 255 && auth_attempted) _exit(EXIT_AUTH_ATTEMPTED); _exit(i); } openssh-10.0p1/PaxHeaders.10889/sshd.8100644 001750 001750 0000000003614775415623 0014206xustar0030 atime=1744182234.867991941 openssh-10.0p1/sshd.8010064400017500001750000001000131477541562300125640ustar00djmdjm.\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $OpenBSD: sshd.8,v 1.327 2024/09/15 01:19:56 djm Exp $ .Dd $Mdocdate: September 15 2024 $ .Dt SSHD 8 .Os .Sh NAME .Nm sshd .Nd OpenSSH daemon .Sh SYNOPSIS .Nm sshd .Bk -words .Op Fl 46DdeGiqTtV .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 o Ar option .Op Fl p Ar port .Op Fl u Ar len .Ek .Sh DESCRIPTION .Nm (OpenSSH Daemon) is the daemon program for .Xr ssh 1 . It provides secure encrypted communications between two untrusted hosts over an insecure network. .Pp .Nm listens for connections from clients. It is normally started at boot from .Pa /etc/rc . It forks a new daemon for each incoming connection. The forked daemons handle key exchange, encryption, authentication, command execution, and data exchange. .Pp .Nm can be configured using command-line options or a configuration file (by default .Xr sshd_config 5 ) ; command-line options override values specified in the configuration file. .Nm rereads its configuration file when it receives a hangup signal, .Dv SIGHUP , by executing itself with the name and options it was started with, e.g.\& .Pa /usr/sbin/sshd . .Pp The options are as follows: .Bl -tag -width Ds .It Fl 4 Forces .Nm to use IPv4 addresses only. .It Fl 6 Forces .Nm to use IPv6 addresses only. .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 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 rdomain and correspond to source address, user, resolved source host name, local address, local port number and routing domain respectively. Additionally the .Dq invalid-user flag (which does not take a value argument) may be specified to simulate a connection from an unrecognised username. .It Fl c Ar host_certificate_file Specifies a path to a certificate file to identify .Nm during key exchange. The certificate file must match a host key file specified using the .Fl h option or the .Cm HostKey configuration directive. .It Fl D When this option is specified, .Nm will not detach and does not become a daemon. This allows easy monitoring of .Nm sshd . .It Fl 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 .Xr fork 2 and will only process one connection. This option is only intended for debugging for the server. Multiple .Fl d options increase the debugging level. Maximum is 3. .It Fl E Ar log_file Append debug logs to .Ar log_file instead of the system log. .It Fl e Write debug logs to standard error instead of the system log. .It Fl f Ar config_file Specifies the name of the configuration file. The default is .Pa /etc/ssh/sshd_config . .Nm refuses to start if there is no configuration file. .It Fl G Parse and print configuration file. Check the validity of the configuration file, output the effective configuration to stdout and then exit. Optionally, .Cm Match rules may be applied by specifying the connection parameters using one or more .Fl C options. .It Fl g Ar 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. .It Fl h Ar host_key_file Specifies a file from which a host key is read. This option must be given if .Nm 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_ecdsa_key , .Pa /etc/ssh/ssh_host_ed25519_key and .Pa /etc/ssh/ssh_host_rsa_key . It is possible to have multiple host key files for the different host key algorithms. .It Fl i Specifies that .Nm is being run from .Xr inetd 8 . .It Fl o Ar option Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate command-line flag. For full details of the options, and their values, see .Xr sshd_config 5 . .It Fl p Ar 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 .Cm Port option are ignored when a command-line port is specified. Ports specified using the .Cm ListenAddress option override command-line ports. .It Fl q Quiet mode. Nothing is sent to the system log. Normally the beginning, authentication, and termination of each connection is logged. .It Fl T Extended test mode. Check the validity of the configuration file, output the effective configuration to stdout and then exit. Optionally, .Cm Match rules may be applied by specifying the connection parameters using one or more .Fl C options. This is similar to the .Fl G flag, but it includes the additional testing performed by the .Fl t flag. .It Fl t Test mode. Only check the validity of the configuration file and sanity of the keys. This is useful for updating .Nm reliably as configuration options may change. .It Fl u Ar len This option is used to specify the size of the field in the .Vt utmp structure that holds the remote host name. If the resolved host name is longer than .Ar 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 .Fl u0 indicates that only dotted decimal addresses should be put into the .Pa utmp file. .Fl u0 may also be used to prevent .Nm from making DNS requests unless the authentication mechanism or configuration requires it. Authentication mechanisms that may require DNS include .Cm HostbasedAuthentication and using a .Cm from="pattern-list" option in a key file. Configuration options that require DNS include using a USER@HOST pattern in .Cm AllowUsers or .Cm DenyUsers . .It Fl V Display the version number and exit. .El .Sh AUTHENTICATION The OpenSSH SSH daemon supports SSH protocol 2 only. Each host has a host-specific key, used to identify the host. Whenever a client connects, the daemon responds with its public host key. The client compares the host key against its own database to verify that it has not changed. Forward 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. 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 (MAC). .Pp 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. .Pp 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 .Cm DenyUsers or its group is listed in .Cm DenyGroups \&. 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, .Ql \&* on HP-UX, containing .Ql Nologin on Tru64, a leading .Ql \&*LOCKED\&* on FreeBSD and a leading .Ql \&! 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 .Ql NP or .Ql \&*NP\&* ). .Pp 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. .Pp After this, the client either requests an interactive shell or execution of a non-interactive command, which .Nm will execute via the user's shell using its .Fl c option. The sides then enter session mode. In this mode, either side may send data at any time, and such data is forwarded to/from the shell or command on the server side, and the user terminal in the client side. .Pp 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. .Sh LOGIN PROCESS When a user successfully logs in, .Nm does the following: .Bl -enum -offset indent .It If the login is on a tty, and no command has been specified, prints last login time and .Pa /etc/motd (unless prevented in the configuration file or by .Pa ~/.hushlogin ; see the .Sx FILES section). .It If the login is on a tty, records login time. .It Checks .Pa /etc/nologin ; if it exists, prints contents and quits (unless root). .It Changes to run with normal user privileges. .It Sets up basic environment. .It Reads the file .Pa ~/.ssh/environment , if it exists, and users are allowed to change their environment. See the .Cm PermitUserEnvironment option in .Xr sshd_config 5 . .It Changes to user's home directory. .It If .Pa ~/.ssh/rc exists and the .Xr sshd_config 5 .Cm PermitUserRC option is set, runs it; else if .Pa /etc/ssh/sshrc exists, runs it; otherwise runs .Xr xauth 1 . The .Dq rc files are given the X11 authentication protocol and cookie in standard input. See .Sx SSHRC , 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 .Pa ~/.ssh/rc exists, .Xr 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 .Ev DISPLAY in its environment). The script must call .Xr xauth 1 because .Nm will not run xauth automatically to add X11 cookies. .Pp 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. .Pp This file will probably contain some initialization code followed by something similar to: .Bd -literal -offset 3n 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 .Ed .Pp If this file does not exist, .Pa /etc/ssh/sshrc is run, and if that does not exist either, xauth is used to add the cookie. .Sh AUTHORIZED_KEYS FILE FORMAT .Cm AuthorizedKeysFile specifies the files containing public keys for public key authentication; if this option is not specified, the default is .Pa ~/.ssh/authorized_keys and .Pa ~/.ssh/authorized_keys2 . Each line of the file contains one key (empty lines and lines starting with a .Ql # are ignored as comments). Public keys consist of the following space-separated fields: options, keytype, base64-encoded key, comment. 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-rsa .El .Pp The comment field is not used for anything (but may be convenient for the user to identify the key). .Pp Note that lines in this file can be several hundred bytes long (because of the size of the public key encoding) up to a limit of 8 kilobytes, which permits RSA keys up to 16 kilobits. You don't want to type them in; instead, copy the .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 of 1024 bits. .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 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. .Pp 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. .It Cm 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 .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, 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 a .Xr sshd_config 5 .Cm ForceCommand 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. 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 .Cm PermitUserEnvironment option. .It Cm expiry-time="timespec" Specifies a time after which the key will not be accepted. The time may be specified as a YYYYMMDD[Z] date or a YYYYMMDDHHMM[SS][Z] time. Dates and times will be interpreted in the system time zone unless suffixed by a Z character, in which case they will be interpreted in the UTC 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 comma-separated list of patterns. See PATTERNS in .Xr ssh_config 5 for more information on patterns. .Pp In addition to the wildcard matching that may be applied to hostnames or addresses, a .Cm from stanza may match IP addresses using CIDR address/masklen notation. .Pp 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). .It Cm no-agent-forwarding Forbids authentication agent forwarding when this key is used for authentication. .It Cm 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 .Cm command option. .It Cm no-pty Prevents tty allocation (a request to allocate a pty will fail). .It Cm no-user-rc Disables execution of .Pa ~/.ssh/rc . .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 the .Xr ssh 1 .Fl L 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 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 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 .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 verify-required Require that signatures made using this key attest that they verified the user, e.g. via a PIN. This option only makes sense for the FIDO authenticator algorithms .Cm ecdsa-sk and .Cm ed25519-sk . .It Cm restrict Enable all restrictions, i.e. disable port, agent and X11 forwarding, as well as disabling PTY allocation 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: .Bd -literal -offset 3n # Comments are allowed at start of line. Blank lines are allowed. # Plain key, no restrictions ssh-rsa ... # Forced command, disable PTY and all forwarding restrict,command="dump /home" ssh-rsa ... # Restriction of ssh -L forwarding destinations permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-rsa ... # Restriction of ssh -R forwarding listeners permitlisten="localhost:8080",permitlisten="[::1]:22000" ssh-rsa ... # Configuration for tunnel forwarding tunnel="0",command="sh /etc/netstart tun0" ssh-rsa ... # Override of restriction to allow PTY allocation restrict,pty,command="nethack" ssh-rsa ... # Allow FIDO key without requiring touch no-touch-required sk-ecdsa-sha2-nistp256@openssh.com ... # Require user-verification (e.g. PIN or biometric) for FIDO key verify-required sk-ecdsa-sha2-nistp256@openssh.com ... # Trust CA key, allow touch-less FIDO if requested in certificate cert-authority,no-touch-required,principals="user_a" ssh-rsa ... .Ed .Sh SSH_KNOWN_HOSTS FILE FORMAT The .Pa /etc/ssh/ssh_known_hosts and .Pa ~/.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 to an unknown host, its key is added to the per-user file. .Pp Each line in these files contains the following fields: marker (optional), 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 .Dq @cert-authority , to indicate that the line contains a certification authority (CA) key, or .Dq @revoked , 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. .Pp Hostnames is a comma-separated list of patterns .Pf ( Ql * and .Ql \&? act as 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 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 .Ql \&[ and .Ql \&] brackets then followed by .Ql \&: and a non-standard port number. .Pp 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 .Ql | character. Only one hashed hostname may appear on a single line and none of the above negation or wildcard operators may be applied. .Pp 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_rsa_key.pub . The optional comment field continues to the end of the line, and is not used. .Pp Lines starting with .Ql # and empty lines are ignored as comments. .Pp 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 .Dq @cert-authority marker described above. .Pp 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 .Dq @revoked 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 .Xr ssh 1 when they are encountered. .Pp 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. .Pp 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, 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 .Pa ~/.ssh/known_hosts including removing hosts matching a host name and converting all host names to their hashed representations. .Pp An example ssh_known_hosts file: .Bd -literal -offset 3n # Comments allowed at start of line 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... .Ed .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.hushlogin This file is used to suppress printing the last login time and .Pa /etc/motd , if .Cm PrintLastLog and .Cm PrintMotd , respectively, are enabled. It does not suppress printing of the banner specified by .Cm Banner . .Pp .It Pa ~/.rhosts This file is used for host-based authentication (see .Xr 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 .Nm reads it as root. Additionally, this file must be owned by the user, and must not have write permissions for anyone else. The recommended permission for most machines is read/write for the user, and not accessible by others. .Pp .It Pa ~/.shosts This file is used in exactly the same way as .Pa .rhosts , but allows host-based authentication without permitting login with rlogin/rsh. .Pp .It Pa ~/.ssh/ This directory is the default location for all user-specific configuration and authentication information. There is no general requirement to keep the entire contents of this directory secret, but the recommended permissions are read/write/execute for the user, and not accessible by others. .Pp .It Pa ~/.ssh/authorized_keys Lists the public keys (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. .Pp If this file, the .Pa ~/.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, .Nm will not allow it to be used unless the .Cm StrictModes option has been set to .Dq no . .Pp .It Pa ~/.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 .Ql # ) , 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 .Cm PermitUserEnvironment option. .Pp .It Pa ~/.ssh/known_hosts Contains a list of host keys for all hosts the user has logged into that are not already in the systemwide list of known host keys. 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. .Pp .It Pa ~/.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. .Pp .It Pa /etc/hosts.equiv This file is for host-based authentication (see .Xr ssh 1 ) . It should only be writable by root. .Pp .It Pa /etc/moduli 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 .Xr motd 5 . .Pp .It Pa /etc/nologin If this file exists, .Nm 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. .Pp .It Pa /etc/shosts.equiv This file is used in exactly the same way as .Pa hosts.equiv , but allows host-based authentication without permitting login with rlogin/rsh. .Pp .It Pa /etc/ssh/ssh_host_ecdsa_key .It Pa /etc/ssh/ssh_host_ed25519_key .It Pa /etc/ssh/ssh_host_rsa_key These files contain the private parts of the host keys. These files should only be owned by root, readable only by root, and not accessible to others. Note that .Nm does not start if these files are group/world-accessible. .Pp .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 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 .Xr ssh-keygen 1 . .Pp .It Pa /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared by the system administrator to contain the public host keys of all machines in the organization. The format of this file is described above. This file should be writable only by root/the owner and should be world-readable. .Pp .It Pa /etc/ssh/sshd_config Contains configuration data for .Nm sshd . The file format and configuration options are described in .Xr sshd_config 5 . .Pp .It Pa /etc/ssh/sshrc Similar to .Pa ~/.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. .Pp .It Pa /var/empty .Xr chroot 2 directory used by .Nm 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. .Pp .It Pa /var/run/sshd.pid Contains the process ID of the .Nm 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. .El .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 , .Xr ssh-keyscan 1 , .Xr chroot 2 , .Xr login.conf 5 , .Xr moduli 5 , .Xr sshd_config 5 , .Xr inetd 8 , .Xr sftp-server 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. Niels Provos and Markus Friedl contributed support for privilege separation. openssh-10.0p1/PaxHeaders.10889/sshd.c100644 001750 001750 0000000003614775415623 0014261xustar0030 atime=1744182234.870921232 openssh-10.0p1/sshd.c010064400017500001750000001504371477541562300126560ustar00djmdjm/* $OpenBSD: sshd.c,v 1.617 2025/04/07 08:12:22 dtucker Exp $ */ /* * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #include "openbsd-compat/openssl-compat.h" #endif #ifdef HAVE_SECUREWARE #include #include #endif #include "xmalloc.h" #include "ssh.h" #include "sshpty.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "servconf.h" #include "compat.h" #include "digest.h" #include "sshkey.h" #include "authfile.h" #include "pathnames.h" #include "canohost.h" #include "hostfile.h" #include "auth.h" #include "authfd.h" #include "msg.h" #include "version.h" #include "ssherr.h" #include "sk-api.h" #include "addr.h" #include "srclimit.h" #include "atomicio.h" /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 2) #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 3) extern char *__progname; /* Server configuration options. */ ServerOptions options; /* * Debug mode flag. This can be set on the command line. If debug * mode is enabled, extra debugging output will be sent to the system * log, the daemon will not go to background, and will exit after processing * the first connection. */ int debug_flag = 0; /* Saved arguments to main(). */ static char **saved_argv; static int saved_argc; /* * The sockets that the server is listening; this is used in the SIGHUP * signal handler. */ #define MAX_LISTEN_SOCKS 16 static int listen_socks[MAX_LISTEN_SOCKS]; static int num_listen_socks = 0; /* * Any really sensitive data in the application is contained in this * structure. The idea is that this structure could be locked into memory so * that the pages do not get written into swap. However, there are some * problems. The private key contains BIGNUMs, and we do not (in principle) * have access to the internals of them, and locking just the structure is * not very useful. Currently, memory locking is not implemented. */ struct { struct sshkey **host_keys; /* all private host keys */ struct sshkey **host_pubkeys; /* all public host keys */ struct sshkey **host_certificates; /* all public host certificates */ int have_ssh2_key; } sensitive_data; /* This is set to true when a signal is received. */ static volatile sig_atomic_t received_siginfo = 0; static volatile sig_atomic_t received_sigchld = 0; static volatile sig_atomic_t received_sighup = 0; static volatile sig_atomic_t received_sigterm = 0; /* record remote hostname or ip */ u_int utmp_len = HOST_NAME_MAX+1; /* * The early_child/children array below is used for tracking children of the * listening sshd process early in their lifespans, before they have * completed authentication. This tracking is needed for four 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. * 4) Tracking and logging unsuccessful exits from the preauth sshd monitor, * including and especially those for LoginGraceTime timeouts. * * 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 sending a * second char over the socket before closing it, otherwise the listener will * continue tracking the child (and using up a MaxStartups slot) until the * preauth subprocess exits, whereupon the listener will log its exit status. * preauth processes will exit with a status of EXIT_LOGIN_GRACE to indicate * they did not authenticate before the LoginGraceTime alarm fired. */ struct early_child { int pipefd; int early; /* Indicates child closed listener */ char *id; /* human readable connection identifier */ pid_t pid; struct xaddr addr; int have_addr; int status, have_status; struct sshbuf *config; struct sshbuf *keys; }; static struct early_child *children; static int children_active; /* sshd_config buffer */ struct sshbuf *cfg; struct sshbuf *config; /* packed */ /* Included files from the configuration file */ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); /* message to be displayed after login */ struct sshbuf *loginmsg; /* Unprivileged user */ struct passwd *privsep_pw = NULL; static char *listener_proctitle; /* * Close all listening sockets */ static void close_listen_socks(void) { int i; for (i = 0; i < num_listen_socks; i++) close(listen_socks[i]); num_listen_socks = 0; } /* Allocate and initialise the children array */ static void child_alloc(void) { int i; children = xcalloc(options.max_startups, sizeof(*children)); for (i = 0; i < options.max_startups; i++) { children[i].pipefd = -1; children[i].pid = -1; } } /* Register a new connection in the children array; child pid comes later */ static struct early_child * child_register(int pipefd, int sockfd) { int i, lport, rport; char *laddr = NULL, *raddr = NULL; struct early_child *child = NULL; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); struct sockaddr *sa = (struct sockaddr *)&addr; for (i = 0; i < options.max_startups; i++) { if (children[i].pipefd != -1 || children[i].config != NULL || children[i].keys != NULL || children[i].pid > 0) continue; child = &(children[i]); break; } if (child == NULL) { fatal_f("error: accepted connection when all %d child " " slots full", options.max_startups); } child->pipefd = pipefd; child->early = 1; if ((child->config = sshbuf_fromb(config)) == NULL) fatal_f("sshbuf_fromb failed"); /* record peer address, if available */ if (getpeername(sockfd, sa, &addrlen) == 0 && addr_sa_to_xaddr(sa, addrlen, &child->addr) == 0) child->have_addr = 1; /* format peer address string for logs */ if ((lport = get_local_port(sockfd)) == 0 || (rport = get_peer_port(sockfd)) == 0) { /* Not a TCP socket */ raddr = get_peer_ipaddr(sockfd); xasprintf(&child->id, "connection from %s", raddr); } else { laddr = get_local_ipaddr(sockfd); raddr = get_peer_ipaddr(sockfd); xasprintf(&child->id, "connection from %s to %s", raddr, laddr); } free(laddr); free(raddr); if (++children_active > options.max_startups) fatal_f("internal error: more children than max_startups"); return child; } /* * Finally free a child entry. Don't call this directly. */ static void child_finish(struct early_child *child) { if (children_active == 0) fatal_f("internal error: children_active underflow"); if (child->pipefd != -1) close(child->pipefd); sshbuf_free(child->config); sshbuf_free(child->keys); free(child->id); memset(child, '\0', sizeof(*child)); child->pipefd = -1; child->pid = -1; children_active--; } /* * Close a child's pipe. This will not stop tracking the child immediately * (it will still be tracked for waitpid()) unless force_final is set, or * child has already exited. */ static void child_close(struct early_child *child, int force_final, int quiet) { if (!quiet) debug_f("enter%s", force_final ? " (forcing)" : ""); if (child->pipefd != -1) { close(child->pipefd); child->pipefd = -1; } if (child->pid == -1 || force_final) child_finish(child); } /* Record a child exit. Safe to call from signal handlers */ static void child_exit(pid_t pid, int status) { int i; if (children == NULL || pid <= 0) return; for (i = 0; i < options.max_startups; i++) { if (children[i].pid == pid) { children[i].have_status = 1; children[i].status = status; break; } } } /* * Reap a child entry that has exited, as previously flagged * using child_exit(). * Handles logging of exit condition and will finalise the child if its pipe * had already been closed. */ static void child_reap(struct early_child *child) { LogLevel level = SYSLOG_LEVEL_DEBUG1; int was_crash, penalty_type = SRCLIMIT_PENALTY_NONE; const char *child_status; if (child->config) child_status = " (sending config)"; else if (child->keys) child_status = " (sending keys)"; else if (child->early) child_status = " (early)"; else child_status = ""; /* Log exit information */ if (WIFSIGNALED(child->status)) { /* * Increase logging for signals potentially associated * with serious conditions. */ if ((was_crash = signal_is_crash(WTERMSIG(child->status)))) level = SYSLOG_LEVEL_ERROR; do_log2(level, "session process %ld for %s killed by " "signal %d%s", (long)child->pid, child->id, WTERMSIG(child->status), child_status); if (was_crash) penalty_type = SRCLIMIT_PENALTY_CRASH; } else if (!WIFEXITED(child->status)) { penalty_type = SRCLIMIT_PENALTY_CRASH; error("session process %ld for %s terminated abnormally, " "status=0x%x%s", (long)child->pid, child->id, child->status, child_status); } else { /* Normal exit. We care about the status */ switch (WEXITSTATUS(child->status)) { case 0: debug3_f("preauth child %ld for %s completed " "normally%s", (long)child->pid, child->id, child_status); break; case EXIT_LOGIN_GRACE: penalty_type = SRCLIMIT_PENALTY_GRACE_EXCEEDED; logit("Timeout before authentication for %s, " "pid = %ld%s", child->id, (long)child->pid, child_status); break; case EXIT_CHILD_CRASH: penalty_type = SRCLIMIT_PENALTY_CRASH; logit("Session process %ld unpriv child crash for %s%s", (long)child->pid, child->id, child_status); break; case EXIT_AUTH_ATTEMPTED: penalty_type = SRCLIMIT_PENALTY_AUTHFAIL; debug_f("preauth child %ld for %s exited " "after unsuccessful auth attempt%s", (long)child->pid, child->id, child_status); break; case EXIT_CONFIG_REFUSED: penalty_type = SRCLIMIT_PENALTY_REFUSECONNECTION; debug_f("preauth child %ld for %s prohibited by" "RefuseConnection%s", (long)child->pid, child->id, child_status); break; default: penalty_type = SRCLIMIT_PENALTY_NOAUTH; debug_f("preauth child %ld for %s exited " "with status %d%s", (long)child->pid, child->id, WEXITSTATUS(child->status), child_status); break; } } if (child->have_addr) srclimit_penalise(&child->addr, penalty_type); child->pid = -1; child->have_status = 0; if (child->pipefd == -1) child_finish(child); } /* Reap all children that have exited; called after SIGCHLD */ static void child_reap_all_exited(void) { int i; pid_t pid; int status; if (children == NULL) return; for (;;) { if ((pid = waitpid(-1, &status, WNOHANG)) == 0) break; else if (pid == -1) { if (errno == EINTR || errno == EAGAIN) continue; if (errno != ECHILD) error_f("waitpid: %s", strerror(errno)); break; } child_exit(pid, status); } for (i = 0; i < options.max_startups; i++) { if (!children[i].have_status) continue; child_reap(&(children[i])); } } static void close_startup_pipes(void) { int i; if (children == NULL) return; for (i = 0; i < options.max_startups; i++) { if (children[i].pipefd != -1) child_close(&(children[i]), 1, 1); } } /* Called after SIGINFO */ static void show_info(void) { int i; const char *child_status; /* XXX print listening sockets here too */ if (children == NULL) return; logit("%d active startups", children_active); for (i = 0; i < options.max_startups; i++) { if (children[i].pipefd == -1 && children[i].pid <= 0) continue; if (children[i].config) child_status = " (sending config)"; else if (children[i].keys) child_status = " (sending keys)"; else if (children[i].early) child_status = " (early)"; else child_status = ""; logit("child %d: fd=%d pid=%ld %s%s", i, children[i].pipefd, (long)children[i].pid, children[i].id, child_status); } srclimit_penalty_info(); } /* * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; * the effect is to reread the configuration file (and to regenerate * the server key). */ static void sighup_handler(int sig) { received_sighup = 1; } /* * Called from the main program after receiving SIGHUP. * Restarts the server. */ static void sighup_restart(void) { logit("Received SIGHUP; restarting."); if (options.pid_file != NULL) unlink(options.pid_file); platform_pre_restart(); close_listen_socks(); close_startup_pipes(); ssh_signal(SIGHUP, SIG_IGN); /* will be restored after exec */ execv(saved_argv[0], saved_argv); logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], strerror(errno)); exit(1); } /* * Generic signal handler for terminating signals in the master daemon. */ static void sigterm_handler(int sig) { received_sigterm = sig; } #ifdef SIGINFO static void siginfo_handler(int sig) { received_siginfo = 1; } #endif static void main_sigchld_handler(int sig) { received_sigchld = 1; } /* * returns 1 if connection should be dropped, 0 otherwise. * dropping starts at connection #max_startups_begin with a probability * of (max_startups_rate/100). the probability increases linearly until * all connections are dropped for startups > max_startups */ static int should_drop_connection(int startups) { int p, r; if (startups < options.max_startups_begin) return 0; if (startups >= options.max_startups) return 1; if (options.max_startups_rate == 100) return 1; p = 100 - options.max_startups_rate; p *= startups - options.max_startups_begin; p /= options.max_startups - options.max_startups_begin; p += options.max_startups_rate; r = arc4random_uniform(100); debug_f("p %d, r %d", p, r); return (r < p) ? 1 : 0; } /* * Check whether connection should be accepted by MaxStartups or for penalty. * Returns 0 if the connection is accepted. If the connection is refused, * returns 1 and attempts to send notification to client. * Logs when the MaxStartups condition is entered or exited, and periodically * while in that state. */ static int drop_connection(int sock, int startups, int notify_pipe) { static struct log_ratelimit_ctx ratelimit_maxstartups; static struct log_ratelimit_ctx ratelimit_penalty; static int init_done; char *laddr, *raddr; const char *reason = NULL, *subreason = NULL; const char msg[] = "Not allowed at this time\r\n"; struct log_ratelimit_ctx *rl = NULL; int ratelimited; u_int ndropped; if (!init_done) { init_done = 1; log_ratelimit_init(&ratelimit_maxstartups, 4, 60, 20, 5*60); log_ratelimit_init(&ratelimit_penalty, 8, 60, 30, 2*60); } /* PerSourcePenalties */ if (!srclimit_penalty_check_allow(sock, &subreason)) { reason = "PerSourcePenalties"; rl = &ratelimit_penalty; } else { /* MaxStartups */ if (!should_drop_connection(startups) && srclimit_check_allow(sock, notify_pipe) == 1) return 0; reason = "Maxstartups"; rl = &ratelimit_maxstartups; } laddr = get_local_ipaddr(sock); raddr = get_peer_ipaddr(sock); ratelimited = log_ratelimit(rl, time(NULL), NULL, &ndropped); do_log2(ratelimited ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO, "drop connection #%d from [%s]:%d on [%s]:%d %s", startups, raddr, get_peer_port(sock), laddr, get_local_port(sock), subreason != NULL ? subreason : reason); free(laddr); free(raddr); if (ndropped != 0) { logit("%s logging rate-limited: additional %u connections " "dropped", reason, ndropped); } /* best-effort notification to client */ (void)write(sock, msg, sizeof(msg) - 1); return 1; } static void usage(void) { fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); fprintf(stderr, "usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n" " [-E log_file] [-f config_file] [-g login_grace_time]\n" " [-h host_key_file] [-o option] [-p port] [-u len]\n" ); exit(1); } static struct sshbuf * pack_hostkeys(void) { struct sshbuf *m = NULL, *keybuf = NULL, *hostkeys = NULL; int r; u_int i; size_t len; if ((m = sshbuf_new()) == NULL || (keybuf = sshbuf_new()) == NULL || (hostkeys = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* pack hostkeys into a string. Empty key slots get empty strings */ for (i = 0; i < options.num_host_key_files; i++) { /* private key */ sshbuf_reset(keybuf); if (sensitive_data.host_keys[i] != NULL && (r = sshkey_private_serialize(sensitive_data.host_keys[i], keybuf)) != 0) fatal_fr(r, "serialize hostkey private"); if ((r = sshbuf_put_stringb(hostkeys, keybuf)) != 0) fatal_fr(r, "compose hostkey private"); /* public key */ if (sensitive_data.host_pubkeys[i] != NULL) { if ((r = sshkey_puts(sensitive_data.host_pubkeys[i], hostkeys)) != 0) fatal_fr(r, "compose hostkey public"); } else { if ((r = sshbuf_put_string(hostkeys, NULL, 0)) != 0) fatal_fr(r, "compose hostkey empty public"); } /* cert */ if (sensitive_data.host_certificates[i] != NULL) { if ((r = sshkey_puts( sensitive_data.host_certificates[i], hostkeys)) != 0) fatal_fr(r, "compose host cert"); } else { if ((r = sshbuf_put_string(hostkeys, NULL, 0)) != 0) fatal_fr(r, "compose host cert empty"); } } if ((r = sshbuf_put_u32(m, 0)) != 0 || (r = sshbuf_put_u8(m, 0)) != 0 || (r = sshbuf_put_stringb(m, hostkeys)) != 0) fatal_fr(r, "compose message"); if ((len = sshbuf_len(m)) < 5 || len > 0xffffffff) fatal_f("bad length %zu", len); POKE_U32(sshbuf_mutable_ptr(m), len - 4); sshbuf_free(keybuf); sshbuf_free(hostkeys); return m; } static struct sshbuf * pack_config(struct sshbuf *conf) { struct sshbuf *m = NULL, *inc = NULL; struct include_item *item = NULL; size_t len; int r; debug3_f("d config len %zu", sshbuf_len(conf)); if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* pack includes into a string */ TAILQ_FOREACH(item, &includes, entry) { if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 || (r = sshbuf_put_cstring(inc, item->filename)) != 0 || (r = sshbuf_put_stringb(inc, item->contents)) != 0) fatal_fr(r, "compose includes"); } if ((r = sshbuf_put_u32(m, 0)) != 0 || (r = sshbuf_put_u8(m, 0)) != 0 || (r = sshbuf_put_stringb(m, conf)) != 0 || (r = sshbuf_put_u64(m, options.timing_secret)) != 0 || (r = sshbuf_put_stringb(m, inc)) != 0) fatal_fr(r, "compose config"); if ((len = sshbuf_len(m)) < 5 || len > 0xffffffff) fatal_f("bad length %zu", len); POKE_U32(sshbuf_mutable_ptr(m), len - 4); sshbuf_free(inc); debug3_f("done"); return m; } /* * Protocol from reexec master to child: * uint32 size * uint8 type (ignored) * string configuration * uint64 timing_secret * string included_files[] { * string selector * string filename * string contents * } * Second message * uint32 size * uint8 type (ignored) * string host_keys[] { * string private_key * string public_key * string certificate * } */ /* * This function is used only if inet_flag or debug_flag is set, * otherwise the data is sent from the main poll loop. * It sends the config from a child process back to the parent. * The parent will read the config after exec. */ static void send_rexec_state(int fd) { struct sshbuf *keys; u_int mlen; pid_t pid; if ((pid = fork()) == -1) fatal_f("fork failed: %s", strerror(errno)); if (pid != 0) return; debug3_f("entering fd = %d config len %zu", fd, sshbuf_len(config)); mlen = sshbuf_len(config); if (atomicio(vwrite, fd, sshbuf_mutable_ptr(config), mlen) != mlen) error_f("write: %s", strerror(errno)); keys = pack_hostkeys(); mlen = sshbuf_len(keys); if (atomicio(vwrite, fd, sshbuf_mutable_ptr(keys), mlen) != mlen) error_f("write: %s", strerror(errno)); sshbuf_free(keys); debug3_f("done"); exit(0); } /* * Listen for TCP connections */ static void listen_on_addrs(struct listenaddr *la) { int ret, listen_sock; struct addrinfo *ai; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; for (ai = la->addrs; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; if (num_listen_socks >= MAX_LISTEN_SOCKS) fatal("Too many listen sockets. " "Enlarge MAX_LISTEN_SOCKS"); if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { error("getnameinfo failed: %.100s", ssh_gai_strerror(ret)); continue; } /* Create socket for listening. */ listen_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (listen_sock == -1) { /* kernel may not support ipv6 */ verbose("socket: %.100s", strerror(errno)); continue; } if (set_nonblock(listen_sock) == -1) { close(listen_sock); continue; } if (fcntl(listen_sock, F_SETFD, FD_CLOEXEC) == -1) { verbose("socket: CLOEXEC: %s", strerror(errno)); close(listen_sock); continue; } /* Socket options */ set_reuseaddr(listen_sock); if (la->rdomain != NULL && set_rdomain(listen_sock, la->rdomain) == -1) { close(listen_sock); continue; } /* Only communicate in IPv6 over AF_INET6 sockets. */ if (ai->ai_family == AF_INET6) sock_set_v6only(listen_sock); debug("Bind to port %s on %s.", strport, ntop); /* Bind the socket to the desired port. */ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) == -1) { error("Bind to port %s on %s failed: %.200s.", strport, ntop, strerror(errno)); close(listen_sock); continue; } listen_socks[num_listen_socks] = listen_sock; num_listen_socks++; /* Start listening on the port. */ if (listen(listen_sock, SSH_LISTEN_BACKLOG) == -1) fatal("listen on [%s]:%s: %.100s", ntop, strport, strerror(errno)); logit("Server listening on %s port %s%s%s.", ntop, strport, la->rdomain == NULL ? "" : " rdomain ", la->rdomain == NULL ? "" : la->rdomain); } } static void server_listen(void) { u_int i; /* Initialise per-source limit tracking. */ srclimit_init(options.max_startups, options.per_source_max_startups, options.per_source_masklen_ipv4, options.per_source_masklen_ipv6, &options.per_source_penalty, options.per_source_penalty_exempt); for (i = 0; i < options.num_listen_addrs; i++) { listen_on_addrs(&options.listen_addrs[i]); freeaddrinfo(options.listen_addrs[i].addrs); free(options.listen_addrs[i].rdomain); memset(&options.listen_addrs[i], 0, sizeof(options.listen_addrs[i])); } free(options.listen_addrs); options.listen_addrs = NULL; options.num_listen_addrs = 0; if (!num_listen_socks) fatal("Cannot bind any address."); } /* * The main TCP accept loop. Note that, for the non-debug case, returns * from this function are in a forked subprocess. */ static void server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, int log_stderr) { struct pollfd *pfd = NULL; int i, ret, npfd, r; int oactive = -1, listening = 0, lameduck = 0; int *startup_pollfd; ssize_t len; const u_char *ptr; char c = 0; struct sockaddr_storage from; struct early_child *child; struct sshbuf *buf; socklen_t fromlen; u_char rnd[256]; sigset_t nsigset, osigset; /* pipes connected to unauthenticated child sshd processes */ child_alloc(); startup_pollfd = xcalloc(options.max_startups, sizeof(int)); /* * Prepare signal mask that we use to block signals that might set * received_sigterm/hup/chld/info, so that we are guaranteed * to immediately wake up the ppoll if a signal is received after * the flag is checked. */ sigemptyset(&nsigset); sigaddset(&nsigset, SIGHUP); sigaddset(&nsigset, SIGCHLD); #ifdef SIGINFO sigaddset(&nsigset, SIGINFO); #endif sigaddset(&nsigset, SIGTERM); sigaddset(&nsigset, SIGQUIT); /* sized for worst-case */ pfd = xcalloc(num_listen_socks + options.max_startups, sizeof(struct pollfd)); /* * Stay listening for connections until the system crashes or * the daemon is killed with a signal. */ for (;;) { sigprocmask(SIG_BLOCK, &nsigset, &osigset); if (received_sigterm) { logit("Received signal %d; terminating.", (int) received_sigterm); close_listen_socks(); if (options.pid_file != NULL) unlink(options.pid_file); exit(received_sigterm == SIGTERM ? 0 : 255); } if (received_sigchld) { child_reap_all_exited(); received_sigchld = 0; } if (received_siginfo) { show_info(); received_siginfo = 0; } if (oactive != children_active) { setproctitle("%s [listener] %d of %d-%d startups", listener_proctitle, children_active, options.max_startups_begin, options.max_startups); oactive = children_active; } if (received_sighup) { if (!lameduck) { debug("Received SIGHUP; waiting for children"); close_listen_socks(); lameduck = 1; } if (listening <= 0) { sigprocmask(SIG_SETMASK, &osigset, NULL); sighup_restart(); } } for (i = 0; i < num_listen_socks; i++) { pfd[i].fd = listen_socks[i]; pfd[i].events = POLLIN; } npfd = num_listen_socks; for (i = 0; i < options.max_startups; i++) { startup_pollfd[i] = -1; if (children[i].pipefd != -1) { pfd[npfd].fd = children[i].pipefd; pfd[npfd].events = POLLIN; if (children[i].config != NULL || children[i].keys != NULL) pfd[npfd].events |= POLLOUT; startup_pollfd[i] = npfd++; } } /* Wait until a connection arrives or a child exits. */ ret = ppoll(pfd, npfd, NULL, &osigset); if (ret == -1 && errno != EINTR) { error("ppoll: %.100s", strerror(errno)); if (errno == EINVAL) cleanup_exit(1); /* can't recover */ } sigprocmask(SIG_SETMASK, &osigset, NULL); if (ret == -1) continue; for (i = 0; i < options.max_startups; i++) { if (children[i].pipefd == -1 || startup_pollfd[i] == -1 || !(pfd[startup_pollfd[i]].revents & POLLOUT)) continue; if (children[i].config) buf = children[i].config; else if (children[i].keys) buf = children[i].keys; else { error_f("no buffer to send"); continue; } ptr = sshbuf_ptr(buf); len = sshbuf_len(buf); ret = write(children[i].pipefd, ptr, len); if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue; if (ret <= 0) { if (children[i].early) listening--; srclimit_done(children[i].pipefd); child_close(&(children[i]), 0, 0); continue; } if (ret == len) { /* finished sending buffer */ sshbuf_free(buf); if (children[i].config == buf) { /* sent config, now send keys */ children[i].config = NULL; children[i].keys = pack_hostkeys(); } else if (children[i].keys == buf) { /* sent both config and keys */ children[i].keys = NULL; } else { fatal("config buf not set"); } } else { if ((r = sshbuf_consume(buf, ret)) != 0) fatal_fr(r, "config buf inconsistent"); } } for (i = 0; i < options.max_startups; i++) { if (children[i].pipefd == -1 || startup_pollfd[i] == -1 || !(pfd[startup_pollfd[i]].revents & (POLLIN|POLLHUP))) continue; switch (read(children[i].pipefd, &c, sizeof(c))) { case -1: if (errno == EINTR || errno == EAGAIN) continue; if (errno != EPIPE) { error_f("startup pipe %d (fd=%d): " "read %s", i, children[i].pipefd, strerror(errno)); } /* FALLTHROUGH */ case 0: /* child exited preauth */ if (children[i].early) listening--; srclimit_done(children[i].pipefd); child_close(&(children[i]), 0, 0); break; case 1: if (children[i].config) { error_f("startup pipe %d (fd=%d)" " early read", i, children[i].pipefd); if (children[i].early) listening--; if (children[i].pid > 0) kill(children[i].pid, SIGTERM); srclimit_done(children[i].pipefd); child_close(&(children[i]), 0, 0); break; } if (children[i].early && c == '\0') { /* child has finished preliminaries */ listening--; children[i].early = 0; debug2_f("child %lu for %s received " "config", (long)children[i].pid, children[i].id); } else if (!children[i].early && c == '\001') { /* child has completed auth */ debug2_f("child %lu for %s auth done", (long)children[i].pid, children[i].id); child_close(&(children[i]), 1, 0); } else { error_f("unexpected message 0x%02x " "child %ld for %s in state %d", (int)c, (long)children[i].pid, children[i].id, children[i].early); } break; } } for (i = 0; i < num_listen_socks; i++) { if (!(pfd[i].revents & POLLIN)) continue; fromlen = sizeof(from); *newsock = accept(listen_socks[i], (struct sockaddr *)&from, &fromlen); if (*newsock == -1) { if (errno != EINTR && errno != EWOULDBLOCK && errno != ECONNABORTED && errno != EAGAIN) error("accept: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) usleep(100 * 1000); continue; } if (unset_nonblock(*newsock) == -1) { close(*newsock); continue; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, config_s) == -1) { error("reexec socketpair: %s", strerror(errno)); close(*newsock); continue; } if (drop_connection(*newsock, children_active, config_s[0])) { close(*newsock); close(config_s[0]); close(config_s[1]); continue; } /* * Got connection. Fork a child to handle it, unless * we are in debugging mode. */ if (debug_flag) { /* * In debugging mode. Close the listening * socket, and start processing the * connection without forking. */ debug("Server will not fork when running in debugging mode."); close_listen_socks(); *sock_in = *newsock; *sock_out = *newsock; send_rexec_state(config_s[0]); close(config_s[0]); free(pfd); return; } /* * Normal production daemon. Fork, and have * the child process the connection. The * parent continues listening. */ platform_pre_fork(); set_nonblock(config_s[0]); listening++; child = child_register(config_s[0], *newsock); if ((child->pid = fork()) == 0) { /* * Child. Close the listening and * max_startup sockets. Start using * the accepted socket. Reinitialize * logging (since our pid has changed). * We return from this function to handle * the connection. */ platform_post_fork_child(); close_startup_pipes(); close_listen_socks(); *sock_in = *newsock; *sock_out = *newsock; log_init(__progname, options.log_level, options.log_facility, log_stderr); close(config_s[0]); free(pfd); return; } /* Parent. Stay in the loop. */ platform_post_fork_parent(child->pid); if (child->pid == -1) error("fork: %.100s", strerror(errno)); else debug("Forked child %ld.", (long)child->pid); close(config_s[1]); close(*newsock); /* * Ensure that our random state differs * from that of the child */ arc4random_stir(); arc4random_buf(rnd, sizeof(rnd)); #ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); if ((RAND_bytes((u_char *)rnd, 1)) != 1) fatal("%s: RAND_bytes failed", __func__); #endif explicit_bzero(rnd, sizeof(rnd)); } } } static void accumulate_host_timing_secret(struct sshbuf *server_cfg, struct sshkey *key) { static struct ssh_digest_ctx *ctx; u_char *hash; size_t len; struct sshbuf *buf; int r; if (ctx == NULL && (ctx = ssh_digest_start(SSH_DIGEST_SHA512)) == NULL) fatal_f("ssh_digest_start"); if (key == NULL) { /* finalize */ /* add server config in case we are using agent for host keys */ if (ssh_digest_update(ctx, sshbuf_ptr(server_cfg), sshbuf_len(server_cfg)) != 0) fatal_f("ssh_digest_update"); len = ssh_digest_bytes(SSH_DIGEST_SHA512); hash = xmalloc(len); if (ssh_digest_final(ctx, hash, len) != 0) fatal_f("ssh_digest_final"); options.timing_secret = PEEK_U64(hash); freezero(hash, len); ssh_digest_free(ctx); ctx = NULL; return; } if ((buf = sshbuf_new()) == NULL) fatal_f("could not allocate buffer"); if ((r = sshkey_private_serialize(key, buf)) != 0) fatal_fr(r, "encode %s key", sshkey_ssh_name(key)); if (ssh_digest_update(ctx, sshbuf_ptr(buf), sshbuf_len(buf)) != 0) fatal_f("ssh_digest_update"); sshbuf_reset(buf); sshbuf_free(buf); } static char * prepare_proctitle(int ac, char **av) { char *ret = NULL; int i; for (i = 0; i < ac; i++) xextendf(&ret, " ", "%s", av[i]); return ret; } static void print_config(struct connection_info *connection_info) { connection_info->test = 1; parse_server_match_config(&options, &includes, connection_info); dump_config(&options); exit(0); } /* * Main program for the daemon. */ int main(int ac, char **av) { extern char *optarg; extern int optind; int log_stderr = 0, inetd_flag = 0, test_flag = 0, no_daemon_flag = 0; char *config_file_name = _PATH_SERVER_CONFIG_FILE; int r, opt, do_dump_cfg = 0, keytype, already_daemon, have_agent = 0; int sock_in = -1, sock_out = -1, newsock = -1, rexec_argc = 0; int devnull, config_s[2] = { -1 , -1 }, have_connection_info = 0; int need_chroot = 1; char *args, *fp, *line, *logfile = NULL, **rexec_argv = NULL; struct stat sb; u_int i, j; mode_t new_umask; struct sshkey *key; struct sshkey *pubkey; struct connection_info connection_info; struct utsname utsname; sigset_t sigmask; memset(&connection_info, 0, sizeof(connection_info)); #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); #endif __progname = ssh_get_progname(av[0]); sigemptyset(&sigmask); sigprocmask(SIG_SETMASK, &sigmask, NULL); /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; rexec_argc = ac; saved_argv = xcalloc(ac + 1, sizeof(*saved_argv)); for (i = 0; (int)i < ac; i++) saved_argv[i] = xstrdup(av[i]); saved_argv[i] = NULL; #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ compat_init_setproctitle(ac, av); av = saved_argv; #endif if (geteuid() == 0 && setgroups(0, NULL) == -1) debug("setgroups(): %.200s", strerror(errno)); /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* Initialize configuration options to their default values. */ initialize_server_options(&options); /* Parse command-line arguments. */ args = argv_assemble(ac, av); /* logged later */ while ((opt = getopt(ac, av, "C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) { switch (opt) { case '4': options.address_family = AF_INET; break; case '6': options.address_family = AF_INET6; break; case 'f': config_file_name = optarg; break; case 'c': servconf_add_hostcert("[command-line]", 0, &options, optarg); break; case 'd': if (debug_flag == 0) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) options.log_level++; break; case 'D': no_daemon_flag = 1; break; case 'G': do_dump_cfg = 1; break; case 'E': logfile = optarg; /* FALLTHROUGH */ case 'e': log_stderr = 1; break; case 'i': inetd_flag = 1; break; case 'r': logit("-r option is deprecated"); break; case 'R': fatal("-R not supported here"); break; case 'Q': /* ignored */ break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'b': /* protocol 1, ignored */ break; case 'p': options.ports_from_cmdline = 1; if (options.num_ports >= MAX_PORTS) { fprintf(stderr, "too many ports.\n"); exit(1); } options.ports[options.num_ports++] = a2port(optarg); if (options.ports[options.num_ports-1] <= 0) { fprintf(stderr, "Bad port number.\n"); exit(1); } break; case 'g': if ((options.login_grace_time = convtime(optarg)) == -1) { fprintf(stderr, "Invalid login grace time.\n"); exit(1); } break; case 'k': /* protocol 1, ignored */ break; case 'h': servconf_add_hostkey("[command-line]", 0, &options, optarg, 1); break; case 't': test_flag = 1; break; case 'T': test_flag = 2; break; case 'C': if (parse_server_match_testspec(&connection_info, optarg) == -1) exit(1); have_connection_info = 1; break; case 'u': utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL); if (utmp_len > HOST_NAME_MAX+1) { fprintf(stderr, "Invalid utmp length.\n"); exit(1); } break; case 'o': line = xstrdup(optarg); if (process_server_config_line(&options, line, "command-line", 0, NULL, NULL, &includes) != 0) exit(1); free(line); break; case 'V': fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); exit(0); default: usage(); break; } } if (!test_flag && !inetd_flag && !do_dump_cfg && !path_absolute(av[0])) fatal("sshd requires execution with an absolute path"); closefrom(STDERR_FILENO + 1); /* Reserve fds we'll need later for reexec things */ if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) fatal("open %s: %s", _PATH_DEVNULL, strerror(errno)); while (devnull < REEXEC_MIN_FREE_FD) { if ((devnull = dup(devnull)) == -1) fatal("dup %s: %s", _PATH_DEVNULL, strerror(errno)); } seed_rng(); /* If requested, redirect the logs to the specified logfile. */ if (logfile != NULL) { char *cp, pid_s[32]; snprintf(pid_s, sizeof(pid_s), "%ld", (unsigned long)getpid()); cp = percent_expand(logfile, "p", pid_s, "P", "sshd", (char *)NULL); log_redirect_stderr_to(cp); free(cp); } /* * Force logging to stderr until we have loaded the private host * key (unless started from inetd) */ log_init(__progname, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_AUTH : options.log_facility, log_stderr || !inetd_flag || debug_flag); /* * Unset KRB5CCNAME, otherwise the user's session may inherit it from * root's environment */ if (getenv("KRB5CCNAME") != NULL) (void) unsetenv("KRB5CCNAME"); sensitive_data.have_ssh2_key = 0; /* * If we're not doing an extended test do not silently ignore connection * test params. */ if (test_flag < 2 && have_connection_info) fatal("Config test connection parameter (-C) provided without " "test mode (-T)"); debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); if (uname(&utsname) != 0) { memset(&utsname, 0, sizeof(utsname)); strlcpy(utsname.sysname, "UNKNOWN", sizeof(utsname.sysname)); } debug3("Running on %s %s %s %s", utsname.sysname, utsname.release, utsname.version, utsname.machine); debug3("Started with: %s", args); free(args); /* Fetch our configuration */ if ((cfg = sshbuf_new()) == NULL) fatal("sshbuf_new config failed"); if (strcasecmp(config_file_name, "none") != 0) load_server_config(config_file_name, cfg); parse_server_config(&options, config_file_name, cfg, &includes, NULL, 0); /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); /* Check that options are sensible */ if (options.authorized_keys_command_user == NULL && (options.authorized_keys_command != NULL && strcasecmp(options.authorized_keys_command, "none") != 0)) fatal("AuthorizedKeysCommand set without " "AuthorizedKeysCommandUser"); if (options.authorized_principals_command_user == NULL && (options.authorized_principals_command != NULL && strcasecmp(options.authorized_principals_command, "none") != 0)) fatal("AuthorizedPrincipalsCommand set without " "AuthorizedPrincipalsCommandUser"); /* * Check whether there is any path through configured auth methods. * Unfortunately it is not possible to verify this generally before * daemonisation in the presence of Match blocks, but this catches * and warns for trivial misconfigurations that could break login. */ if (options.num_auth_methods != 0) { for (i = 0; i < options.num_auth_methods; i++) { if (auth2_methods_valid(options.auth_methods[i], 1) == 0) break; } if (i >= options.num_auth_methods) fatal("AuthenticationMethods cannot be satisfied by " "enabled authentication methods"); } /* Check that there are no remaining arguments. */ if (optind < ac) { fprintf(stderr, "Extra argument %s.\n", av[optind]); exit(1); } if (do_dump_cfg) print_config(&connection_info); /* load host keys */ sensitive_data.host_keys = xcalloc(options.num_host_key_files, sizeof(struct sshkey *)); sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, sizeof(struct sshkey *)); if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) setenv(SSH_AUTHSOCKET_ENV_NAME, options.host_key_agent, 1); if ((r = ssh_get_authentication_socket(NULL)) == 0) have_agent = 1; else error_r(r, "Could not connect to agent \"%s\"", options.host_key_agent); } for (i = 0; i < options.num_host_key_files; i++) { int ll = options.host_key_file_userprovided[i] ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_DEBUG1; if (options.host_key_files[i] == NULL) continue; if ((r = sshkey_load_private(options.host_key_files[i], "", &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) do_log2_r(r, ll, "Unable to load host key \"%s\"", options.host_key_files[i]); if (sshkey_is_sk(key) && key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { debug("host key %s requires user presence, ignoring", options.host_key_files[i]); key->sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; } if (r == 0 && key != NULL && (r = sshkey_shield_private(key)) != 0) { do_log2_r(r, ll, "Unable to shield host key \"%s\"", options.host_key_files[i]); sshkey_free(key); key = NULL; } if ((r = sshkey_load_public(options.host_key_files[i], &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) do_log2_r(r, ll, "Unable to load host key \"%s\"", options.host_key_files[i]); if (pubkey != NULL && key != NULL) { if (!sshkey_equal(pubkey, key)) { error("Public key for %s does not match " "private key", options.host_key_files[i]); sshkey_free(pubkey); pubkey = NULL; } } if (pubkey == NULL && key != NULL) { if ((r = sshkey_from_private(key, &pubkey)) != 0) fatal_r(r, "Could not demote key: \"%s\"", options.host_key_files[i]); } if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey, options.required_rsa_size)) != 0) { error_fr(r, "Host key %s", options.host_key_files[i]); sshkey_free(pubkey); sshkey_free(key); continue; } sensitive_data.host_keys[i] = key; sensitive_data.host_pubkeys[i] = pubkey; if (key == NULL && pubkey != NULL && have_agent) { debug("will rely on agent for hostkey %s", options.host_key_files[i]); keytype = pubkey->type; } else if (key != NULL) { keytype = key->type; accumulate_host_timing_secret(cfg, key); } else { do_log2(ll, "Unable to load host key: %s", options.host_key_files[i]); sensitive_data.host_keys[i] = NULL; sensitive_data.host_pubkeys[i] = NULL; continue; } switch (keytype) { case KEY_RSA: case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: case KEY_XMSS: if (have_agent || key != NULL) sensitive_data.have_ssh2_key = 1; break; } if ((fp = sshkey_fingerprint(pubkey, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal("sshkey_fingerprint failed"); debug("%s host key #%d: %s %s", key ? "private" : "agent", i, sshkey_ssh_name(pubkey), fp); free(fp); } accumulate_host_timing_secret(cfg, NULL); if (!sensitive_data.have_ssh2_key) { logit("sshd: no hostkeys available -- exiting."); exit(1); } /* * Load certificates. They are stored in an array at identical * indices to the public keys that they relate to. */ sensitive_data.host_certificates = xcalloc(options.num_host_key_files, sizeof(struct sshkey *)); for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_certificates[i] = NULL; for (i = 0; i < options.num_host_cert_files; i++) { if (options.host_cert_files[i] == NULL) continue; if ((r = sshkey_load_public(options.host_cert_files[i], &key, NULL)) != 0) { error_r(r, "Could not load host certificate \"%s\"", options.host_cert_files[i]); continue; } if (!sshkey_is_cert(key)) { error("Certificate file is not a certificate: %s", options.host_cert_files[i]); sshkey_free(key); continue; } /* Find matching private key */ for (j = 0; j < options.num_host_key_files; j++) { if (sshkey_equal_public(key, sensitive_data.host_pubkeys[j])) { sensitive_data.host_certificates[j] = key; break; } } if (j >= options.num_host_key_files) { error("No matching private key for certificate: %s", options.host_cert_files[i]); sshkey_free(key); continue; } sensitive_data.host_certificates[j] = key; debug("host certificate: #%u type %d %s", j, key->type, sshkey_type(key)); } /* Ensure privsep directory is correctly configured. */ need_chroot = ((getuid() == 0 || geteuid() == 0) || options.kerberos_authentication); if ((getpwnam(SSH_PRIVSEP_USER)) == NULL && need_chroot) { fatal("Privilege separation user %s does not exist", SSH_PRIVSEP_USER); } endpwent(); if (need_chroot) { if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &sb) == -1) || (S_ISDIR(sb.st_mode) == 0)) fatal("Missing privilege separation directory: %s", _PATH_PRIVSEP_CHROOT_DIR); #ifdef HAVE_CYGWIN if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) && (sb.st_uid != getuid () || (sb.st_mode & (S_IWGRP|S_IWOTH)) != 0)) #else if (sb.st_uid != 0 || (sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) #endif fatal("%s must be owned by root and not group or " "world-writable.", _PATH_PRIVSEP_CHROOT_DIR); } if (test_flag > 1) print_config(&connection_info); /* Configuration looks good, so exit if in test mode. */ if (test_flag) exit(0); /* * Clear out any supplemental groups we may have inherited. This * prevents inadvertent creation of files with bad modes (in the * portable version at least, it's certainly possible for PAM * to create a file, and we can't control the code in every * module which might be used). */ if (setgroups(0, NULL) < 0) debug("setgroups() failed: %.200s", strerror(errno)); /* Prepare arguments for sshd-session */ if (rexec_argc < 0) fatal("rexec_argc %d < 0", rexec_argc); rexec_argv = xcalloc(rexec_argc + 3, sizeof(char *)); /* Point to the sshd-session binary instead of sshd */ rexec_argv[0] = options.sshd_session_path; for (i = 1; 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] = NULL; if (stat(rexec_argv[0], &sb) != 0 || !(sb.st_mode & (S_IXOTH|S_IXUSR))) fatal("%s does not exist or is not executable", rexec_argv[0]); debug3("using %s for re-exec", rexec_argv[0]); /* Ensure that the privsep binary exists now too. */ if (stat(options.sshd_auth_path, &sb) != 0 || !(sb.st_mode & (S_IXOTH|S_IXUSR))) { fatal("%s does not exist or is not executable", options.sshd_auth_path); } listener_proctitle = prepare_proctitle(ac, av); /* Ensure that umask disallows at least group and world write */ new_umask = umask(0077) | 0022; (void) umask(new_umask); /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && !inetd_flag) log_stderr = 1; log_init(__progname, options.log_level, options.log_facility, log_stderr); for (i = 0; i < options.num_log_verbose; i++) log_verbose_add(options.log_verbose[i]); /* * If not in debugging mode, not started from inetd and not already * daemonized (eg re-exec via SIGHUP), disconnect from the controlling * terminal, and fork. The original process exits. */ already_daemon = daemonized(); if (!(debug_flag || inetd_flag || no_daemon_flag || already_daemon)) { if (daemon(0, 0) == -1) fatal("daemon() failed: %.200s", strerror(errno)); disconnect_controlling_tty(); } /* Reinitialize the log (because of the fork above). */ log_init(__progname, options.log_level, options.log_facility, log_stderr); /* * Chdir to the root directory so that the current disk can be * unmounted if desired. */ if (chdir("/") == -1) error("chdir(\"/\"): %s", strerror(errno)); /* ignore SIGPIPE */ ssh_signal(SIGPIPE, SIG_IGN); config = pack_config(cfg); /* Get a connection, either from inetd or a listening TCP socket */ if (inetd_flag) { /* Send configuration to ancestor sshd-session process */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, config_s) == -1) fatal("socketpair: %s", strerror(errno)); send_rexec_state(config_s[0]); close(config_s[0]); } else { platform_pre_listen(); server_listen(); ssh_signal(SIGHUP, sighup_handler); ssh_signal(SIGCHLD, main_sigchld_handler); ssh_signal(SIGTERM, sigterm_handler); ssh_signal(SIGQUIT, sigterm_handler); #ifdef SIGINFO ssh_signal(SIGINFO, siginfo_handler); #endif platform_post_listen(); /* * Write out the pid file after the sigterm handler * is setup and the listen sockets are bound */ if (options.pid_file != NULL && !debug_flag) { FILE *f = fopen(options.pid_file, "w"); if (f == NULL) { error("Couldn't create pid file \"%s\": %s", options.pid_file, strerror(errno)); } else { fprintf(f, "%ld\n", (long) getpid()); fclose(f); } } /* Accept a connection and return in a forked child */ server_accept_loop(&sock_in, &sock_out, &newsock, config_s, log_stderr); } /* This is the child processing a new connection. */ setproctitle("%s", "[accepted]"); /* * Create a new session and process group since the 4.4BSD * setlogin() affects the entire process group. We don't * want the child to be able to affect the parent. */ if (!debug_flag && !inetd_flag && setsid() == -1) error("setsid: %.100s", strerror(errno)); debug("rexec start in %d out %d newsock %d config_s %d/%d", sock_in, sock_out, newsock, config_s[0], config_s[1]); if (!inetd_flag) { if (dup2(newsock, STDIN_FILENO) == -1) fatal("dup2 stdin: %s", strerror(errno)); if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1) fatal("dup2 stdout: %s", strerror(errno)); if (newsock > STDOUT_FILENO) close(newsock); } if (config_s[1] != REEXEC_CONFIG_PASS_FD) { if (dup2(config_s[1], REEXEC_CONFIG_PASS_FD) == -1) fatal("dup2 config_s: %s", strerror(errno)); close(config_s[1]); } log_redirect_stderr_to(NULL); closefrom(REEXEC_MIN_FREE_FD); ssh_signal(SIGHUP, SIG_IGN); /* avoid reset to SIG_DFL */ execv(rexec_argv[0], rexec_argv); fatal("rexec of %s failed: %s", rexec_argv[0], strerror(errno)); } /* server specific fatal cleanup */ void cleanup_exit(int i) { _exit(i); } openssh-10.0p1/PaxHeaders.10889/sshd_config100644 001750 001750 0000000003614775415623 0015365xustar0030 atime=1744182234.870921232 openssh-10.0p1/sshd_config010064400017500001750000000063461477541562300137610ustar00djmdjm# $OpenBSD: sshd_config,v 1.105 2024/12/03 14:12:47 dtucker Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin # The strategy used for options in the default sshd_config shipped with # OpenSSH is to specify options with their default value where # possible, but leave them commented. Uncommented options override the # default value. #Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress :: #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_ecdsa_key #HostKey /etc/ssh/ssh_host_ed25519_key # Ciphers and keying #RekeyLimit default none # Logging #SyslogFacility AUTH #LogLevel INFO # Authentication: #LoginGraceTime 2m #PermitRootLogin prohibit-password #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 #PubkeyAuthentication yes # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 # but this is overridden so installations will only check .ssh/authorized_keys AuthorizedKeysFile .ssh/authorized_keys #AuthorizedPrincipalsFile none #AuthorizedKeysCommand none #AuthorizedKeysCommandUser nobody # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #HostbasedAuthentication no # Change to yes if you don't trust ~/.ssh/known_hosts for # HostbasedAuthentication #IgnoreUserKnownHosts no # Don't read the user's ~/.rhosts and ~/.shosts files #IgnoreRhosts yes # To disable tunneled clear text passwords, change to "no" here! #PasswordAuthentication yes #PermitEmptyPasswords no # Change to "no" to disable keyboard-interactive authentication. Depending on # the system's configuration, this may involve passwords, challenge-response, # one-time passwords or some combination of these and other methods. #KbdInteractiveAuthentication 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 KbdInteractiveAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via KbdInteractiveAuthentication may bypass # the setting of "PermitRootLogin prohibit-password". # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and KbdInteractiveAuthentication to 'no'. #UsePAM no #AllowAgentForwarding yes #AllowTcpForwarding yes #GatewayPorts no #X11Forwarding no #X11DisplayOffset 10 #X11UseLocalhost yes #PermitTTY yes #PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 #ClientAliveCountMax 3 #UseDNS no #PidFile /var/run/sshd.pid #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none #VersionAddendum 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 # PermitTTY no # ForceCommand cvs server openssh-10.0p1/PaxHeaders.10889/sshd_config.0100644 001750 001750 0000000003514775415623 0015522xustar0029 atime=1744182234.87189814 openssh-10.0p1/sshd_config.0010064400017500001750000002220501477541562300141070ustar00djmdjmSSHD_CONFIG(5) File Formats Manual SSHD_CONFIG(5) NAME sshd_config M-bM-^@M-^S OpenSSH daemon configuration file 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. Unless noted otherwise, for each keyword, the first obtained value will be used. 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 and SetEnv in ssh_config(5) for how to configure the client. The 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 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 any (the default), inet (use IPv4 only), or inet6 (use IPv6 only). AllowAgentForwarding Specifies whether ssh-agent(1) forwarding is permitted. The default is 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. AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. If specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. The allow/deny groups directives are processed in the following order: DenyGroups, AllowGroups. See PATTERNS in ssh_config(5) for more information on patterns. This keyword may appear multiple times in sshd_config with each instance appending to the list. AllowStreamLocalForwarding Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted. The available options are yes (the default) or all to allow StreamLocal forwarding, no to prevent all StreamLocal forwarding, local to allow local (from the perspective of ssh(1)) forwarding only or remote to allow remote forwarding only. Note that disabling StreamLocal forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. AllowTcpForwarding Specifies whether TCP forwarding is permitted. The available options are yes (the default) or all to allow TCP forwarding, no to prevent all TCP forwarding, local to allow local (from the perspective of ssh(1)) forwarding only or remote to allow remote forwarding only. Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. AllowUsers This keyword can be followed by a list of user name patterns, separated by spaces. If specified, login is allowed only for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny users directives are processed in the following order: DenyUsers, AllowUsers. See PATTERNS in ssh_config(5) for more information on patterns. This keyword may appear multiple times in sshd_config with each instance appending to the list. AuthenticationMethods Specifies the authentication methods that must be successfully completed for a user to be granted access. This option must be followed by one or more lists of comma-separated authentication method names, or by the single string 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. For example, "publickey,password publickey,keyboard-interactive" would require the user to complete public key authentication, followed by either password or keyboard interactive authentication. Only methods that are next in one or more lists are offered at each stage, so for this example it would not be possible to attempt password or keyboard-interactive authentication before public key. For keyboard interactive authentication it is also possible to restrict authentication to a specific device by appending a colon followed by the device identifier bsdauth or pam. depending on the server configuration. For example, "keyboard-interactive:bsdauth" would restrict keyboard interactive authentication to the bsdauth device. If the publickey method is listed more than once, sshd(8) verifies that keys that have been used successfully are not reused for subsequent authentications. For example, "publickey,publickey" requires successful authentication using two different public keys. Note that each authentication method listed should also be explicitly enabled in the configuration. The available authentication methods are: "gssapi-with-mic", "hostbased", "keyboard-interactive", "none" (used for access to password-less accounts when PermitEmptyPasswords is enabled), "password" and "publickey". AuthorizedKeysCommand Specifies a program to be used to look up the user's public keys. The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to AuthorizedKeysCommand accept the tokens described in the TOKENS section. If no arguments are specified then the username of the target user is used. The program should produce on standard output zero or more lines of authorized_keys output (see AUTHORIZED_KEYS in sshd(8)). AuthorizedKeysCommand is tried after the usual AuthorizedKeysFile files and will not be executed if a matching key is found there. 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 used for user authentication. The format is described in the AUTHORIZED_KEYS FILE FORMAT section of sshd(8). Arguments to AuthorizedKeysFile may include wildcards and accept the tokens described in the TOKENS section. 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. Alternately this option may be set to none to skip checking for user keys in files. The default is ".ssh/authorized_keys .ssh/authorized_keys2". AuthorizedPrincipalsCommand Specifies a program to be used to generate the list of allowed certificate principals as per AuthorizedPrincipalsFile. The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to AuthorizedPrincipalsCommand accept the tokens described in the TOKENS section. If no arguments are specified then the username of the target user is used. The program should produce on standard output zero or more lines of AuthorizedPrincipalsFile output. If either AuthorizedPrincipalsCommand or AuthorizedPrincipalsFile is specified, then certificates offered by the client for authentication must contain a principal that is listed. By default, no AuthorizedPrincipalsCommand is run. AuthorizedPrincipalsCommandUser Specifies the user under whose account the 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 AuthorizedPrincipalsCommand is specified but AuthorizedPrincipalsCommandUser is not, then sshd(8) will refuse to start. 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. Arguments to AuthorizedPrincipalsFile may include wildcards and accept the tokens described in the TOKENS section. After expansion, AuthorizedPrincipalsFile is taken to be an absolute path or one relative to the user's home directory. The default is none, 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 none then no banner is displayed. By default, no banner is displayed. CASignatureAlgorithms Specifies which algorithms are allowed for signing of certificates by certificate authorities (CAs). The default is: ssh-ed25519,ecdsa-sha2-nistp256, ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. Certificates signed using other algorithms will not be accepted for public key or host-based authentication. ChannelTimeout Specifies whether and how quickly sshd(8) should close inactive channels. Timeouts are specified as one or more M-bM-^@M-^\type=intervalM-bM-^@M-^] pairs separated by whitespace, where the M-bM-^@M-^\typeM-bM-^@M-^] must be the special keyword M-bM-^@M-^\globalM-bM-^@M-^] or a channel type name from the list below, optionally containing wildcard characters. The timeout value M-bM-^@M-^\intervalM-bM-^@M-^] is specified in seconds or may use any of the units documented in the TIME FORMATS section. For example, M-bM-^@M-^\session=5mM-bM-^@M-^] would cause interactive sessions to terminate after five minutes of inactivity. Specifying a zero value disables the inactivity timeout. The special timeout M-bM-^@M-^\globalM-bM-^@M-^] applies to all active channels, taken together. Traffic on any active channel will reset the timeout, but when the timeout expires then all open channels will be closed. Note that this global timeout is not matched by wildcards and must be specified explicitly. The available channel type names include: agent-connection Open connections to ssh-agent(1). direct-tcpip, direct-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established from a ssh(1) local forwarding, i.e. LocalForward or DynamicForward. forwarded-tcpip, forwarded-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established to a sshd(8) listening on behalf of a ssh(1) remote forwarding, i.e. RemoteForward. session The interactive main session, including shell session, command execution, scp(1), sftp(1), etc. tun-connection Open TunnelForward connections. x11-connection Open X11 forwarding sessions. Note that in all the above cases, terminating an inactive session does not guarantee to remove all resources associated with the session, e.g. shell processes or X11 clients relating to the session may continue to execute. Moreover, terminating an inactive channel or session does not necessarily close the SSH connection, nor does it prevent a client from requesting another channel of the same type. In particular, expiring an inactive forwarding session does not prevent another identical forwarding from being subsequently created. The default is not to expire channels of any type for inactivity. 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 group or others. After the chroot, sshd(8) changes the working directory to the user's home directory. Arguments to ChrootDirectory accept the tokens described in the TOKENS section. 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 SFTP 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 none, indicating not to chroot(2). Ciphers Specifies the ciphers allowed. Multiple ciphers must be comma- separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified ciphers will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified ciphers will be placed at the head of the default set. 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 chacha20-poly1305@openssh.com The default is: chacha20-poly1305@openssh.com, aes128-gcm@openssh.com,aes256-gcm@openssh.com, aes128-ctr,aes192-ctr,aes256-ctr The list of available ciphers may also be obtained using "ssh -Q cipher". ClientAliveCountMax Sets the number of client alive messages 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. 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 unresponsive. The default value is 3. If ClientAliveInterval is set to 15, and ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. Setting a zero ClientAliveCountMax disables connection termination. 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. Compression Specifies whether compression is enabled after the user has authenticated successfully. The argument must be yes, delayed (a legacy synonym for yes) or no. The default is yes. DenyGroups This keyword can be followed by a list of group name patterns, separated by spaces. Login is disallowed for users whose primary group or supplementary group list matches one of the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. The allow/deny groups directives are processed in the following order: DenyGroups, AllowGroups. See PATTERNS in ssh_config(5) for more information on patterns. This keyword may appear multiple times in sshd_config with each instance appending to the list. DenyUsers This keyword can be followed by a list of user name patterns, separated by spaces. Login is disallowed for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny users directives are processed in the following order: DenyUsers, AllowUsers. See PATTERNS in ssh_config(5) for more information on patterns. This keyword may appear multiple times in sshd_config with each instance appending to the list. DisableForwarding Disables all forwarding features, including X11, ssh-agent(1), TCP and StreamLocal. This option overrides all other forwarding- related options and may simplify restricted configurations. 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 SSH_USER_AUTH environment variable. The default is no. FingerprintHash Specifies the hash algorithm used when logging key fingerprints. Valid options are: md5 and sha256. The default is sha256. 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 internal-sftp will force the use of an in-process SFTP server that requires no support files when used with ChrootDirectory. The default is none. 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 no to force remote port forwardings to be available to the local host only, yes to force remote port forwardings to bind to the wildcard address, or clientspecified to allow the client to select the address to which the forwarding is bound. The default is no. GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is no. GSSAPICleanupCredentials Specifies whether to automatically destroy the user's credentials cache on logout. The default is yes. GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. If set to yes then the client must authenticate against the host service on the current hostname. If set to 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 yes. HostbasedAcceptedAlgorithms Specifies the signature algorithms that will be accepted for hostbased authentication as a list of comma-separated patterns. Alternately if the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified signature algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified signature algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified signature algorithms will be placed at the head of the default set. The default for this option is: ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 The list of available signature algorithms may also be obtained using "ssh -Q HostbasedAcceptedAlgorithms". This was formerly named HostbasedAcceptedKeyTypes. HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed (host-based authentication). The default is no. 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 yes 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 no. 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 defaults are /etc/ssh/ssh_host_ecdsa_key, /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key. Note that sshd(8) will refuse to use a file if it is group/world- accessible and that the HostKeyAlgorithms option restricts which of the keys are actually used by sshd(8). It is possible to have multiple host key files. It is also possible to specify public host key files instead. In this case operations on the private key will be delegated to an ssh-agent(1). HostKeyAgent Identifies the UNIX-domain socket used to communicate with an agent that has access to the private host keys. If the string "SSH_AUTH_SOCK" is specified, the location of the socket will be read from the SSH_AUTH_SOCK environment variable. HostKeyAlgorithms Specifies the host key signature algorithms that the server offers. The default for this option is: ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 The list of available signature algorithms may also be obtained using "ssh -Q HostKeyAlgorithms". IgnoreRhosts Specifies whether to ignore per-user .rhosts and .shosts files during HostbasedAuthentication. The system-wide /etc/hosts.equiv and /etc/shosts.equiv are still used regardless of this setting. Accepted values are yes (the default) to ignore all per-user files, shosts-only to allow the use of .shosts but to ignore .rhosts or no to allow both .shosts and rhosts. IgnoreUserKnownHosts Specifies whether sshd(8) should ignore the user's ~/.ssh/known_hosts during HostbasedAuthentication and use only the system-wide known hosts file /etc/ssh/ssh_known_hosts. The default is M-bM-^@M-^\noM-bM-^@M-^]. Include Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(7) wildcards that will be expanded and processed in lexical order. Files without absolute paths are assumed to be in /etc/ssh. An Include directive may appear inside a Match block to perform conditional inclusion. IPQoS Specifies the IPv4 type-of-service or DSCP class for the connection. Accepted values are af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, ef, le, lowdelay, throughput, reliability, a numeric value, or none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is af21 (Low-Latency Data) for interactive sessions and cs1 (Lower Effort) for non- interactive sessions. KbdInteractiveAuthentication Specifies whether to allow keyboard-interactive authentication. All authentication styles from login.conf(5) are supported. The default is yes. The argument to this keyword must be yes or no. ChallengeResponseAuthentication is a deprecated alias for this. 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 no. 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 no. 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 yes. KerberosTicketCleanup Specifies whether to automatically destroy the user's ticket cache file on logout. The default is yes. KexAlgorithms Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. The ordering of this list is not important, as the client specifies the preference order. Multiple algorithms must be comma-separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will be placed at the head of the default set. The supported algorithms are: curve25519-sha256 curve25519-sha256@libssh.org diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 mlkem768x25519-sha256 sntrup761x25519-sha512 sntrup761x25519-sha512@openssh.com The default is: mlkem768x25519-sha256, sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521 The list of supported key exchange algorithms may also be obtained using "ssh -Q KexAlgorithms". ListenAddress Specifies the local addresses sshd(8) should listen on. The following forms may be used: ListenAddress hostname|address [rdomain domain] ListenAddress hostname:port [rdomain domain] ListenAddress IPv4_address:port [rdomain domain] ListenAddress [hostname|address]:port [rdomain domain] The optional rdomain qualifier requests sshd(8) listen in an explicit routing domain. If port is not specified, sshd will listen on the address and all Port options specified. The default is to listen on all local addresses on the current default routing domain. Multiple ListenAddress options are permitted. For more information on routing domains, see rdomain(4). 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. LogVerbose Specify one or more overrides to LogLevel. An override consists of one or more pattern lists that matches the source file, function and line number to force detailed logging for. For example, an override pattern of: kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* would enable detailed logging for line 1000 of kex.c, everything in the kex_exchange_identification() function, and all code in the packet.c file. This option is intended for debugging and no overrides are enabled by default. MACs Specifies the available MAC (message authentication code) algorithms. The MAC algorithm is used for data integrity protection. Multiple algorithms must be comma-separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will be placed at the head of the default set. The algorithms that contain "-etm" 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-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-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, hmac-sha1-etm@openssh.com, umac-64@openssh.com,umac-128@openssh.com, hmac-sha2-256,hmac-sha2-512,hmac-sha1 The list of available MAC algorithms may also be obtained using "ssh -Q mac". 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 one of the single token criteria: All, which matches all criteria, or Invalid-User, which matches when the requested user- name does not match any known account. The available criteria are User, Group, Host, LocalAddress, LocalPort, Version, RDomain, and Address (with RDomain representing the rdomain(4) on which the connection was received). 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, such as 192.0.2.0/24 or 2001:db8::/32. Note that the mask length provided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. The Version keyword matches against the version string of sshd(8), for example M-bM-^@M-^\OpenSSH_10.0M-bM-^@M-^]. 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, AuthorizedPrincipalsCommand, AuthorizedPrincipalsCommandUser, AuthorizedPrincipalsFile, Banner, CASignatureAlgorithms, ChannelTimeout, ChrootDirectory, ClientAliveCountMax, ClientAliveInterval, DenyGroups, DenyUsers, DisableForwarding, ExposeAuthInfo, ForceCommand, GatewayPorts, GSSAPIAuthentication, HostbasedAcceptedAlgorithms, HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, IgnoreRhosts, Include, IPQoS, KbdInteractiveAuthentication, KerberosAuthentication, LogLevel, MaxAuthTries, MaxSessions, PAMServiceName, PasswordAuthentication, PermitEmptyPasswords, PermitListen, PermitOpen, PermitRootLogin, PermitTTY, PermitTunnel, PermitUserRC, PubkeyAcceptedAlgorithms, PubkeyAuthentication, PubkeyAuthOptions, RefuseConnection, RekeyLimit, RevokedKeys, RDomain, SetEnv, StreamLocalBindMask, StreamLocalBindUnlink, TrustedUserCAKeys, UnusedConnectionTimeout, 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 shell, login or subsystem (e.g. sftp) sessions permitted per network connection. Multiple sessions may be established by clients that support connection multiplexing. Setting 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. 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 start:rate:full (e.g. "10:30:60"). sshd(8) will refuse connection attempts with a probability of rate/100 (30%) if there are currently start (10) unauthenticated connections. The probability increases linearly and all connection attempts are refused if the number of unauthenticated connections reaches full (60). ModuliFile Specifies the moduli(5) file that contains the Diffie-Hellman groups used for the M-bM-^@M-^\diffie-hellman-group-exchange-sha1M-bM-^@M-^] and M-bM-^@M-^\diffie-hellman-group-exchange-sha256M-bM-^@M-^] key exchange methods. The default is /etc/moduli. PAMServiceName Specifies the service name used for Pluggable Authentication Modules (PAM) authentication, authorisation and session controls when UsePAM is enabled. The default is sshd. PasswordAuthentication Specifies whether password authentication is allowed. The default is yes. PermitEmptyPasswords When password authentication is allowed, it specifies whether the server allows login to accounts with empty password strings. The default is no. PermitListen Specifies the addresses/ports on which a remote TCP port forwarding may listen. The listen specification must be one of the following forms: PermitListen port PermitListen host:port Multiple permissions may be specified by separating them with whitespace. An argument of any can be used to remove all restrictions and permit any listen requests. An argument of none can be used to prohibit all listen requests. The host name may contain wildcards as described in the PATTERNS section in ssh_config(5). The wildcard M-bM-^@M-^X*M-bM-^@M-^Y 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 GatewayPorts option may further restrict which addresses may be listened on. Note also that ssh(1) will request a listen host of M-bM-^@M-^\localhostM-bM-^@M-^] if no listen host was specifically requested, and this name is treated differently to explicit localhost addresses of M-bM-^@M-^\127.0.0.1M-bM-^@M-^] and M-bM-^@M-^\::1M-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 any can be used to remove all restrictions and permit any forwarding requests. An argument of none can be used to prohibit all forwarding requests. The wildcard M-bM-^@M-^X*M-bM-^@M-^Y 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. PermitRootLogin Specifies whether root can log in using ssh(1). The argument must be yes, prohibit-password, forced-commands-only, or no. The default is prohibit-password. If this option is set to prohibit-password (or its deprecated alias, without-password), password and keyboard-interactive authentication are disabled for root. If this option is set to forced-commands-only, 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 no, root is not allowed to log in. PermitTTY Specifies whether pty(4) allocation is permitted. The default is yes. PermitTunnel Specifies whether tun(4) device forwarding is allowed. The argument must be yes, point-to-point (layer 3), ethernet (layer 2), or no. Specifying yes permits both point-to-point and ethernet. The default is no. Independent of this setting, the permissions of the selected tun(4) device must allow access to the user. PermitUserEnvironment Specifies whether ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd(8). Valid options are yes, no or a pattern-list specifying which environment variable names to accept (for example "LANG,LC_*"). The default is no. 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 yes. PerSourceMaxStartups Specifies the number of unauthenticated connections allowed from a given source address, or M-bM-^@M-^\noneM-bM-^@M-^] if there is no limit. This limit is applied in addition to MaxStartups, whichever is lower. The default is none. PerSourceNetBlockSize Specifies the number of bits of source address that are grouped together for the purposes of applying PerSourceMaxStartups limits. Values for IPv4 and optionally IPv6 may be specified, separated by a colon. The default is 32:128, which means each address is considered individually. PerSourcePenalties Controls penalties for various conditions that may represent attacks on sshd(8). If a penalty is enforced against a client then its source address and any others in the same network, as defined by PerSourceNetBlockSize, will be refused connection for a period. A penalty doesn't affect concurrent connections in progress, but multiple penalties from the same source from concurrent connections will accumulate up to a maximum. Conversely, penalties are not applied until a minimum threshold time has been accumulated. Penalties are enabled by default with the default settings listed below but may disabled using the no keyword. The defaults may be overridden by specifying one or more of the keywords below, separated by whitespace. All keywords accept arguments, e.g. "crash:2m". crash:duration Specifies how long to refuse clients that cause a crash of sshd(8) (default: 90s). authfail:duration Specifies how long to refuse clients that disconnect after making one or more unsuccessful authentication attempts (default: 5s). refuseconnection:duration Specifies how long to refuse clients that were administratively prohibited connection via the RefuseConnection option (default: 10s). noauth:duration Specifies how long to refuse clients that disconnect without attempting authentication (default: 1s). This timeout should be used cautiously otherwise it may penalise legitimate scanning tools such as ssh-keyscan(1). grace-exceeded:duration Specifies how long to refuse clients that fail to authenticate after LoginGraceTime (default: 10s). max:duration Specifies the maximum time a particular source address range will be refused access for (default: 10m). Repeated penalties will accumulate up to this maximum. min:duration Specifies the minimum penalty that must accrue before enforcement begins (default: 15s). max-sources4:number, max-sources6:number Specifies the maximum number of client IPv4 and IPv6 address ranges to track for penalties (default: 65536 for both). overflow:mode Controls how the server behaves when max-sources4 or max-sources6 is exceeded. There are two operating modes: deny-all, which denies all incoming connections other than those exempted via PerSourcePenaltyExemptList until a penalty expires, and permissive, which allows new connections by removing existing penalties early (default: permissive). Note that client penalties below the min threshold count against the total number of tracked penalties. IPv4 and IPv6 addresses are tracked separately, so an overflow in one will not affect the other. overflow6:mode Allows specifying a different overflow mode for IPv6 addresses. The default it to use the same overflow mode as was specified for IPv4. PerSourcePenaltyExemptList Specifies a comma-separated list of addresses to exempt from penalties. This list may contain wildcards and CIDR address/masklen ranges. Note that the mask length provided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. The default is not to exempt any addresses. PidFile Specifies the file that contains the process ID of the SSH daemon, or none to not write one. 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 yes. 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 yes. PubkeyAcceptedAlgorithms Specifies the signature algorithms that will be accepted for public key authentication as a list of comma-separated patterns. Alternately if the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y 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 M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will be placed at the head of the default set. The default for this option is: ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 The list of available signature algorithms may also be obtained using "ssh -Q PubkeyAcceptedAlgorithms". PubkeyAuthOptions Sets one or more public key authentication options. The supported keywords are: none (the default; indicating no additional options are enabled), touch-required and verify-required. The touch-required option causes public key authentication using a FIDO authenticator algorithm (i.e. ecdsa-sk or 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, sshd(8) requires user presence unless overridden with an authorized_keys option. The touch-required flag disables this override. The verify-required option requires a FIDO key signature attest that the user was verified, e.g. via a PIN. Neither the touch-required or verify-required options have any effect for other, non-FIDO, public key types. PubkeyAuthentication Specifies whether public key authentication is allowed. The default is yes. RefuseConnection Indicates that sshd(8) should unconditionally terminate the connection. Additionally, a refuseconnection penalty may be recorded against the source of the connection if PerSourcePenalties are enabled. This option is only really useful in a Match block. RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of 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 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. RequiredRSASize Specifies the minimum RSA key size (in bits) that sshd(8) will accept. User and host-based authentication keys smaller than this limit will be refused. The default is 1024 bits. Note that this limit may only be raised from the default. RevokedKeys Specifies revoked public keys file, or none to not use one. Keys listed in this file will be refused for public key authentication. Note that if this file is not readable, then public key authentication will be refused for all users. Keys may be specified as a text file, listing one public key per line, or as an OpenSSH Key Revocation List (KRL) as generated by ssh-keygen(1). For more information on KRLs, see the KEY REVOCATION LISTS section in ssh-keygen(1). RDomain Specifies an explicit routing domain that is applied after authentication has completed. The user session, as well as any forwarded or listening IP sockets, will be bound to this rdomain(4). If the routing domain is set to %D, then the domain in which the incoming connection was received will be applied. 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. SetEnv Specifies one or more environment variables to set in child sessions started by sshd(8) as M-bM-^@M-^\NAME=VALUEM-bM-^@M-^]. The environment value may be quoted (e.g. if it contains whitespace characters). Environment variables set by SetEnv override the default environment and any variables specified by the user via AcceptEnv or PermitUserEnvironment. SshdAuthPath Overrides the default path to the sshd-auth binary that is invoked to complete user authentication. The default is /usr/libexec/sshd-auth. This option is intended for use by tests. SshdSessionPath Overrides the default path to the sshd-session binary that is invoked to handle each connection. The default is /usr/libexec/sshd-session. This option is intended for use by tests. 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 yes or no. The default is no. 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 yes. 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 implements the SFTP file transfer subsystem. Alternately the name internal-sftp implements an in-process SFTP server. This may simplify configurations using ChrootDirectory to force a different filesystem root on clients. It accepts the same command line arguments as sftp-server and even though it is in-process, settings such as LogLevel or SyslogFacility do not apply to it and must be set explicitly via command line arguments. By default no subsystems are defined. 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 "ghost" users and consuming server resources. The default is 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. To disable TCP keepalive messages, the value should be set to no. TrustedUserCAKeys Specifies a file containing public keys of certificate authorities that are trusted to sign user certificates for authentication, or none to not use one. 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). UnusedConnectionTimeout Specifies whether and how quickly sshd(8) should close client connections with no open channels. Open channels include active shell, command execution or subsystem sessions, connected network, socket, agent or X11 forwardings. Forwarding listeners, such as those from the ssh(1) -R flag, are not considered as open channels and do not prevent the timeout. The timeout value is specified in seconds or may use any of the units documented in the TIME FORMATS section. Note that this timeout starts when the client connection completes user authentication but before the client has an opportunity to open any channels. Caution should be used when using short timeout values, as they may not provide sufficient time for the client to request and open its channels before terminating the connection. The default none is to never expire connections for having no open channels. This option may be useful in conjunction with ChannelTimeout. UseDNS Specifies whether sshd(8) should look up the remote host name, and to check that the resolved host name for the remote IP address maps back to the very same IP address. If this option is set to no (the default) then only addresses and not host names may be used in ~/.ssh/authorized_keys from and sshd_config Match Host directives. UsePAM Enables the Pluggable Authentication Module interface. If set to yes this will enable PAM authentication using KbdInteractiveAuthentication and PasswordAuthentication in addition to PAM account and session module processing for all authentication types. Because PAM keyboard-interactive authentication usually serves an equivalent role to password authentication, you should disable either PasswordAuthentication or KbdInteractiveAuthentication. If UsePAM is enabled, you will not be able to run sshd(8) as a non-root user. The default is no. VersionAddendum Optionally specifies additional text to append to the SSH protocol banner sent by the server upon connection. The default is none. 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 yes or no. The default is no. 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), 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 no setting. Note that disabling X11 forwarding does not prevent users from forwarding X11 traffic, as users can always install their own forwarders. 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 localhost. 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 no to specify that the forwarding server should be bound to the wildcard address. The argument must be yes or no. The default is yes. XAuthLocation Specifies the full pathname of the xauth(1) program, or none to not use one. 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) TOKENS Arguments to some keywords can make use of tokens, which are expanded at runtime: %% A literal M-bM-^@M-^X%M-bM-^@M-^Y. %C Identifies the connection endpoints, containing four space- separated values: client address, client port number, server address, and server port number. %D The routing domain in which the incoming connection was received. %F The fingerprint of the CA key. %f The fingerprint of the key or certificate. %h The home directory of the user. %i The key ID in the certificate. %K The base64-encoded CA key. %k The base64-encoded key or certificate for authentication. %s The serial number of the certificate. %T The type of the CA key. %t The key or certificate type. %U The numeric user ID of the target user. %u The username. AuthorizedKeysCommand accepts the tokens %%, %C, %D, %f, %h, %k, %t, %U, and %u. AuthorizedKeysFile accepts the tokens %%, %h, %U, and %u. AuthorizedPrincipalsCommand accepts the tokens %%, %C, %D, %F, %f, %h, %i, %K, %k, %s, %T, %t, %U, and %u. AuthorizedPrincipalsFile accepts the tokens %%, %h, %U, and %u. ChrootDirectory accepts the tokens %%, %h, %U, and %u. RoutingDomain accepts the token %D. 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 sftp-server(8), 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 7.6 February 15, 2025 OpenBSD 7.6 openssh-10.0p1/PaxHeaders.10889/sshd_config.5100644 001750 001750 0000000003614775415623 0015530xustar0030 atime=1744182234.873851745 openssh-10.0p1/sshd_config.5010064400017500001750000001767411477541562300141330ustar00djmdjm.\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $OpenBSD: sshd_config.5,v 1.381 2025/02/15 01:52:07 djm Exp $ .Dd $Mdocdate: February 15 2025 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME .Nm sshd_config .Nd OpenSSH daemon configuration file .Sh DESCRIPTION .Xr sshd 8 reads configuration data from .Pa /etc/ssh/sshd_config (or the file specified with .Fl f on the command line). The file contains keyword-argument pairs, one per line. Unless noted otherwise, for each keyword, the first obtained value will be used. Lines starting with .Ql # and empty lines are interpreted as comments. Arguments may optionally be enclosed in double quotes .Pq \&" in order to represent arguments containing spaces. .Pp The possible keywords and their meanings are as follows (note that keywords are case-insensitive and arguments are case-sensitive): .Bl -tag -width Ds .It Cm AcceptEnv Specifies what environment variables sent by the client will be copied into the session's .Xr environ 7 . See .Cm SendEnv and .Cm SetEnv in .Xr ssh_config 5 for how to configure the client. The .Ev TERM environment variable is always accepted whenever the client requests a pseudo-terminal as it is required by the protocol. Variables are specified by name, which may contain the wildcard characters .Ql * and .Ql \&? . Multiple environment variables may be separated by whitespace or spread across multiple .Cm AcceptEnv directives. Be warned that some environment variables could be used to bypass restricted user environments. For this reason, care should be taken in the use of this directive. The default is not to accept any environment variables. .It Cm AddressFamily Specifies which address family should be used by .Xr sshd 8 . Valid arguments are .Cm any (the default), .Cm inet (use IPv4 only), or .Cm inet6 (use IPv6 only). .It Cm AllowAgentForwarding Specifies whether .Xr ssh-agent 1 forwarding is permitted. The default is .Cm yes . Note that disabling agent forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. If specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. The allow/deny groups directives are processed in the following order: .Cm DenyGroups , .Cm AllowGroups . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm AllowStreamLocalForwarding Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted. The available options are .Cm yes (the default) or .Cm all to allow StreamLocal forwarding, .Cm no to prevent all StreamLocal forwarding, .Cm local to allow local (from the perspective of .Xr ssh 1 ) forwarding only or .Cm remote to allow remote forwarding only. Note that disabling StreamLocal forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. .It Cm AllowTcpForwarding Specifies whether TCP forwarding is permitted. The available options are .Cm yes (the default) or .Cm all to allow TCP forwarding, .Cm no to prevent all TCP forwarding, .Cm local to allow local (from the perspective of .Xr ssh 1 ) forwarding only or .Cm remote to allow remote forwarding only. Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. .It Cm AllowUsers This keyword can be followed by a list of user name patterns, separated by spaces. If specified, login is allowed only for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny users directives are processed in the following order: .Cm DenyUsers , .Cm AllowUsers . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm AuthenticationMethods Specifies the authentication methods that must be successfully completed for a user to be granted access. This option must be followed by one or more lists of comma-separated authentication method names, or by the single string .Cm any to indicate the default behaviour of accepting any single authentication method. If the default is overridden, then successful authentication requires completion of every method in at least one of these lists. .Pp For example, .Qq publickey,password publickey,keyboard-interactive would require the user to complete public key authentication, followed by either password or keyboard interactive authentication. Only methods that are next in one or more lists are offered at each stage, so for this example it would not be possible to attempt password or keyboard-interactive authentication before public key. .Pp For keyboard interactive authentication it is also possible to restrict authentication to a specific device by appending a colon followed by the device identifier .Cm bsdauth or .Cm pam . depending on the server configuration. For example, .Qq keyboard-interactive:bsdauth would restrict keyboard interactive authentication to the .Cm bsdauth device. .Pp If the publickey method is listed more than once, .Xr sshd 8 verifies that keys that have been used successfully are not reused for subsequent authentications. For example, .Qq publickey,publickey requires successful authentication using two different public keys. .Pp Note that each authentication method listed should also be explicitly enabled in the configuration. .Pp The available authentication methods are: .Qq gssapi-with-mic , .Qq hostbased , .Qq keyboard-interactive , .Qq none (used for access to password-less accounts when .Cm PermitEmptyPasswords is enabled), .Qq password and .Qq publickey . .It Cm AuthorizedKeysCommand Specifies a program to be used to look up the user's public keys. The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to .Cm AuthorizedKeysCommand accept the tokens described in the .Sx TOKENS section. If no arguments are specified then the username of the target user is used. .Pp The program should produce on standard output zero or more lines of authorized_keys output (see .Cm AUTHORIZED_KEYS in .Xr sshd 8 ) . .Cm AuthorizedKeysCommand is tried after the usual .Cm AuthorizedKeysFile files and will not be executed if a matching key is found there. By default, no .Cm AuthorizedKeysCommand is run. .It Cm AuthorizedKeysCommandUser Specifies the user under whose account the .Cm AuthorizedKeysCommand is run. It is recommended to use a dedicated user that has no other role on the host than running authorized keys commands. If .Cm AuthorizedKeysCommand is specified but .Cm AuthorizedKeysCommandUser is not, then .Xr sshd 8 will refuse to start. .It Cm AuthorizedKeysFile Specifies the file that contains the public keys used for user authentication. The format is described in the AUTHORIZED_KEYS FILE FORMAT section of .Xr sshd 8 . Arguments to .Cm AuthorizedKeysFile may include wildcards and accept the tokens described in the .Sx TOKENS section. After expansion, .Cm AuthorizedKeysFile is taken to be an absolute path or one relative to the user's home directory. Multiple files may be listed, separated by whitespace. Alternately this option may be set to .Cm none to skip checking for user keys in files. The default is .Qq .ssh/authorized_keys .ssh/authorized_keys2 . .It Cm AuthorizedPrincipalsCommand Specifies a program to be used to generate the list of allowed certificate principals as per .Cm AuthorizedPrincipalsFile . The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to .Cm AuthorizedPrincipalsCommand accept the tokens described in the .Sx TOKENS section. If no arguments are specified then the username of the target user is used. .Pp The program should produce on standard output zero or more lines of .Cm AuthorizedPrincipalsFile output. If either .Cm AuthorizedPrincipalsCommand or .Cm AuthorizedPrincipalsFile is specified, then certificates offered by the client for authentication must contain a principal that is listed. By default, no .Cm AuthorizedPrincipalsCommand is run. .It Cm AuthorizedPrincipalsCommandUser Specifies the user under whose account the .Cm AuthorizedPrincipalsCommand is run. It is recommended to use a dedicated user that has no other role on the host than running authorized principals commands. If .Cm AuthorizedPrincipalsCommand is specified but .Cm AuthorizedPrincipalsCommandUser is not, then .Xr sshd 8 will refuse to start. .It Cm AuthorizedPrincipalsFile Specifies a file that lists principal names that are accepted for certificate authentication. When using certificates signed by a key listed in .Cm TrustedUserCAKeys , this file lists names, one of which must appear in the certificate for it to be accepted for authentication. Names are listed one per line preceded by key options (as described in .Cm AUTHORIZED_KEYS FILE FORMAT in .Xr sshd 8 ) . Empty lines and comments starting with .Ql # are ignored. .Pp Arguments to .Cm AuthorizedPrincipalsFile may include wildcards and accept the tokens described in the .Sx TOKENS section. After expansion, .Cm AuthorizedPrincipalsFile is taken to be an absolute path or one relative to the user's home directory. The default is .Cm none , i.e. not to use a principals file \(en in this case, the username of the user must appear in a certificate's principals list for it to be accepted. .Pp Note that .Cm AuthorizedPrincipalsFile is only used when authentication proceeds using a CA listed in .Cm TrustedUserCAKeys and is not consulted for certification authorities trusted via .Pa ~/.ssh/authorized_keys , though the .Cm principals= key option offers a similar facility (see .Xr sshd 8 for details). .It Cm Banner The contents of the specified file are sent to the remote user before authentication is allowed. If the argument is .Cm none then no banner is displayed. By default, no banner is displayed. .It Cm CASignatureAlgorithms Specifies which algorithms are allowed for signing of certificates by certificate authorities (CAs). The default is: .Bd -literal -offset indent ssh-ed25519,ecdsa-sha2-nistp256, ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. .Pp Certificates signed using other algorithms will not be accepted for public key or host-based authentication. .It Cm ChannelTimeout Specifies whether and how quickly .Xr sshd 8 should close inactive channels. Timeouts are specified as one or more .Dq type=interval pairs separated by whitespace, where the .Dq type must be the special keyword .Dq global or a channel type name from the list below, optionally containing wildcard characters. .Pp The timeout value .Dq interval is specified in seconds or may use any of the units documented in the .Sx TIME FORMATS section. For example, .Dq session=5m would cause interactive sessions to terminate after five minutes of inactivity. Specifying a zero value disables the inactivity timeout. .Pp The special timeout .Dq global applies to all active channels, taken together. Traffic on any active channel will reset the timeout, but when the timeout expires then all open channels will be closed. Note that this global timeout is not matched by wildcards and must be specified explicitly. .Pp The available channel type names include: .Bl -tag -width Ds .It Cm agent-connection Open connections to .Xr ssh-agent 1 . .It Cm direct-tcpip , Cm direct-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established from a .Xr ssh 1 local forwarding, i.e.\& .Cm LocalForward or .Cm DynamicForward . .It Cm forwarded-tcpip , Cm forwarded-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established to a .Xr sshd 8 listening on behalf of a .Xr ssh 1 remote forwarding, i.e.\& .Cm RemoteForward . .It Cm session The interactive main session, including shell session, command execution, .Xr scp 1 , .Xr sftp 1 , etc. .It Cm tun-connection Open .Cm TunnelForward connections. .It Cm x11-connection Open X11 forwarding sessions. .El .Pp Note that in all the above cases, terminating an inactive session does not guarantee to remove all resources associated with the session, e.g. shell processes or X11 clients relating to the session may continue to execute. .Pp Moreover, terminating an inactive channel or session does not necessarily close the SSH connection, nor does it prevent a client from requesting another channel of the same type. In particular, expiring an inactive forwarding session does not prevent another identical forwarding from being subsequently created. .Pp The default is not to expire channels of any type for inactivity. .It Cm ChrootDirectory Specifies the pathname of a directory to .Xr chroot 2 to after authentication. At session startup .Xr sshd 8 checks that all components of the pathname are root-owned directories which are not writable by group or others. After the chroot, .Xr sshd 8 changes the working directory to the user's home directory. Arguments to .Cm ChrootDirectory accept the tokens described in the .Sx TOKENS section. .Pp The .Cm ChrootDirectory must contain the necessary files and directories to support the user's session. For an interactive session this requires at least a shell, typically .Xr sh 1 , and basic .Pa /dev nodes such as .Xr null 4 , .Xr zero 4 , .Xr stdin 4 , .Xr stdout 4 , .Xr stderr 4 , and .Xr tty 4 devices. For file transfer sessions using SFTP no additional configuration of the environment is necessary if the in-process sftp-server is used, though sessions which use logging may require .Pa /dev/log inside the chroot directory on some operating systems (see .Xr sftp-server 8 for details). .Pp For safety, it is very important that the directory hierarchy be prevented from modification by other processes on the system (especially those outside the jail). Misconfiguration can lead to unsafe environments which .Xr sshd 8 cannot detect. .Pp The default is .Cm none , indicating not to .Xr chroot 2 . .It Cm Ciphers Specifies the ciphers allowed. Multiple ciphers must be comma-separated. If the specified list begins with a .Sq + character, then the specified ciphers will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified ciphers (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified ciphers will be placed at the head of the default set. .Pp The supported ciphers are: .Pp .Bl -item -compact -offset indent .It 3des-cbc .It aes128-cbc .It aes192-cbc .It aes256-cbc .It aes128-ctr .It aes192-ctr .It aes256-ctr .It aes128-gcm@openssh.com .It aes256-gcm@openssh.com .It chacha20-poly1305@openssh.com .El .Pp The default is: .Bd -literal -offset indent chacha20-poly1305@openssh.com, aes128-gcm@openssh.com,aes256-gcm@openssh.com, aes128-ctr,aes192-ctr,aes256-ctr .Ed .Pp The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClientAliveCountMax Sets the number of client alive messages which may be sent without .Xr sshd 8 receiving any messages back from the client. If this threshold is reached while client alive messages are being sent, sshd will disconnect the client, terminating the session. It is important to note that the use of client alive messages is very different from .Cm TCPKeepAlive . The client alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by .Cm TCPKeepAlive is spoofable. The client alive mechanism is valuable when the client or server depend on knowing when a connection has become unresponsive. .Pp The default value is 3. If .Cm ClientAliveInterval is set to 15, and .Cm ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. Setting a zero .Cm ClientAliveCountMax disables connection termination. .It Cm ClientAliveInterval Sets a timeout interval in seconds after which if no data has been received from the client, .Xr sshd 8 will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will not be sent to the client. .It Cm Compression Specifies whether compression is enabled after the user has authenticated successfully. The argument must be .Cm yes , .Cm delayed (a legacy synonym for .Cm yes ) or .Cm no . The default is .Cm yes . .It Cm DenyGroups This keyword can be followed by a list of group name patterns, separated by spaces. Login is disallowed for users whose primary group or supplementary group list matches one of the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. The allow/deny groups directives are processed in the following order: .Cm DenyGroups , .Cm AllowGroups . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm DenyUsers This keyword can be followed by a list of user name patterns, separated by spaces. Login is disallowed for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny users directives are processed in the following order: .Cm DenyUsers , .Cm AllowUsers . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm DisableForwarding Disables all forwarding features, including X11, .Xr ssh-agent 1 , TCP and StreamLocal. This option overrides all other forwarding-related options and may simplify restricted configurations. .It Cm ExposeAuthInfo Writes a temporary file containing a list of authentication methods and public credentials (e.g. keys) used to authenticate the user. The location of the file is exposed to the user session through the .Ev SSH_USER_AUTH environment variable. The default is .Cm no . .It Cm FingerprintHash Specifies the hash algorithm used when logging key fingerprints. Valid options are: .Cm md5 and .Cm sha256 . The default is .Cm sha256 . .It Cm ForceCommand Forces the execution of the command specified by .Cm ForceCommand , ignoring any command supplied by the client and .Pa ~/.ssh/rc if present. The command is invoked by using the user's login shell with the -c option. This applies to shell, command, or subsystem execution. It is most useful inside a .Cm Match block. The command originally supplied by the client is available in the .Ev SSH_ORIGINAL_COMMAND environment variable. Specifying a command of .Cm internal-sftp will force the use of an in-process SFTP server that requires no support files when used with .Cm ChrootDirectory . The default is .Cm none . .It Cm GatewayPorts Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, .Xr sshd 8 binds remote port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. .Cm GatewayPorts can be used to specify that sshd should allow remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be .Cm no to force remote port forwardings to be available to the local host only, .Cm yes to force remote port forwardings to bind to the wildcard address, or .Cm clientspecified to allow the client to select the address to which the forwarding is bound. The default is .Cm no . .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . .It Cm GSSAPICleanupCredentials Specifies whether to automatically destroy the user's credentials cache on logout. The default is .Cm yes . .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. If set to .Cm yes then the client must authenticate against the host service on the current hostname. If set to .Cm no then the client may authenticate against any service key stored in the machine's default store. This facility is provided to assist with operation on multi homed machines. The default is .Cm yes . .It Cm HostbasedAcceptedAlgorithms Specifies the signature algorithms that will be accepted for hostbased authentication as a list of comma-separated patterns. Alternately if the specified list begins with a .Sq + character, then the specified signature algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified signature algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified signature algorithms will be placed at the head of the default set. The default for this option is: .Bd -literal -offset 3n ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostbasedAcceptedAlgorithms . This was formerly named HostbasedAcceptedKeyTypes. .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed (host-based authentication). The default is .Cm no . .It Cm HostbasedUsesNameFromPacketOnly Specifies whether or not the server will attempt to perform a reverse name lookup when matching the name in the .Pa ~/.shosts , .Pa ~/.rhosts , and .Pa /etc/hosts.equiv files during .Cm HostbasedAuthentication . A setting of .Cm yes means that .Xr sshd 8 uses the name supplied by the client rather than attempting to resolve the name from the TCP connection itself. The default is .Cm no . .It Cm HostCertificate Specifies a file containing a public host certificate. The certificate's public key must match a private host key already specified by .Cm HostKey . The default behaviour of .Xr sshd 8 is not to load any certificates. .It Cm HostKey Specifies a file containing a private host key used by SSH. The defaults are .Pa /etc/ssh/ssh_host_ecdsa_key , .Pa /etc/ssh/ssh_host_ed25519_key and .Pa /etc/ssh/ssh_host_rsa_key . .Pp Note that .Xr sshd 8 will refuse to use a file if it is group/world-accessible and that the .Cm HostKeyAlgorithms option restricts which of the keys are actually used by .Xr sshd 8 . .Pp It is possible to have multiple host key files. It is also possible to specify public host key files instead. In this case operations on the private key will be delegated to an .Xr ssh-agent 1 . .It Cm HostKeyAgent Identifies the UNIX-domain socket used to communicate with an agent that has access to the private host keys. If the string .Qq SSH_AUTH_SOCK is specified, the location of the socket will be read from the .Ev SSH_AUTH_SOCK environment variable. .It Cm HostKeyAlgorithms Specifies the host key signature algorithms that the server offers. The default for this option is: .Bd -literal -offset 3n ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts Specifies whether to ignore per-user .Pa .rhosts and .Pa .shosts files during .Cm HostbasedAuthentication . The system-wide .Pa /etc/hosts.equiv and .Pa /etc/shosts.equiv are still used regardless of this setting. .Pp Accepted values are .Cm yes (the default) to ignore all per-user files, .Cm shosts-only to allow the use of .Pa .shosts but to ignore .Pa .rhosts or .Cm no to allow both .Pa .shosts and .Pa rhosts . .It Cm IgnoreUserKnownHosts Specifies whether .Xr sshd 8 should ignore the user's .Pa ~/.ssh/known_hosts during .Cm HostbasedAuthentication and use only the system-wide known hosts file .Pa /etc/ssh/ssh_known_hosts . The default is .Dq no . .It Cm Include Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain .Xr glob 7 wildcards that will be expanded and processed in lexical order. Files without absolute paths are assumed to be in .Pa /etc/ssh . An .Cm Include directive may appear inside a .Cm Match block to perform conditional inclusion. .It Cm IPQoS Specifies the IPv4 type-of-service or DSCP class for the connection. Accepted values are .Cm af11 , .Cm af12 , .Cm af13 , .Cm af21 , .Cm af22 , .Cm af23 , .Cm af31 , .Cm af32 , .Cm af33 , .Cm af41 , .Cm af42 , .Cm af43 , .Cm cs0 , .Cm cs1 , .Cm cs2 , .Cm cs3 , .Cm cs4 , .Cm cs5 , .Cm cs6 , .Cm cs7 , .Cm ef , .Cm le , .Cm lowdelay , .Cm throughput , .Cm reliability , a numeric value, or .Cm none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is .Cm af21 (Low-Latency Data) for interactive sessions and .Cm cs1 (Lower Effort) for non-interactive sessions. .It Cm KbdInteractiveAuthentication Specifies whether to allow keyboard-interactive authentication. All authentication styles from .Xr login.conf 5 are supported. The default is .Cm yes . The argument to this keyword must be .Cm yes or .Cm no . .Cm ChallengeResponseAuthentication is a deprecated alias for this. .It Cm KerberosAuthentication Specifies whether the password provided by the user for .Cm PasswordAuthentication will be validated through the Kerberos KDC. To use this option, the server needs a Kerberos servtab which allows the verification of the KDC's identity. The default is .Cm no . .It Cm KerberosGetAFSToken If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire an AFS token before accessing the user's home directory. The default is .Cm no . .It Cm KerberosOrLocalPasswd If password authentication through Kerberos fails then the password will be validated via any additional local mechanism such as .Pa /etc/passwd . The default is .Cm yes . .It Cm KerberosTicketCleanup Specifies whether to automatically destroy the user's ticket cache file on logout. The default is .Cm yes . .It Cm KexAlgorithms Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. The ordering of this list is not important, as the client specifies the preference order. Multiple algorithms must be comma-separated. .Pp If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. 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 supported algorithms are: .Pp .Bl -item -compact -offset indent .It curve25519-sha256 .It curve25519-sha256@libssh.org .It diffie-hellman-group1-sha1 .It diffie-hellman-group14-sha1 .It diffie-hellman-group14-sha256 .It diffie-hellman-group16-sha512 .It diffie-hellman-group18-sha512 .It diffie-hellman-group-exchange-sha1 .It diffie-hellman-group-exchange-sha256 .It ecdh-sha2-nistp256 .It ecdh-sha2-nistp384 .It ecdh-sha2-nistp521 .It mlkem768x25519-sha256 .It sntrup761x25519-sha512 .It sntrup761x25519-sha512@openssh.com .El .Pp The default is: .Bd -literal -offset indent mlkem768x25519-sha256, sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521 .Ed .Pp The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress Specifies the local addresses .Xr sshd 8 should listen on. The following forms may be used: .Pp .Bl -item -offset indent -compact .It .Cm ListenAddress .Sm off .Ar hostname | address .Sm on .Op Cm rdomain Ar domain .It .Cm ListenAddress .Sm off .Ar hostname : port .Sm on .Op Cm rdomain Ar domain .It .Cm ListenAddress .Sm off .Ar IPv4_address : port .Sm on .Op Cm rdomain Ar domain .It .Cm ListenAddress .Sm off .Oo Ar hostname | address Oc : Ar port .Sm on .Op Cm rdomain Ar domain .El .Pp The optional .Cm rdomain qualifier requests .Xr sshd 8 listen in an explicit routing domain. If .Ar port is not specified, sshd will listen on the address and all .Cm Port options specified. The default is to listen on all local addresses on the current default routing domain. Multiple .Cm ListenAddress options are permitted. For more information on routing domains, see .Xr rdomain 4 . .It Cm LoginGraceTime The server disconnects after this time if the user has not successfully logged in. If the value is 0, there is no time limit. The default is 120 seconds. .It Cm LogLevel Gives the verbosity level that is used when logging messages from .Xr sshd 8 . The possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of debugging output. Logging with a DEBUG level violates the privacy of users and is not recommended. .It Cm LogVerbose Specify one or more overrides to .Cm LogLevel . An override consists of one or more pattern lists that matches the source file, function and line number to force detailed logging for. For example, an override pattern of: .Bd -literal -offset indent kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* .Ed .Pp would enable detailed logging for line 1000 of .Pa kex.c , everything in the .Fn kex_exchange_identification function, and all code in the .Pa packet.c file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs Specifies the available MAC (message authentication code) algorithms. The MAC algorithm is used for data integrity protection. Multiple algorithms must be comma-separated. If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified algorithms will be placed at the head of the default set. .Pp The algorithms that contain .Qq -etm calculate the MAC after encryption (encrypt-then-mac). These are considered safer and their use recommended. The supported MACs are: .Pp .Bl -item -compact -offset indent .It hmac-md5 .It hmac-md5-96 .It hmac-sha1 .It hmac-sha1-96 .It hmac-sha2-256 .It hmac-sha2-512 .It umac-64@openssh.com .It umac-128@openssh.com .It hmac-md5-etm@openssh.com .It hmac-md5-96-etm@openssh.com .It hmac-sha1-etm@openssh.com .It hmac-sha1-96-etm@openssh.com .It hmac-sha2-256-etm@openssh.com .It hmac-sha2-512-etm@openssh.com .It umac-64-etm@openssh.com .It umac-128-etm@openssh.com .El .Pp The default is: .Bd -literal -offset indent umac-64-etm@openssh.com,umac-128-etm@openssh.com, hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, hmac-sha1-etm@openssh.com, umac-64@openssh.com,umac-128@openssh.com, hmac-sha2-256,hmac-sha2-512,hmac-sha1 .Ed .Pp The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm Match Introduces a conditional block. If all of the criteria on the .Cm Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another .Cm Match line or the end of the file. If a keyword appears in multiple .Cm Match blocks that are satisfied, only the first instance of the keyword is applied. .Pp The arguments to .Cm Match are one or more criteria-pattern pairs or one of the single token criteria: .Cm All , which matches all criteria, or .Cm Invalid-User , which matches when the requested user-name does not match any known account. The available criteria are .Cm User , .Cm Group , .Cm Host , .Cm LocalAddress , .Cm LocalPort , .Cm Version , .Cm RDomain , and .Cm Address (with .Cm RDomain representing the .Xr rdomain 4 on which the connection was received). .Pp The match patterns may consist of single entries or comma-separated lists and may use the wildcard and negation operators described in the .Sx PATTERNS section of .Xr ssh_config 5 . .Pp The patterns in an .Cm Address criteria may additionally contain addresses to match in CIDR address/masklen format, such as 192.0.2.0/24 or 2001:db8::/32. Note that the mask length provided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. .Pp The .Cm Version keyword matches against the version string of .Xr sshd 8 , for example .Dq OpenSSH_10.0 . .Pp Only a subset of keywords may be used on the lines following a .Cm Match keyword. Available keywords are .Cm AcceptEnv , .Cm AllowAgentForwarding , .Cm AllowGroups , .Cm AllowStreamLocalForwarding , .Cm AllowTcpForwarding , .Cm AllowUsers , .Cm AuthenticationMethods , .Cm AuthorizedKeysCommand , .Cm AuthorizedKeysCommandUser , .Cm AuthorizedKeysFile , .Cm AuthorizedPrincipalsCommand , .Cm AuthorizedPrincipalsCommandUser , .Cm AuthorizedPrincipalsFile , .Cm Banner , .Cm CASignatureAlgorithms , .Cm ChannelTimeout , .Cm ChrootDirectory , .Cm ClientAliveCountMax , .Cm ClientAliveInterval , .Cm DenyGroups , .Cm DenyUsers , .Cm DisableForwarding , .Cm ExposeAuthInfo , .Cm ForceCommand , .Cm GatewayPorts , .Cm GSSAPIAuthentication , .Cm HostbasedAcceptedAlgorithms , .Cm HostbasedAuthentication , .Cm HostbasedUsesNameFromPacketOnly , .Cm IgnoreRhosts , .Cm Include , .Cm IPQoS , .Cm KbdInteractiveAuthentication , .Cm KerberosAuthentication , .Cm LogLevel , .Cm MaxAuthTries , .Cm MaxSessions , .Cm PAMServiceName , .Cm PasswordAuthentication , .Cm PermitEmptyPasswords , .Cm PermitListen , .Cm PermitOpen , .Cm PermitRootLogin , .Cm PermitTTY , .Cm PermitTunnel , .Cm PermitUserRC , .Cm PubkeyAcceptedAlgorithms , .Cm PubkeyAuthentication , .Cm PubkeyAuthOptions , .Cm RefuseConnection , .Cm RekeyLimit , .Cm RevokedKeys , .Cm RDomain , .Cm SetEnv , .Cm StreamLocalBindMask , .Cm StreamLocalBindUnlink , .Cm TrustedUserCAKeys , .Cm UnusedConnectionTimeout , .Cm X11DisplayOffset , .Cm X11Forwarding and .Cm X11UseLocalhost . .It Cm MaxAuthTries Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6. .It Cm MaxSessions Specifies the maximum number of open shell, login or subsystem (e.g. sftp) sessions permitted per network connection. Multiple sessions may be established by clients that support connection multiplexing. Setting .Cm MaxSessions to 1 will effectively disable session multiplexing, whereas setting it to 0 will prevent all shell, login and subsystem sessions while still permitting forwarding. The default is 10. .It Cm MaxStartups Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the .Cm LoginGraceTime expires for a connection. The default is 10:30:100. .Pp Alternatively, random early drop can be enabled by specifying the three colon separated values start:rate:full (e.g. "10:30:60"). .Xr sshd 8 will refuse connection attempts with a probability of rate/100 (30%) if there are currently start (10) unauthenticated connections. The probability increases linearly and all connection attempts are refused if the number of unauthenticated connections reaches full (60). .It Cm ModuliFile Specifies the .Xr moduli 5 file that contains the Diffie-Hellman groups used for the .Dq diffie-hellman-group-exchange-sha1 and .Dq diffie-hellman-group-exchange-sha256 key exchange methods. The default is .Pa /etc/moduli . .It Cm PAMServiceName Specifies the service name used for Pluggable Authentication Modules (PAM) authentication, authorisation and session controls when .Cm UsePAM is enabled. The default is .Cm sshd . .It Cm PasswordAuthentication Specifies whether password authentication is allowed. The default is .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 .Cm no . .It Cm PermitListen Specifies the addresses/ports on which a remote TCP port forwarding may listen. The listen specification must be one of the following forms: .Pp .Bl -item -offset indent -compact .It .Cm PermitListen .Sm off .Ar port .Sm on .It .Cm PermitListen .Sm off .Ar host : port .Sm on .El .Pp Multiple permissions may be specified by separating them with whitespace. An argument of .Cm any can be used to remove all restrictions and permit any listen requests. An argument of .Cm none can be used to prohibit all listen requests. The host name may contain wildcards as described in the PATTERNS section in .Xr ssh_config 5 . The wildcard .Sq * can also be used in place of a port number to allow all ports. By default all port forwarding listen requests are permitted. Note that the .Cm GatewayPorts option may further restrict which addresses may be listened on. Note also that .Xr ssh 1 will request a listen host of .Dq localhost if no listen host was specifically requested, and this name is treated differently to explicit localhost addresses of .Dq 127.0.0.1 and .Dq ::1 . .It Cm PermitOpen Specifies the destinations to which TCP port forwarding is permitted. The forwarding specification must be one of the following forms: .Pp .Bl -item -offset indent -compact .It .Cm PermitOpen .Sm off .Ar host : port .Sm on .It .Cm PermitOpen .Sm off .Ar IPv4_addr : port .Sm on .It .Cm PermitOpen .Sm off .Ar \&[ IPv6_addr \&] : port .Sm on .El .Pp Multiple forwards may be specified by separating them with whitespace. An argument of .Cm any can be used to remove all restrictions and permit any forwarding requests. An argument of .Cm none can be used to prohibit all forwarding requests. The wildcard .Sq * can be used for host or port to allow all hosts or ports respectively. Otherwise, no pattern matching or address lookups are performed on supplied names. By default all port forwarding requests are permitted. .It Cm PermitRootLogin Specifies whether root can log in using .Xr ssh 1 . The argument must be .Cm yes , .Cm prohibit-password , .Cm forced-commands-only , or .Cm no . The default is .Cm prohibit-password . .Pp If this option is set to .Cm prohibit-password (or its deprecated alias, .Cm without-password ) , password and keyboard-interactive authentication are disabled for root. .Pp If this option is set to .Cm forced-commands-only , root login with public key authentication will be allowed, but only if the .Ar command option has been specified (which may be useful for taking remote backups even if root login is normally not allowed). All other authentication methods are disabled for root. .Pp If this option is set to .Cm no , root is not allowed to log in. .It Cm PermitTTY Specifies whether .Xr pty 4 allocation is permitted. The default is .Cm yes . .It Cm PermitTunnel Specifies whether .Xr tun 4 device forwarding is allowed. The argument must be .Cm yes , .Cm point-to-point (layer 3), .Cm ethernet (layer 2), or .Cm no . Specifying .Cm yes permits both .Cm point-to-point and .Cm ethernet . The default is .Cm no . .Pp Independent of this setting, the permissions of the selected .Xr tun 4 device must allow access to the user. .It Cm PermitUserEnvironment Specifies whether .Pa ~/.ssh/environment and .Cm environment= options in .Pa ~/.ssh/authorized_keys are processed by .Xr sshd 8 . Valid options are .Cm yes , .Cm no or a pattern-list specifying which environment variable names to accept (for example .Qq LANG,LC_* ) . The default is .Cm no . Enabling environment processing may enable users to bypass access restrictions in some configurations using mechanisms such as .Ev LD_PRELOAD . .It Cm PermitUserRC Specifies whether any .Pa ~/.ssh/rc file is executed. The default is .Cm yes . .It Cm PerSourceMaxStartups Specifies the number of unauthenticated connections allowed from a given source address, or .Dq none if there is no limit. This limit is applied in addition to .Cm MaxStartups , whichever is lower. The default is .Cm none . .It Cm PerSourceNetBlockSize Specifies the number of bits of source address that are grouped together for the purposes of applying PerSourceMaxStartups limits. Values for IPv4 and optionally IPv6 may be specified, separated by a colon. The default is .Cm 32:128 , which means each address is considered individually. .It Cm PerSourcePenalties Controls penalties for various conditions that may represent attacks on .Xr sshd 8 . If a penalty is enforced against a client then its source address and any others in the same network, as defined by .Cm PerSourceNetBlockSize , will be refused connection for a period. .Pp A penalty doesn't affect concurrent connections in progress, but multiple penalties from the same source from concurrent connections will accumulate up to a maximum. Conversely, penalties are not applied until a minimum threshold time has been accumulated. .Pp Penalties are enabled by default with the default settings listed below but may disabled using the .Cm no keyword. The defaults may be overridden by specifying one or more of the keywords below, separated by whitespace. All keywords accept arguments, e.g.\& .Qq crash:2m . .Bl -tag -width Ds .It Cm crash:duration Specifies how long to refuse clients that cause a crash of .Xr sshd 8 (default: 90s). .It Cm authfail:duration Specifies how long to refuse clients that disconnect after making one or more unsuccessful authentication attempts (default: 5s). .It Cm refuseconnection:duration Specifies how long to refuse clients that were administratively prohibited connection via the .Cm RefuseConnection option (default: 10s). .It Cm noauth:duration Specifies how long to refuse clients that disconnect without attempting authentication (default: 1s). This timeout should be used cautiously otherwise it may penalise legitimate scanning tools such as .Xr ssh-keyscan 1 . .It Cm grace-exceeded:duration Specifies how long to refuse clients that fail to authenticate after .Cm LoginGraceTime (default: 10s). .It Cm max:duration Specifies the maximum time a particular source address range will be refused access for (default: 10m). Repeated penalties will accumulate up to this maximum. .It Cm min:duration Specifies the minimum penalty that must accrue before enforcement begins (default: 15s). .It Cm max-sources4:number , max-sources6:number Specifies the maximum number of client IPv4 and IPv6 address ranges to track for penalties (default: 65536 for both). .It Cm overflow:mode Controls how the server behaves when .Cm max-sources4 or .Cm max-sources6 is exceeded. There are two operating modes: .Cm deny-all , which denies all incoming connections other than those exempted via .Cm PerSourcePenaltyExemptList until a penalty expires, and .Cm permissive , which allows new connections by removing existing penalties early (default: permissive). Note that client penalties below the .Cm min threshold count against the total number of tracked penalties. IPv4 and IPv6 addresses are tracked separately, so an overflow in one will not affect the other. .It Cm overflow6:mode Allows specifying a different overflow mode for IPv6 addresses. The default it to use the same overflow mode as was specified for IPv4. .El .It Cm PerSourcePenaltyExemptList Specifies a comma-separated list of addresses to exempt from penalties. This list may contain wildcards and CIDR address/masklen ranges. Note that the mask length provided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. The default is not to exempt any addresses. .It Cm PidFile Specifies the file that contains the process ID of the SSH daemon, or .Cm none to not write one. The default is .Pa /var/run/sshd.pid . .It Cm Port Specifies the port number that .Xr sshd 8 listens on. The default is 22. Multiple options of this type are permitted. See also .Cm ListenAddress . .It Cm PrintLastLog Specifies whether .Xr sshd 8 should print the date and time of the last user login when a user logs in interactively. The default is .Cm yes . .It Cm PrintMotd Specifies whether .Xr sshd 8 should print .Pa /etc/motd when a user logs in interactively. (On some systems it is also printed by the shell, .Pa /etc/profile , or equivalent.) The default is .Cm yes . .It Cm PubkeyAcceptedAlgorithms Specifies the signature algorithms that will be accepted for public key authentication as a list of comma-separated patterns. Alternately if the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ character, then the specified algorithms will be placed at the head of the default set. The default for this option is: .Bd -literal -offset 3n ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, sk-ssh-ed25519-cert-v01@openssh.com, sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, rsa-sha2-512-cert-v01@openssh.com, rsa-sha2-256-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . .It Cm PubkeyAuthOptions Sets one or more public key authentication options. The supported keywords are: .Cm none (the default; indicating no additional options are enabled), .Cm touch-required and .Cm verify-required . .Pp The .Cm touch-required option causes public key authentication using a FIDO authenticator algorithm (i.e.\& .Cm ecdsa-sk or .Cm ed25519-sk ) to always require the signature to attest that a physically present user explicitly confirmed the authentication (usually by touching the authenticator). By default, .Xr sshd 8 requires user presence unless overridden with an authorized_keys option. The .Cm touch-required flag disables this override. .Pp The .Cm verify-required option requires a FIDO key signature attest that the user was verified, e.g. via a PIN. .Pp Neither the .Cm touch-required or .Cm verify-required options have any effect for other, non-FIDO, public key types. .It Cm PubkeyAuthentication Specifies whether public key authentication is allowed. The default is .Cm yes . .It Cm RefuseConnection Indicates that .Xr sshd 8 should unconditionally terminate the connection. Additionally, a .Cm refuseconnection penalty may be recorded against the source of the connection if .Cm PerSourcePenalties are enabled. This option is only really useful in a .Cm Match block. .It Cm RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of .Sq K , .Sq M , or .Sq G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between .Sq 1G and .Sq 4G , depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the .Sx TIME FORMATS section. The default value for .Cm RekeyLimit is .Cm default none , which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. .It Cm RequiredRSASize Specifies the minimum RSA key size (in bits) that .Xr sshd 8 will accept. User and host-based authentication keys smaller than this limit will be refused. The default is .Cm 1024 bits. Note that this limit may only be raised from the default. .It Cm RevokedKeys Specifies revoked public keys file, or .Cm none to not use one. Keys listed in this file will be refused for public key authentication. Note that if this file is not readable, then public key authentication will be refused for all users. Keys may be specified as a text file, listing one public key per line, or as an OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . .It Cm RDomain Specifies an explicit routing domain that is applied after authentication has completed. The user session, as well as any forwarded or listening IP sockets, will be bound to this .Xr rdomain 4 . If the routing domain is set to .Cm \&%D , then the domain in which the incoming connection was received will be applied. .It Cm SecurityKeyProvider Specifies a path to a library that will be used when loading FIDO authenticator-hosted keys, overriding the default of using the built-in USB HID support. .It Cm SetEnv Specifies one or more environment variables to set in child sessions started by .Xr sshd 8 as .Dq NAME=VALUE . The environment value may be quoted (e.g. if it contains whitespace characters). Environment variables set by .Cm SetEnv override the default environment and any variables specified by the user via .Cm AcceptEnv or .Cm PermitUserEnvironment . .It Cm SshdAuthPath Overrides the default path to the .Cm sshd-auth binary that is invoked to complete user authentication. The default is .Pa /usr/libexec/sshd-auth . This option is intended for use by tests. .It Cm SshdSessionPath Overrides the default path to the .Cm sshd-session binary that is invoked to handle each connection. The default is .Pa /usr/libexec/sshd-session . This option is intended for use by tests. .It Cm StreamLocalBindMask Sets the octal file creation mode mask .Pq umask used when creating a Unix-domain socket file for local or remote port forwarding. This option is only used for port forwarding to a Unix-domain socket file. .Pp The default value is 0177, which creates a Unix-domain socket file that is readable and writable only by the owner. Note that not all operating systems honor the file mode on Unix-domain socket files. .It Cm StreamLocalBindUnlink Specifies whether to remove an existing Unix-domain socket file for local or remote port forwarding before creating a new one. If the socket file already exists and .Cm StreamLocalBindUnlink is not enabled, .Nm sshd will be unable to forward the port to the Unix-domain socket file. This option is only used for port forwarding to a Unix-domain socket file. .Pp The argument must be .Cm yes or .Cm no . The default is .Cm no . .It Cm StrictModes Specifies whether .Xr sshd 8 should check file modes and ownership of the user's files and home directory before accepting login. This is normally desirable because novices sometimes accidentally leave their directory or files world-writable. The default is .Cm yes . Note that this does not apply to .Cm ChrootDirectory , whose permissions and ownership are checked unconditionally. .It Cm Subsystem Configures an external subsystem (e.g. file transfer daemon). Arguments should be a subsystem name and a command (with optional arguments) to execute upon subsystem request. .Pp The command .Cm sftp-server implements the SFTP file transfer subsystem. .Pp Alternately the name .Cm internal-sftp implements an in-process SFTP server. This may simplify configurations using .Cm ChrootDirectory to force a different filesystem root on clients. It accepts the same command line arguments as .Cm sftp-server and even though it is in-process, settings such as .Cm LogLevel or .Cm SyslogFacility do not apply to it and must be set explicitly via command line arguments. .Pp By default no subsystems are defined. .It Cm SyslogFacility Gives the facility code that is used when logging messages from .Xr sshd 8 . The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is AUTH. .It Cm TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, this means that connections will die if the route is down temporarily, and some people find it annoying. On the other hand, if TCP keepalives are not sent, sessions may hang indefinitely on the server, leaving .Qq ghost users and consuming server resources. .Pp The default is .Cm yes (to send TCP keepalive messages), and the server will notice if the network goes down or the client host crashes. This avoids infinitely hanging sessions. .Pp To disable TCP keepalive messages, the value should be set to .Cm no . .It Cm TrustedUserCAKeys Specifies a file containing public keys of certificate authorities that are trusted to sign user certificates for authentication, or .Cm none to not use one. Keys are listed one per line; empty lines and comments starting with .Ql # are allowed. If a certificate is presented for authentication and has its signing CA key listed in this file, then it may be used for authentication for any user listed in the certificate's principals list. Note that certificates that lack a list of principals will not be permitted for authentication using .Cm TrustedUserCAKeys . For more details on certificates, see the CERTIFICATES section in .Xr ssh-keygen 1 . .It Cm UnusedConnectionTimeout Specifies whether and how quickly .Xr sshd 8 should close client connections with no open channels. Open channels include active shell, command execution or subsystem sessions, connected network, socket, agent or X11 forwardings. Forwarding listeners, such as those from the .Xr ssh 1 .Fl R flag, are not considered as open channels and do not prevent the timeout. The timeout value is specified in seconds or may use any of the units documented in the .Sx TIME FORMATS section. .Pp Note that this timeout starts when the client connection completes user authentication but before the client has an opportunity to open any channels. Caution should be used when using short timeout values, as they may not provide sufficient time for the client to request and open its channels before terminating the connection. .Pp The default .Cm none is to never expire connections for having no open channels. This option may be useful in conjunction with .Cm ChannelTimeout . .It Cm UseDNS Specifies whether .Xr sshd 8 should look up the remote host name, and to check that the resolved host name for the remote IP address maps back to the very same IP address. .Pp If this option is set to .Cm no (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 .Cm yes this will enable PAM authentication using .Cm KbdInteractiveAuthentication and .Cm PasswordAuthentication in addition to PAM account and session module processing for all authentication types. .Pp Because PAM keyboard-interactive authentication usually serves an equivalent role to password authentication, you should disable either .Cm PasswordAuthentication or .Cm KbdInteractiveAuthentication . .Pp If .Cm UsePAM is enabled, you will not be able to run .Xr sshd 8 as a non-root user. The default is .Cm no . .It Cm VersionAddendum Optionally specifies additional text to append to the SSH protocol banner sent by the server upon connection. The default is .Cm none . .It Cm X11DisplayOffset Specifies the first display number available for .Xr sshd 8 Ns 's X11 forwarding. This prevents sshd from interfering with real X11 servers. The default is 10. .It Cm X11Forwarding Specifies whether X11 forwarding is permitted. The argument must be .Cm yes or .Cm no . The default is .Cm no . .Pp When X11 forwarding is enabled, there may be additional exposure to the server and to client displays if the .Xr sshd 8 proxy display is configured to listen on the wildcard address (see .Cm X11UseLocalhost ) , though this is not the default. Additionally, the authentication spoofing and authentication data verification and substitution occur on the client side. The security risk of using X11 forwarding is that the client's X11 display server may be exposed to attack when the SSH client requests forwarding (see the warnings for .Cm ForwardX11 in .Xr ssh_config 5 ) . A system administrator may have a stance in which they want to protect clients that may expose themselves to attack by unwittingly requesting X11 forwarding, which can warrant a .Cm no setting. .Pp Note that disabling X11 forwarding does not prevent users from forwarding X11 traffic, as users can always install their own forwarders. .It Cm X11UseLocalhost Specifies whether .Xr sshd 8 should bind the X11 forwarding server to the loopback address or to the wildcard address. By default, sshd binds the forwarding server to the loopback address and sets the hostname part of the .Ev DISPLAY environment variable to .Cm localhost . This prevents remote hosts from connecting to the proxy display. However, some older X11 clients may not function with this configuration. .Cm X11UseLocalhost may be set to .Cm no to specify that the forwarding server should be bound to the wildcard address. The argument must be .Cm yes or .Cm no . The default is .Cm yes . .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 program, or .Cm none to not use one. The default is .Pa /usr/X11R6/bin/xauth . .El .Sh TIME FORMATS .Xr sshd 8 command-line arguments and configuration file options that specify time may be expressed using a sequence of the form: .Sm off .Ar time Op Ar qualifier , .Sm on where .Ar time is a positive integer value and .Ar qualifier is one of the following: .Pp .Bl -tag -width Ds -compact -offset indent .It Aq Cm none seconds .It Cm s | Cm S seconds .It Cm m | Cm M minutes .It Cm h | Cm H hours .It Cm d | Cm D days .It Cm w | Cm W weeks .El .Pp Each member of the sequence is added together to calculate the total time value. .Pp Time format examples: .Pp .Bl -tag -width Ds -compact -offset indent .It 600 600 seconds (10 minutes) .It 10m 10 minutes .It 1h30m 1 hour 30 minutes (90 minutes) .El .Sh TOKENS Arguments to some keywords can make use of tokens, which are expanded at runtime: .Pp .Bl -tag -width XXXX -offset indent -compact .It %% A literal .Sq % . .It \&%C Identifies the connection endpoints, containing four space-separated values: client address, client port number, server address, and server port number. .It \&%D The routing domain in which the incoming connection was received. .It %F The fingerprint of the CA key. .It %f The fingerprint of the key or certificate. .It %h The home directory of the user. .It %i The key ID in the certificate. .It %K The base64-encoded CA key. .It %k The base64-encoded key or certificate for authentication. .It %s The serial number of the certificate. .It \&%T The type of the CA key. .It %t The key or certificate type. .It \&%U The numeric user ID of the target user. .It %u The username. .El .Pp .Cm AuthorizedKeysCommand accepts the tokens %%, %C, %D, %f, %h, %k, %t, %U, and %u. .Pp .Cm AuthorizedKeysFile accepts the tokens %%, %h, %U, and %u. .Pp .Cm AuthorizedPrincipalsCommand accepts the tokens %%, %C, %D, %F, %f, %h, %i, %K, %k, %s, %T, %t, %U, and %u. .Pp .Cm AuthorizedPrincipalsFile accepts the tokens %%, %h, %U, and %u. .Pp .Cm ChrootDirectory accepts the tokens %%, %h, %U, and %u. .Pp .Cm RoutingDomain accepts the token %D. .Sh FILES .Bl -tag -width Ds .It Pa /etc/ssh/sshd_config Contains configuration data for .Xr sshd 8 . This file should be writable by root only, but it is recommended (though not necessary) that it be world-readable. .El .Sh SEE ALSO .Xr sftp-server 8 , .Xr sshd 8 .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos , .An Theo de Raadt and .An Dug Song removed many bugs, re-added newer features and created OpenSSH. .An Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. .An Niels Provos and .An Markus Friedl contributed support for privilege separation. openssh-10.0p1/PaxHeaders.10889/ssherr.c100644 001750 001750 0000000003614775415623 0014626xustar0030 atime=1744182234.874827721 openssh-10.0p1/ssherr.c010064400017500001750000000122611477541562300132130ustar00djmdjm/* $OpenBSD: ssherr.c,v 1.10 2020/01/25 23:13:09 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 #include #include "ssherr.h" const char * ssh_err(int n) { switch (n) { case SSH_ERR_SUCCESS: return "success"; case SSH_ERR_INTERNAL_ERROR: return "unexpected internal error"; case SSH_ERR_ALLOC_FAIL: return "memory allocation failed"; case SSH_ERR_MESSAGE_INCOMPLETE: return "incomplete message"; case SSH_ERR_INVALID_FORMAT: return "invalid format"; case SSH_ERR_BIGNUM_IS_NEGATIVE: return "bignum is negative"; case SSH_ERR_STRING_TOO_LARGE: return "string is too large"; case SSH_ERR_BIGNUM_TOO_LARGE: return "bignum is too large"; case SSH_ERR_ECPOINT_TOO_LARGE: return "elliptic curve point is too large"; case SSH_ERR_NO_BUFFER_SPACE: return "insufficient buffer space"; case SSH_ERR_INVALID_ARGUMENT: return "invalid argument"; case SSH_ERR_KEY_BITS_MISMATCH: return "key bits do not match"; case SSH_ERR_EC_CURVE_INVALID: return "invalid elliptic curve"; case SSH_ERR_KEY_TYPE_MISMATCH: return "key type does not match"; case SSH_ERR_KEY_TYPE_UNKNOWN: return "unknown or unsupported key type"; case SSH_ERR_EC_CURVE_MISMATCH: return "elliptic curve does not match"; case SSH_ERR_EXPECTED_CERT: return "plain key provided where certificate required"; case SSH_ERR_KEY_LACKS_CERTBLOB: return "key lacks certificate data"; case SSH_ERR_KEY_CERT_UNKNOWN_TYPE: return "unknown/unsupported certificate type"; case SSH_ERR_KEY_CERT_INVALID_SIGN_KEY: return "invalid certificate signing key"; case SSH_ERR_KEY_INVALID_EC_VALUE: return "invalid elliptic curve value"; case SSH_ERR_SIGNATURE_INVALID: return "incorrect signature"; case SSH_ERR_LIBCRYPTO_ERROR: return "error in libcrypto"; /* XXX fetch and return */ case SSH_ERR_UNEXPECTED_TRAILING_DATA: return "unexpected bytes remain after decoding"; case SSH_ERR_SYSTEM_ERROR: return strerror(errno); case SSH_ERR_KEY_CERT_INVALID: return "invalid certificate"; case SSH_ERR_AGENT_COMMUNICATION: return "communication with agent failed"; case SSH_ERR_AGENT_FAILURE: return "agent refused operation"; case SSH_ERR_DH_GEX_OUT_OF_RANGE: return "DH GEX group out of range"; case SSH_ERR_DISCONNECTED: return "disconnected"; case SSH_ERR_MAC_INVALID: return "message authentication code incorrect"; case SSH_ERR_NO_CIPHER_ALG_MATCH: return "no matching cipher found"; case SSH_ERR_NO_MAC_ALG_MATCH: return "no matching MAC found"; case SSH_ERR_NO_COMPRESS_ALG_MATCH: return "no matching compression method found"; case SSH_ERR_NO_KEX_ALG_MATCH: return "no matching key exchange method found"; case SSH_ERR_NO_HOSTKEY_ALG_MATCH: return "no matching host key type found"; case SSH_ERR_PROTOCOL_MISMATCH: return "protocol version mismatch"; case SSH_ERR_NO_PROTOCOL_VERSION: return "could not read protocol version"; case SSH_ERR_NO_HOSTKEY_LOADED: return "could not load host key"; case SSH_ERR_NEED_REKEY: return "rekeying not supported by peer"; case SSH_ERR_PASSPHRASE_TOO_SHORT: return "passphrase is too short (minimum five characters)"; case SSH_ERR_FILE_CHANGED: return "file changed while reading"; case SSH_ERR_KEY_UNKNOWN_CIPHER: return "key encrypted using unsupported cipher"; case SSH_ERR_KEY_WRONG_PASSPHRASE: return "incorrect passphrase supplied to decrypt private key"; case SSH_ERR_KEY_BAD_PERMISSIONS: return "bad permissions"; case SSH_ERR_KEY_CERT_MISMATCH: return "certificate does not match key"; case SSH_ERR_KEY_NOT_FOUND: return "key not found"; case SSH_ERR_AGENT_NOT_PRESENT: return "agent not present"; case SSH_ERR_AGENT_NO_IDENTITIES: return "agent contains no identities"; case SSH_ERR_BUFFER_READ_ONLY: return "internal error: buffer is read-only"; case SSH_ERR_KRL_BAD_MAGIC: return "KRL file has invalid magic number"; case SSH_ERR_KEY_REVOKED: return "Key is revoked"; case SSH_ERR_CONN_CLOSED: return "Connection closed"; case SSH_ERR_CONN_TIMEOUT: return "Connection timed out"; case SSH_ERR_CONN_CORRUPT: 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"; } } openssh-10.0p1/PaxHeaders.10889/ssherr.h100644 001750 001750 0000000003614775415623 0014633xustar0030 atime=1744182234.874827721 openssh-10.0p1/ssherr.h010064400017500001750000000065621477541562300132270ustar00djmdjm/* $OpenBSD: ssherr.h,v 1.8 2020/01/25 23:13:09 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. */ #ifndef _SSHERR_H #define _SSHERR_H /* XXX are these too granular? not granular enough? I can't decide - djm */ /* Error codes */ #define SSH_ERR_SUCCESS 0 #define SSH_ERR_INTERNAL_ERROR -1 #define SSH_ERR_ALLOC_FAIL -2 #define SSH_ERR_MESSAGE_INCOMPLETE -3 #define SSH_ERR_INVALID_FORMAT -4 #define SSH_ERR_BIGNUM_IS_NEGATIVE -5 #define SSH_ERR_STRING_TOO_LARGE -6 #define SSH_ERR_BIGNUM_TOO_LARGE -7 #define SSH_ERR_ECPOINT_TOO_LARGE -8 #define SSH_ERR_NO_BUFFER_SPACE -9 #define SSH_ERR_INVALID_ARGUMENT -10 #define SSH_ERR_KEY_BITS_MISMATCH -11 #define SSH_ERR_EC_CURVE_INVALID -12 #define SSH_ERR_KEY_TYPE_MISMATCH -13 #define SSH_ERR_KEY_TYPE_UNKNOWN -14 /* XXX UNSUPPORTED? */ #define SSH_ERR_EC_CURVE_MISMATCH -15 #define SSH_ERR_EXPECTED_CERT -16 #define SSH_ERR_KEY_LACKS_CERTBLOB -17 #define SSH_ERR_KEY_CERT_UNKNOWN_TYPE -18 #define SSH_ERR_KEY_CERT_INVALID_SIGN_KEY -19 #define SSH_ERR_KEY_INVALID_EC_VALUE -20 #define SSH_ERR_SIGNATURE_INVALID -21 #define SSH_ERR_LIBCRYPTO_ERROR -22 #define SSH_ERR_UNEXPECTED_TRAILING_DATA -23 #define SSH_ERR_SYSTEM_ERROR -24 #define SSH_ERR_KEY_CERT_INVALID -25 #define SSH_ERR_AGENT_COMMUNICATION -26 #define SSH_ERR_AGENT_FAILURE -27 #define SSH_ERR_DH_GEX_OUT_OF_RANGE -28 #define SSH_ERR_DISCONNECTED -29 #define SSH_ERR_MAC_INVALID -30 #define SSH_ERR_NO_CIPHER_ALG_MATCH -31 #define SSH_ERR_NO_MAC_ALG_MATCH -32 #define SSH_ERR_NO_COMPRESS_ALG_MATCH -33 #define SSH_ERR_NO_KEX_ALG_MATCH -34 #define SSH_ERR_NO_HOSTKEY_ALG_MATCH -35 #define SSH_ERR_NO_HOSTKEY_LOADED -36 #define SSH_ERR_PROTOCOL_MISMATCH -37 #define SSH_ERR_NO_PROTOCOL_VERSION -38 #define SSH_ERR_NEED_REKEY -39 #define SSH_ERR_PASSPHRASE_TOO_SHORT -40 #define SSH_ERR_FILE_CHANGED -41 #define SSH_ERR_KEY_UNKNOWN_CIPHER -42 #define SSH_ERR_KEY_WRONG_PASSPHRASE -43 #define SSH_ERR_KEY_BAD_PERMISSIONS -44 #define SSH_ERR_KEY_CERT_MISMATCH -45 #define SSH_ERR_KEY_NOT_FOUND -46 #define SSH_ERR_AGENT_NOT_PRESENT -47 #define SSH_ERR_AGENT_NO_IDENTITIES -48 #define SSH_ERR_BUFFER_READ_ONLY -49 #define SSH_ERR_KRL_BAD_MAGIC -50 #define SSH_ERR_KEY_REVOKED -51 #define SSH_ERR_CONN_CLOSED -52 #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); #endif /* _SSHERR_H */ openssh-10.0p1/PaxHeaders.10889/sshkey-xmss.c100644 001750 001750 0000000003514775415623 0015615xustar0029 atime=1744182234.87580493 openssh-10.0p1/sshkey-xmss.c010064400017500001750000000733461477541562300142160ustar00djmdjm/* $OpenBSD: sshkey-xmss.c,v 1.12 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #ifdef WITH_XMSS #include #include #include #include #include #include #include #ifdef HAVE_SYS_FILE_H # include #endif #include "ssh2.h" #include "ssherr.h" #include "sshbuf.h" #include "cipher.h" #include "sshkey.h" #include "sshkey-xmss.h" #include "atomicio.h" #include "log.h" #include "xmss_fast.h" /* opaque internal XMSS state */ #define XMSS_MAGIC "xmss-state-v1" #define XMSS_CIPHERNAME "aes256-gcm@openssh.com" struct ssh_xmss_state { xmss_params params; u_int32_t n, w, h, k; bds_state bds; u_char *stack; u_int32_t stackoffset; u_char *stacklevels; u_char *auth; u_char *keep; u_char *th_nodes; u_char *retain; treehash_inst *treehash; u_int32_t idx; /* state read from file */ u_int32_t maxidx; /* restricted # of signatures */ int have_state; /* .state file exists */ int lockfd; /* locked in sshkey_xmss_get_state() */ u_char allow_update; /* allow sshkey_xmss_update_state() */ char *enc_ciphername;/* encrypt state with cipher */ u_char *enc_keyiv; /* encrypt state with key */ u_int32_t enc_keyiv_len; /* length of enc_keyiv */ }; int sshkey_xmss_init_bds_state(struct sshkey *); int sshkey_xmss_init_enc_key(struct sshkey *, const char *); void sshkey_xmss_free_bds(struct sshkey *); int sshkey_xmss_get_state_from_file(struct sshkey *, const char *, int *, int); int sshkey_xmss_encrypt_state(const struct sshkey *, struct sshbuf *, struct sshbuf **); int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *, struct sshbuf **); int sshkey_xmss_serialize_enc_key(const struct sshkey *, struct sshbuf *); int sshkey_xmss_deserialize_enc_key(struct sshkey *, struct sshbuf *); #define PRINT(...) do { if (printerror) sshlog(__FILE__, __func__, __LINE__, \ 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__); } while (0) int sshkey_xmss_init(struct sshkey *key, const char *name) { struct ssh_xmss_state *state; if (key->xmss_state != NULL) return SSH_ERR_INVALID_FORMAT; if (name == NULL) return SSH_ERR_INVALID_FORMAT; state = calloc(sizeof(struct ssh_xmss_state), 1); if (state == NULL) return SSH_ERR_ALLOC_FAIL; if (strcmp(name, XMSS_SHA2_256_W16_H10_NAME) == 0) { state->n = 32; state->w = 16; state->h = 10; } else if (strcmp(name, XMSS_SHA2_256_W16_H16_NAME) == 0) { state->n = 32; state->w = 16; state->h = 16; } else if (strcmp(name, XMSS_SHA2_256_W16_H20_NAME) == 0) { state->n = 32; state->w = 16; state->h = 20; } else { free(state); return SSH_ERR_KEY_TYPE_UNKNOWN; } if ((key->xmss_name = strdup(name)) == NULL) { free(state); return SSH_ERR_ALLOC_FAIL; } state->k = 2; /* XXX hardcoded */ state->lockfd = -1; if (xmss_set_params(&state->params, state->n, state->h, state->w, state->k) != 0) { free(state); return SSH_ERR_INVALID_FORMAT; } key->xmss_state = state; return 0; } void sshkey_xmss_free_state(struct sshkey *key) { struct ssh_xmss_state *state = key->xmss_state; sshkey_xmss_free_bds(key); if (state) { if (state->enc_keyiv) { explicit_bzero(state->enc_keyiv, state->enc_keyiv_len); free(state->enc_keyiv); } free(state->enc_ciphername); free(state); } key->xmss_state = NULL; } #define SSH_XMSS_K2_MAGIC "k=2" #define num_stack(x) ((x->h+1)*(x->n)) #define num_stacklevels(x) (x->h+1) #define num_auth(x) ((x->h)*(x->n)) #define num_keep(x) ((x->h >> 1)*(x->n)) #define num_th_nodes(x) ((x->h - x->k)*(x->n)) #define num_retain(x) (((1ULL << x->k) - x->k - 1) * (x->n)) #define num_treehash(x) ((x->h) - (x->k)) int sshkey_xmss_init_bds_state(struct sshkey *key) { struct ssh_xmss_state *state = key->xmss_state; u_int32_t i; state->stackoffset = 0; if ((state->stack = calloc(num_stack(state), 1)) == NULL || (state->stacklevels = calloc(num_stacklevels(state), 1))== NULL || (state->auth = calloc(num_auth(state), 1)) == NULL || (state->keep = calloc(num_keep(state), 1)) == NULL || (state->th_nodes = calloc(num_th_nodes(state), 1)) == NULL || (state->retain = calloc(num_retain(state), 1)) == NULL || (state->treehash = calloc(num_treehash(state), sizeof(treehash_inst))) == NULL) { sshkey_xmss_free_bds(key); return SSH_ERR_ALLOC_FAIL; } for (i = 0; i < state->h - state->k; i++) state->treehash[i].node = &state->th_nodes[state->n*i]; xmss_set_bds_state(&state->bds, state->stack, state->stackoffset, state->stacklevels, state->auth, state->keep, state->treehash, state->retain, 0); return 0; } void sshkey_xmss_free_bds(struct sshkey *key) { struct ssh_xmss_state *state = key->xmss_state; if (state == NULL) return; free(state->stack); free(state->stacklevels); free(state->auth); free(state->keep); free(state->th_nodes); free(state->retain); free(state->treehash); state->stack = NULL; state->stacklevels = NULL; state->auth = NULL; state->keep = NULL; state->th_nodes = NULL; state->retain = NULL; state->treehash = NULL; } void * sshkey_xmss_params(const struct sshkey *key) { struct ssh_xmss_state *state = key->xmss_state; if (state == NULL) return NULL; return &state->params; } void * sshkey_xmss_bds_state(const struct sshkey *key) { struct ssh_xmss_state *state = key->xmss_state; if (state == NULL) return NULL; return &state->bds; } int sshkey_xmss_siglen(const struct sshkey *key, size_t *lenp) { struct ssh_xmss_state *state = key->xmss_state; if (lenp == NULL) return SSH_ERR_INVALID_ARGUMENT; if (state == NULL) return SSH_ERR_INVALID_FORMAT; *lenp = 4 + state->n + state->params.wots_par.keysize + state->h * state->n; return 0; } size_t sshkey_xmss_pklen(const struct sshkey *key) { struct ssh_xmss_state *state = key->xmss_state; if (state == NULL) return 0; return state->n * 2; } size_t sshkey_xmss_sklen(const struct sshkey *key) { struct ssh_xmss_state *state = key->xmss_state; if (state == NULL) return 0; return state->n * 4 + 4; } int sshkey_xmss_init_enc_key(struct sshkey *k, const char *ciphername) { struct ssh_xmss_state *state = k->xmss_state; const struct sshcipher *cipher; size_t keylen = 0, ivlen = 0; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((cipher = cipher_by_name(ciphername)) == NULL) return SSH_ERR_INTERNAL_ERROR; if ((state->enc_ciphername = strdup(ciphername)) == NULL) return SSH_ERR_ALLOC_FAIL; keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); state->enc_keyiv_len = keylen + ivlen; if ((state->enc_keyiv = calloc(state->enc_keyiv_len, 1)) == NULL) { free(state->enc_ciphername); state->enc_ciphername = NULL; return SSH_ERR_ALLOC_FAIL; } arc4random_buf(state->enc_keyiv, state->enc_keyiv_len); return 0; } int sshkey_xmss_serialize_enc_key(const struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; int r; if (state == NULL || state->enc_keyiv == NULL || state->enc_ciphername == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_put_cstring(b, state->enc_ciphername)) != 0 || (r = sshbuf_put_string(b, state->enc_keyiv, state->enc_keyiv_len)) != 0) return r; return 0; } int sshkey_xmss_deserialize_enc_key(struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; size_t len; int r; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_get_cstring(b, &state->enc_ciphername, NULL)) != 0 || (r = sshbuf_get_string(b, &state->enc_keyiv, &len)) != 0) return r; state->enc_keyiv_len = len; return 0; } int sshkey_xmss_serialize_pk_info(const struct sshkey *k, struct sshbuf *b, enum sshkey_serialize_rep opts) { struct ssh_xmss_state *state = k->xmss_state; u_char have_info = 1; u_int32_t idx; int r; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if (opts != SSHKEY_SERIALIZE_INFO) return 0; idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx; if ((r = sshbuf_put_u8(b, have_info)) != 0 || (r = sshbuf_put_u32(b, idx)) != 0 || (r = sshbuf_put_u32(b, state->maxidx)) != 0) return r; return 0; } int sshkey_xmss_deserialize_pk_info(struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; u_char have_info; int r; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; /* optional */ if (sshbuf_len(b) == 0) return 0; if ((r = sshbuf_get_u8(b, &have_info)) != 0) return r; if (have_info != 1) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_get_u32(b, &state->idx)) != 0 || (r = sshbuf_get_u32(b, &state->maxidx)) != 0) return r; return 0; } int sshkey_xmss_generate_private_key(struct sshkey *k, int bits) { int r; const char *name; if (bits == 10) { name = XMSS_SHA2_256_W16_H10_NAME; } else if (bits == 16) { name = XMSS_SHA2_256_W16_H16_NAME; } else if (bits == 20) { name = XMSS_SHA2_256_W16_H20_NAME; } else { name = XMSS_DEFAULT_NAME; } if ((r = sshkey_xmss_init(k, name)) != 0 || (r = sshkey_xmss_init_bds_state(k)) != 0 || (r = sshkey_xmss_init_enc_key(k, XMSS_CIPHERNAME)) != 0) return r; if ((k->xmss_pk = malloc(sshkey_xmss_pklen(k))) == NULL || (k->xmss_sk = malloc(sshkey_xmss_sklen(k))) == NULL) { return SSH_ERR_ALLOC_FAIL; } xmss_keypair(k->xmss_pk, k->xmss_sk, sshkey_xmss_bds_state(k), sshkey_xmss_params(k)); return 0; } int sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename, int *have_file, int printerror) { struct sshbuf *b = NULL, *enc = NULL; int ret = SSH_ERR_SYSTEM_ERROR, r, fd = -1; u_int32_t len; unsigned char buf[4], *data = NULL; *have_file = 0; if ((fd = open(filename, O_RDONLY)) >= 0) { *have_file = 1; if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) { PRINT("corrupt state file: %s", filename); goto done; } len = PEEK_U32(buf); if ((data = calloc(len, 1)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto done; } if (atomicio(read, fd, data, len) != len) { PRINT("cannot read blob: %s", filename); goto done; } if ((enc = sshbuf_from(data, len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto done; } sshkey_xmss_free_bds(k); if ((r = sshkey_xmss_decrypt_state(k, enc, &b)) != 0) { ret = r; goto done; } if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) { ret = r; goto done; } ret = 0; } done: if (fd != -1) close(fd); free(data); sshbuf_free(enc); sshbuf_free(b); return ret; } int sshkey_xmss_get_state(const struct sshkey *k, int printerror) { struct ssh_xmss_state *state = k->xmss_state; u_int32_t idx = 0; char *filename = NULL; char *statefile = NULL, *ostatefile = NULL, *lockfile = NULL; int lockfd = -1, have_state = 0, have_ostate, tries = 0; int ret = SSH_ERR_INVALID_ARGUMENT, r; if (state == NULL) goto done; /* * If maxidx is set, then we are allowed a limited number * of signatures, but don't need to access the disk. * Otherwise we need to deal with the on-disk state. */ if (state->maxidx) { /* xmss_sk always contains the current state */ idx = PEEK_U32(k->xmss_sk); if (idx < state->maxidx) { state->allow_update = 1; return 0; } return SSH_ERR_INVALID_ARGUMENT; } if ((filename = k->xmss_filename) == NULL) goto done; if (asprintf(&lockfile, "%s.lock", filename) == -1 || asprintf(&statefile, "%s.state", filename) == -1 || asprintf(&ostatefile, "%s.ostate", filename) == -1) { ret = SSH_ERR_ALLOC_FAIL; goto done; } if ((lockfd = open(lockfile, O_CREAT|O_RDONLY, 0600)) == -1) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("cannot open/create: %s", lockfile); goto done; } while (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { if (errno != EWOULDBLOCK) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("cannot lock: %s", lockfile); goto done; } if (++tries > 10) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("giving up on: %s", lockfile); goto done; } usleep(1000*100*tries); } /* XXX no longer const */ if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k, statefile, &have_state, printerror)) != 0) { if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k, ostatefile, &have_ostate, printerror)) == 0) { state->allow_update = 1; r = sshkey_xmss_forward_state(k, 1); state->idx = PEEK_U32(k->xmss_sk); state->allow_update = 0; } } if (!have_state && !have_ostate) { /* check that bds state is initialized */ if (state->bds.auth == NULL) goto done; PRINT("start from scratch idx 0: %u", state->idx); } else if (r != 0) { ret = r; goto done; } if (state->idx + 1 < state->idx) { PRINT("state wrap: %u", state->idx); goto done; } state->have_state = have_state; state->lockfd = lockfd; state->allow_update = 1; lockfd = -1; ret = 0; done: if (lockfd != -1) close(lockfd); free(lockfile); free(statefile); free(ostatefile); return ret; } int sshkey_xmss_forward_state(const struct sshkey *k, u_int32_t reserve) { struct ssh_xmss_state *state = k->xmss_state; u_char *sig = NULL; size_t required_siglen; unsigned long long smlen; u_char data; int ret, r; if (state == NULL || !state->allow_update) return SSH_ERR_INVALID_ARGUMENT; if (reserve == 0) return SSH_ERR_INVALID_ARGUMENT; if (state->idx + reserve <= state->idx) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshkey_xmss_siglen(k, &required_siglen)) != 0) return r; if ((sig = malloc(required_siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; while (reserve-- > 0) { state->idx = PEEK_U32(k->xmss_sk); smlen = required_siglen; if ((ret = xmss_sign(k->xmss_sk, sshkey_xmss_bds_state(k), sig, &smlen, &data, 0, sshkey_xmss_params(k))) != 0) { r = SSH_ERR_INVALID_ARGUMENT; break; } } free(sig); return r; } int sshkey_xmss_update_state(const struct sshkey *k, int printerror) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *b = NULL, *enc = NULL; u_int32_t idx = 0; unsigned char buf[4]; char *filename = NULL; char *statefile = NULL, *ostatefile = NULL, *nstatefile = NULL; int fd = -1; int ret = SSH_ERR_INVALID_ARGUMENT; if (state == NULL || !state->allow_update) return ret; if (state->maxidx) { /* no update since the number of signatures is limited */ ret = 0; goto done; } idx = PEEK_U32(k->xmss_sk); if (idx == state->idx) { /* no signature happened, no need to update */ ret = 0; goto done; } else if (idx != state->idx + 1) { PRINT("more than one signature happened: idx %u state %u", idx, state->idx); goto done; } state->idx = idx; if ((filename = k->xmss_filename) == NULL) goto done; if (asprintf(&statefile, "%s.state", filename) == -1 || asprintf(&ostatefile, "%s.ostate", filename) == -1 || asprintf(&nstatefile, "%s.nstate", filename) == -1) { ret = SSH_ERR_ALLOC_FAIL; goto done; } unlink(nstatefile); if ((b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto done; } if ((ret = sshkey_xmss_serialize_state(k, b)) != 0) { PRINT("SERLIALIZE FAILED: %d", ret); goto done; } if ((ret = sshkey_xmss_encrypt_state(k, b, &enc)) != 0) { PRINT("ENCRYPT FAILED: %d", ret); goto done; } if ((fd = open(nstatefile, O_CREAT|O_WRONLY|O_EXCL, 0600)) == -1) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("open new state file: %s", nstatefile); goto done; } POKE_U32(buf, sshbuf_len(enc)); if (atomicio(vwrite, fd, buf, sizeof(buf)) != sizeof(buf)) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("write new state file hdr: %s", nstatefile); close(fd); goto done; } if (atomicio(vwrite, fd, sshbuf_mutable_ptr(enc), sshbuf_len(enc)) != sshbuf_len(enc)) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("write new state file data: %s", nstatefile); close(fd); goto done; } if (fsync(fd) == -1) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("sync new state file: %s", nstatefile); close(fd); goto done; } if (close(fd) == -1) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("close new state file: %s", nstatefile); goto done; } if (state->have_state) { unlink(ostatefile); if (link(statefile, ostatefile)) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("backup state %s to %s", statefile, ostatefile); goto done; } } if (rename(nstatefile, statefile) == -1) { ret = SSH_ERR_SYSTEM_ERROR; PRINT("rename %s to %s", nstatefile, statefile); goto done; } ret = 0; done: if (state->lockfd != -1) { close(state->lockfd); state->lockfd = -1; } if (nstatefile) unlink(nstatefile); free(statefile); free(ostatefile); free(nstatefile); sshbuf_free(b); sshbuf_free(enc); return ret; } int sshkey_xmss_serialize_state(const struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; treehash_inst *th; u_int32_t i, node; int r; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if (state->stack == NULL) return SSH_ERR_INVALID_ARGUMENT; state->stackoffset = state->bds.stackoffset; /* copy back */ if ((r = sshbuf_put_cstring(b, SSH_XMSS_K2_MAGIC)) != 0 || (r = sshbuf_put_u32(b, state->idx)) != 0 || (r = sshbuf_put_string(b, state->stack, num_stack(state))) != 0 || (r = sshbuf_put_u32(b, state->stackoffset)) != 0 || (r = sshbuf_put_string(b, state->stacklevels, num_stacklevels(state))) != 0 || (r = sshbuf_put_string(b, state->auth, num_auth(state))) != 0 || (r = sshbuf_put_string(b, state->keep, num_keep(state))) != 0 || (r = sshbuf_put_string(b, state->th_nodes, num_th_nodes(state))) != 0 || (r = sshbuf_put_string(b, state->retain, num_retain(state))) != 0 || (r = sshbuf_put_u32(b, num_treehash(state))) != 0) return r; for (i = 0; i < num_treehash(state); i++) { th = &state->treehash[i]; node = th->node - state->th_nodes; if ((r = sshbuf_put_u32(b, th->h)) != 0 || (r = sshbuf_put_u32(b, th->next_idx)) != 0 || (r = sshbuf_put_u32(b, th->stackusage)) != 0 || (r = sshbuf_put_u8(b, th->completed)) != 0 || (r = sshbuf_put_u32(b, node)) != 0) return r; } return 0; } int sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b, enum sshkey_serialize_rep opts) { struct ssh_xmss_state *state = k->xmss_state; int r = SSH_ERR_INVALID_ARGUMENT; u_char have_stack, have_filename, have_enc; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_put_u8(b, opts)) != 0) return r; switch (opts) { case SSHKEY_SERIALIZE_STATE: r = sshkey_xmss_serialize_state(k, b); break; case SSHKEY_SERIALIZE_FULL: if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0) return r; r = sshkey_xmss_serialize_state(k, b); break; case SSHKEY_SERIALIZE_SHIELD: /* all of stack/filename/enc are optional */ have_stack = state->stack != NULL; if ((r = sshbuf_put_u8(b, have_stack)) != 0) return r; if (have_stack) { state->idx = PEEK_U32(k->xmss_sk); /* update */ if ((r = sshkey_xmss_serialize_state(k, b)) != 0) return r; } have_filename = k->xmss_filename != NULL; if ((r = sshbuf_put_u8(b, have_filename)) != 0) return r; if (have_filename && (r = sshbuf_put_cstring(b, k->xmss_filename)) != 0) return r; have_enc = state->enc_keyiv != NULL; if ((r = sshbuf_put_u8(b, have_enc)) != 0) return r; if (have_enc && (r = sshkey_xmss_serialize_enc_key(k, b)) != 0) return r; if ((r = sshbuf_put_u32(b, state->maxidx)) != 0 || (r = sshbuf_put_u8(b, state->allow_update)) != 0) return r; break; case SSHKEY_SERIALIZE_DEFAULT: r = 0; break; default: r = SSH_ERR_INVALID_ARGUMENT; break; } return r; } int sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; treehash_inst *th; u_int32_t i, lh, node; size_t ls, lsl, la, lk, ln, lr; char *magic; int r = SSH_ERR_INTERNAL_ERROR; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if (k->xmss_sk == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((state->treehash = calloc(num_treehash(state), sizeof(treehash_inst))) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_cstring(b, &magic, NULL)) != 0 || (r = sshbuf_get_u32(b, &state->idx)) != 0 || (r = sshbuf_get_string(b, &state->stack, &ls)) != 0 || (r = sshbuf_get_u32(b, &state->stackoffset)) != 0 || (r = sshbuf_get_string(b, &state->stacklevels, &lsl)) != 0 || (r = sshbuf_get_string(b, &state->auth, &la)) != 0 || (r = sshbuf_get_string(b, &state->keep, &lk)) != 0 || (r = sshbuf_get_string(b, &state->th_nodes, &ln)) != 0 || (r = sshbuf_get_string(b, &state->retain, &lr)) != 0 || (r = sshbuf_get_u32(b, &lh)) != 0) goto out; if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } /* XXX check stackoffset */ if (ls != num_stack(state) || lsl != num_stacklevels(state) || la != num_auth(state) || lk != num_keep(state) || ln != num_th_nodes(state) || lr != num_retain(state) || lh != num_treehash(state)) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } for (i = 0; i < num_treehash(state); i++) { th = &state->treehash[i]; if ((r = sshbuf_get_u32(b, &th->h)) != 0 || (r = sshbuf_get_u32(b, &th->next_idx)) != 0 || (r = sshbuf_get_u32(b, &th->stackusage)) != 0 || (r = sshbuf_get_u8(b, &th->completed)) != 0 || (r = sshbuf_get_u32(b, &node)) != 0) goto out; if (node < num_th_nodes(state)) th->node = &state->th_nodes[node]; } POKE_U32(k->xmss_sk, state->idx); xmss_set_bds_state(&state->bds, state->stack, state->stackoffset, state->stacklevels, state->auth, state->keep, state->treehash, state->retain, 0); /* success */ r = 0; out: free(magic); return r; } int sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; enum sshkey_serialize_rep opts; u_char have_state, have_stack, have_filename, have_enc; int r; if ((r = sshbuf_get_u8(b, &have_state)) != 0) return r; opts = have_state; switch (opts) { case SSHKEY_SERIALIZE_DEFAULT: r = 0; break; case SSHKEY_SERIALIZE_SHIELD: if ((r = sshbuf_get_u8(b, &have_stack)) != 0) return r; if (have_stack && (r = sshkey_xmss_deserialize_state(k, b)) != 0) return r; if ((r = sshbuf_get_u8(b, &have_filename)) != 0) return r; if (have_filename && (r = sshbuf_get_cstring(b, &k->xmss_filename, NULL)) != 0) return r; if ((r = sshbuf_get_u8(b, &have_enc)) != 0) return r; if (have_enc && (r = sshkey_xmss_deserialize_enc_key(k, b)) != 0) return r; if ((r = sshbuf_get_u32(b, &state->maxidx)) != 0 || (r = sshbuf_get_u8(b, &state->allow_update)) != 0) return r; break; case SSHKEY_SERIALIZE_STATE: if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) return r; break; case SSHKEY_SERIALIZE_FULL: if ((r = sshkey_xmss_deserialize_enc_key(k, b)) != 0 || (r = sshkey_xmss_deserialize_state(k, b)) != 0) return r; break; default: r = SSH_ERR_INVALID_FORMAT; break; } return r; } int sshkey_xmss_encrypt_state(const struct sshkey *k, struct sshbuf *b, struct sshbuf **retp) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *encrypted = NULL, *encoded = NULL, *padded = NULL; struct sshcipher_ctx *ciphercontext = NULL; const struct sshcipher *cipher; u_char *cp, *key, *iv = NULL; size_t i, keylen, ivlen, blocksize, authlen, encrypted_len, aadlen; int r = SSH_ERR_INTERNAL_ERROR; if (retp != NULL) *retp = NULL; if (state == NULL || state->enc_keyiv == NULL || state->enc_ciphername == NULL) return SSH_ERR_INTERNAL_ERROR; if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } blocksize = cipher_blocksize(cipher); keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if (state->enc_keyiv_len != keylen + ivlen) { r = SSH_ERR_INVALID_FORMAT; goto out; } key = state->enc_keyiv; if ((encrypted = sshbuf_new()) == NULL || (encoded = sshbuf_new()) == NULL || (padded = sshbuf_new()) == NULL || (iv = malloc(ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* replace first 4 bytes of IV with index to ensure uniqueness */ memcpy(iv, key + keylen, ivlen); POKE_U32(iv, state->idx); if ((r = sshbuf_put(encoded, XMSS_MAGIC, sizeof(XMSS_MAGIC))) != 0 || (r = sshbuf_put_u32(encoded, state->idx)) != 0) goto out; /* padded state will be encrypted */ if ((r = sshbuf_putb(padded, b)) != 0) goto out; i = 0; while (sshbuf_len(padded) % blocksize) { if ((r = sshbuf_put_u8(padded, ++i & 0xff)) != 0) goto out; } encrypted_len = sshbuf_len(padded); /* header including the length of state is used as AAD */ if ((r = sshbuf_put_u32(encoded, encrypted_len)) != 0) goto out; aadlen = sshbuf_len(encoded); /* concat header and state */ if ((r = sshbuf_putb(encoded, padded)) != 0) goto out; /* reserve space for encryption of encoded data plus auth tag */ /* encrypt at offset addlen */ if ((r = sshbuf_reserve(encrypted, encrypted_len + aadlen + authlen, &cp)) != 0 || (r = cipher_init(&ciphercontext, cipher, key, keylen, iv, ivlen, 1)) != 0 || (r = cipher_crypt(ciphercontext, 0, cp, sshbuf_ptr(encoded), encrypted_len, aadlen, authlen)) != 0) goto out; /* success */ r = 0; out: if (retp != NULL) { *retp = encrypted; encrypted = NULL; } sshbuf_free(padded); sshbuf_free(encoded); sshbuf_free(encrypted); cipher_free(ciphercontext); free(iv); return r; } int sshkey_xmss_decrypt_state(const struct sshkey *k, struct sshbuf *encoded, struct sshbuf **retp) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *copy = NULL, *decrypted = NULL; struct sshcipher_ctx *ciphercontext = NULL; const struct sshcipher *cipher = NULL; u_char *key, *iv = NULL, *dp; size_t keylen, ivlen, authlen, aadlen; u_int blocksize, encrypted_len, index; int r = SSH_ERR_INTERNAL_ERROR; if (retp != NULL) *retp = NULL; if (state == NULL || state->enc_keyiv == NULL || state->enc_ciphername == NULL) return SSH_ERR_INTERNAL_ERROR; if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) { r = SSH_ERR_INVALID_FORMAT; goto out; } blocksize = cipher_blocksize(cipher); keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if (state->enc_keyiv_len != keylen + ivlen) { r = SSH_ERR_INTERNAL_ERROR; goto out; } key = state->enc_keyiv; if ((copy = sshbuf_fromb(encoded)) == NULL || (decrypted = sshbuf_new()) == NULL || (iv = malloc(ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* check magic */ if (sshbuf_len(encoded) < sizeof(XMSS_MAGIC) || memcmp(sshbuf_ptr(encoded), XMSS_MAGIC, sizeof(XMSS_MAGIC))) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* parse public portion */ if ((r = sshbuf_consume(encoded, sizeof(XMSS_MAGIC))) != 0 || (r = sshbuf_get_u32(encoded, &index)) != 0 || (r = sshbuf_get_u32(encoded, &encrypted_len)) != 0) goto out; /* check size of encrypted key blob */ if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* check that an appropriate amount of auth data is present */ if (sshbuf_len(encoded) < authlen || sshbuf_len(encoded) - authlen < encrypted_len) { r = SSH_ERR_INVALID_FORMAT; goto out; } aadlen = sshbuf_len(copy) - sshbuf_len(encoded); /* replace first 4 bytes of IV with index to ensure uniqueness */ memcpy(iv, key + keylen, ivlen); POKE_U32(iv, index); /* decrypt private state of key */ if ((r = sshbuf_reserve(decrypted, aadlen + encrypted_len, &dp)) != 0 || (r = cipher_init(&ciphercontext, cipher, key, keylen, iv, ivlen, 0)) != 0 || (r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(copy), encrypted_len, aadlen, authlen)) != 0) goto out; /* there should be no trailing data */ if ((r = sshbuf_consume(encoded, encrypted_len + authlen)) != 0) goto out; if (sshbuf_len(encoded) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* remove AAD */ if ((r = sshbuf_consume(decrypted, aadlen)) != 0) goto out; /* XXX encrypted includes unchecked padding */ /* success */ r = 0; if (retp != NULL) { *retp = decrypted; decrypted = NULL; } out: cipher_free(ciphercontext); sshbuf_free(copy); sshbuf_free(decrypted); free(iv); return r; } u_int32_t sshkey_xmss_signatures_left(const struct sshkey *k) { struct ssh_xmss_state *state = k->xmss_state; u_int32_t idx; if (sshkey_type_plain(k->type) == KEY_XMSS && state && state->maxidx) { idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx; if (idx < state->maxidx) return state->maxidx - idx; } return 0; } int sshkey_xmss_enable_maxsign(struct sshkey *k, u_int32_t maxsign) { struct ssh_xmss_state *state = k->xmss_state; if (sshkey_type_plain(k->type) != KEY_XMSS) return SSH_ERR_INVALID_ARGUMENT; if (maxsign == 0) return 0; if (state->idx + maxsign < state->idx) return SSH_ERR_INVALID_ARGUMENT; state->maxidx = state->idx + maxsign; return 0; } #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/sshkey-xmss.h100644 001750 001750 0000000003514775415623 0015622xustar0029 atime=1744182234.87580493 openssh-10.0p1/sshkey-xmss.h010064400017500001750000000055511477541562300142140ustar00djmdjm/* $OpenBSD: sshkey-xmss.h,v 1.4 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SSHKEY_XMSS_H #define SSHKEY_XMSS_H #define XMSS_SHA2_256_W16_H10_NAME "XMSS_SHA2-256_W16_H10" #define XMSS_SHA2_256_W16_H16_NAME "XMSS_SHA2-256_W16_H16" #define XMSS_SHA2_256_W16_H20_NAME "XMSS_SHA2-256_W16_H20" #define XMSS_DEFAULT_NAME XMSS_SHA2_256_W16_H10_NAME size_t sshkey_xmss_pklen(const struct sshkey *); size_t sshkey_xmss_sklen(const struct sshkey *); int sshkey_xmss_init(struct sshkey *, const char *); void sshkey_xmss_free_state(struct sshkey *); int sshkey_xmss_generate_private_key(struct sshkey *, int); int sshkey_xmss_serialize_state(const struct sshkey *, struct sshbuf *); int sshkey_xmss_serialize_state_opt(const struct sshkey *, struct sshbuf *, enum sshkey_serialize_rep); int sshkey_xmss_serialize_pk_info(const struct sshkey *, struct sshbuf *, enum sshkey_serialize_rep); int sshkey_xmss_deserialize_state(struct sshkey *, struct sshbuf *); int sshkey_xmss_deserialize_state_opt(struct sshkey *, struct sshbuf *); int sshkey_xmss_deserialize_pk_info(struct sshkey *, struct sshbuf *); int sshkey_xmss_siglen(const struct sshkey *, size_t *); void *sshkey_xmss_params(const struct sshkey *); void *sshkey_xmss_bds_state(const struct sshkey *); int sshkey_xmss_get_state(const struct sshkey *, int); int sshkey_xmss_enable_maxsign(struct sshkey *, u_int32_t); int sshkey_xmss_forward_state(const struct sshkey *, u_int32_t); int sshkey_xmss_update_state(const struct sshkey *, int); u_int32_t sshkey_xmss_signatures_left(const struct sshkey *); #endif /* SSHKEY_XMSS_H */ openssh-10.0p1/PaxHeaders.10889/sshkey.c100644 001750 001750 0000000003614775415623 0014626xustar0030 atime=1744182234.889476289 openssh-10.0p1/sshkey.c010064400017500001750000002717621477541562300132300ustar00djmdjm/* $OpenBSD: sshkey.c,v 1.148 2024/12/03 15:53:51 tb Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. * Copyright (c) 2010,2011 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #ifdef WITH_OPENSSL #include #include #include #endif #include "crypto_api.h" #include #include #include #include #include #include #include #ifdef HAVE_UTIL_H #include #endif /* HAVE_UTIL_H */ #include "ssh2.h" #include "ssherr.h" #include "misc.h" #include "sshbuf.h" #include "cipher.h" #include "digest.h" #define SSHKEY_INTERNAL #include "sshkey.h" #include "match.h" #include "ssh-sk.h" #ifdef WITH_XMSS #include "sshkey-xmss.h" #include "xmss_fast.h" #endif #include "openbsd-compat/openssl-compat.h" /* openssh private key file format */ #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1) #define MARK_END_LEN (sizeof(MARK_END) - 1) #define KDFNAME "bcrypt" #define AUTH_MAGIC "openssh-key-v1" #define SALT_LEN 16 #define DEFAULT_CIPHERNAME "aes256-ctr" #define DEFAULT_ROUNDS 24 /* * Constants relating to "shielding" support; protection of keys expected * to remain in memory for long durations */ #define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024) #define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */ #define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512 int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep); static int sshkey_from_blob_internal(struct sshbuf *buf, struct sshkey **keyp, int allow_cert); /* Supported key types */ extern const struct sshkey_impl sshkey_ed25519_impl; extern const struct sshkey_impl sshkey_ed25519_cert_impl; extern const struct sshkey_impl sshkey_ed25519_sk_impl; extern const struct sshkey_impl sshkey_ed25519_sk_cert_impl; #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC # ifdef ENABLE_SK extern const struct sshkey_impl sshkey_ecdsa_sk_impl; extern const struct sshkey_impl sshkey_ecdsa_sk_cert_impl; extern const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl; # endif /* ENABLE_SK */ extern const struct sshkey_impl sshkey_ecdsa_nistp256_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp384_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl; # ifdef OPENSSL_HAS_NISTP521 extern const struct sshkey_impl sshkey_ecdsa_nistp521_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl; # endif /* OPENSSL_HAS_NISTP521 */ # endif /* OPENSSL_HAS_ECC */ extern const struct sshkey_impl sshkey_rsa_impl; extern const struct sshkey_impl sshkey_rsa_cert_impl; extern const struct sshkey_impl sshkey_rsa_sha256_impl; extern const struct sshkey_impl sshkey_rsa_sha256_cert_impl; extern const struct sshkey_impl sshkey_rsa_sha512_impl; extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl; # ifdef WITH_DSA extern const struct sshkey_impl sshkey_dss_impl; extern const struct sshkey_impl sshkey_dsa_cert_impl; # endif #endif /* WITH_OPENSSL */ #ifdef WITH_XMSS extern const struct sshkey_impl sshkey_xmss_impl; extern const struct sshkey_impl sshkey_xmss_cert_impl; #endif const struct sshkey_impl * const keyimpls[] = { &sshkey_ed25519_impl, &sshkey_ed25519_cert_impl, #ifdef ENABLE_SK &sshkey_ed25519_sk_impl, &sshkey_ed25519_sk_cert_impl, #endif #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC &sshkey_ecdsa_nistp256_impl, &sshkey_ecdsa_nistp256_cert_impl, &sshkey_ecdsa_nistp384_impl, &sshkey_ecdsa_nistp384_cert_impl, # ifdef OPENSSL_HAS_NISTP521 &sshkey_ecdsa_nistp521_impl, &sshkey_ecdsa_nistp521_cert_impl, # endif /* OPENSSL_HAS_NISTP521 */ # ifdef ENABLE_SK &sshkey_ecdsa_sk_impl, &sshkey_ecdsa_sk_cert_impl, &sshkey_ecdsa_sk_webauthn_impl, # endif /* ENABLE_SK */ # endif /* OPENSSL_HAS_ECC */ # ifdef WITH_DSA &sshkey_dss_impl, &sshkey_dsa_cert_impl, # endif &sshkey_rsa_impl, &sshkey_rsa_cert_impl, &sshkey_rsa_sha256_impl, &sshkey_rsa_sha256_cert_impl, &sshkey_rsa_sha512_impl, &sshkey_rsa_sha512_cert_impl, #endif /* WITH_OPENSSL */ #ifdef WITH_XMSS &sshkey_xmss_impl, &sshkey_xmss_cert_impl, #endif NULL }; static const struct sshkey_impl * sshkey_impl_from_type(int type) { int i; for (i = 0; keyimpls[i] != NULL; i++) { if (keyimpls[i]->type == type) return keyimpls[i]; } return NULL; } static const struct sshkey_impl * sshkey_impl_from_type_nid(int type, int nid) { int i; for (i = 0; keyimpls[i] != NULL; i++) { if (keyimpls[i]->type == type && (keyimpls[i]->nid == 0 || keyimpls[i]->nid == nid)) return keyimpls[i]; } return NULL; } static const struct sshkey_impl * sshkey_impl_from_key(const struct sshkey *k) { if (k == NULL) return NULL; return sshkey_impl_from_type_nid(k->type, k->ecdsa_nid); } const char * sshkey_type(const struct sshkey *k) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_key(k)) == NULL) return "unknown"; return impl->shortname; } static const char * sshkey_ssh_name_from_type_nid(int type, int nid) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_type_nid(type, nid)) == NULL) return "ssh-unknown"; return impl->name; } int sshkey_type_is_cert(int type) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_type(type)) == NULL) return 0; return impl->cert; } const char * sshkey_ssh_name(const struct sshkey *k) { return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid); } const char * sshkey_ssh_name_plain(const struct sshkey *k) { return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type), k->ecdsa_nid); } static int type_from_name(const char *name, int allow_short) { int i; const struct sshkey_impl *impl; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; if (impl->name != NULL && strcmp(name, impl->name) == 0) return impl->type; /* Only allow shortname matches for plain key types */ if (allow_short && !impl->cert && impl->shortname != NULL && strcasecmp(impl->shortname, name) == 0) return impl->type; } return KEY_UNSPEC; } int sshkey_type_from_name(const char *name) { return type_from_name(name, 0); } int sshkey_type_from_shortname(const char *name) { return type_from_name(name, 1); } static int key_type_is_ecdsa_variant(int type) { switch (type) { case KEY_ECDSA: case KEY_ECDSA_CERT: case KEY_ECDSA_SK: case KEY_ECDSA_SK_CERT: return 1; } return 0; } int sshkey_ecdsa_nid_from_name(const char *name) { int i; for (i = 0; keyimpls[i] != NULL; i++) { if (!key_type_is_ecdsa_variant(keyimpls[i]->type)) continue; if (keyimpls[i]->name != NULL && strcmp(name, keyimpls[i]->name) == 0) return keyimpls[i]->nid; } return -1; } int sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs) { int ktype; if (sigalgs == NULL || *sigalgs == '\0' || (ktype = sshkey_type_from_name(keyname)) == KEY_UNSPEC) return 0; else if (ktype == KEY_RSA) { return match_pattern_list("ssh-rsa", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-256", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-512", sigalgs, 0) == 1; } else if (ktype == KEY_RSA_CERT) { return match_pattern_list("ssh-rsa-cert-v01@openssh.com", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", sigalgs, 0) == 1; } else return match_pattern_list(keyname, sigalgs, 0) == 1; } char * sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) { char *tmp, *ret = NULL; size_t i, nlen, rlen = 0; const struct sshkey_impl *impl; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; if (impl->name == NULL) continue; if (!include_sigonly && impl->sigonly) continue; if ((certs_only && !impl->cert) || (plain_only && impl->cert)) continue; if (ret != NULL) ret[rlen++] = sep; nlen = strlen(impl->name); if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { free(ret); return NULL; } ret = tmp; memcpy(ret + rlen, impl->name, nlen + 1); rlen += nlen; } return ret; } int sshkey_names_valid2(const char *names, int allow_wildcard, int plain_only) { char *s, *cp, *p; const struct sshkey_impl *impl; int i, type; if (names == NULL || strcmp(names, "") == 0) return 0; if ((s = cp = strdup(names)) == NULL) return 0; for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { type = sshkey_type_from_name(p); if (type == KEY_UNSPEC) { if (allow_wildcard) { /* * Try matching key types against the string. * If any has a positive or negative match then * the component is accepted. */ impl = NULL; for (i = 0; keyimpls[i] != NULL; i++) { if (match_pattern_list( keyimpls[i]->name, p, 0) != 0) { impl = keyimpls[i]; break; } } if (impl != NULL) continue; } free(s); return 0; } else if (plain_only && sshkey_type_is_cert(type)) { free(s); return 0; } } free(s); return 1; } u_int sshkey_size(const struct sshkey *k) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_key(k)) == NULL) return 0; if (impl->funcs->size != NULL) return impl->funcs->size(k); return impl->keybits; } static int sshkey_type_is_valid_ca(int type) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_type(type)) == NULL) return 0; /* All non-certificate types may act as CAs */ return !impl->cert; } int sshkey_is_cert(const struct sshkey *k) { if (k == NULL) return 0; return sshkey_type_is_cert(k->type); } int sshkey_is_sk(const struct sshkey *k) { if (k == NULL) return 0; switch (sshkey_type_plain(k->type)) { case KEY_ECDSA_SK: case KEY_ED25519_SK: return 1; default: return 0; } } /* Return the cert-less equivalent to a certified key type */ int sshkey_type_plain(int type) { switch (type) { case KEY_RSA_CERT: return KEY_RSA; case KEY_DSA_CERT: return KEY_DSA; case KEY_ECDSA_CERT: return KEY_ECDSA; case KEY_ECDSA_SK_CERT: return KEY_ECDSA_SK; case KEY_ED25519_CERT: return KEY_ED25519; case KEY_ED25519_SK_CERT: return KEY_ED25519_SK; case KEY_XMSS_CERT: return KEY_XMSS; default: return type; } } /* Return the cert equivalent to a plain key type */ static int sshkey_type_certified(int type) { switch (type) { case KEY_RSA: return KEY_RSA_CERT; case KEY_DSA: return KEY_DSA_CERT; case KEY_ECDSA: return KEY_ECDSA_CERT; case KEY_ECDSA_SK: return KEY_ECDSA_SK_CERT; case KEY_ED25519: return KEY_ED25519_CERT; case KEY_ED25519_SK: return KEY_ED25519_SK_CERT; case KEY_XMSS: return KEY_XMSS_CERT; default: return -1; } } #ifdef WITH_OPENSSL static const EVP_MD * ssh_digest_to_md(int hash_alg) { switch (hash_alg) { case SSH_DIGEST_SHA1: return EVP_sha1(); case SSH_DIGEST_SHA256: return EVP_sha256(); case SSH_DIGEST_SHA384: return EVP_sha384(); case SSH_DIGEST_SHA512: return EVP_sha512(); } return NULL; } int sshkey_pkey_digest_sign(EVP_PKEY *pkey, int hash_alg, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen) { EVP_MD_CTX *ctx = NULL; u_char *sig = NULL; int ret; size_t slen; const EVP_MD *evpmd; *sigp = NULL; *lenp = 0; slen = EVP_PKEY_size(pkey); if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM || (evpmd = ssh_digest_to_md(hash_alg)) == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((sig = malloc(slen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((ctx = EVP_MD_CTX_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (EVP_DigestSignInit(ctx, NULL, evpmd, NULL, pkey) != 1 || EVP_DigestSign(ctx, sig, &slen, data, datalen) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } *sigp = sig; *lenp = slen; /* Now owned by the caller */ sig = NULL; ret = 0; out: EVP_MD_CTX_free(ctx); free(sig); return ret; } int sshkey_pkey_digest_verify(EVP_PKEY *pkey, int hash_alg, const u_char *data, size_t datalen, u_char *sigbuf, size_t siglen) { EVP_MD_CTX *ctx = NULL; int ret = SSH_ERR_INTERNAL_ERROR; const EVP_MD *evpmd; if ((evpmd = ssh_digest_to_md(hash_alg)) == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((ctx = EVP_MD_CTX_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if (EVP_DigestVerifyInit(ctx, NULL, evpmd, NULL, pkey) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } switch (EVP_DigestVerify(ctx, sigbuf, siglen, data, datalen)) { case 1: ret = 0; break; case 0: ret = SSH_ERR_SIGNATURE_INVALID; break; default: ret = SSH_ERR_LIBCRYPTO_ERROR; break; } out: EVP_MD_CTX_free(ctx); return ret; } /* XXX: these are really begging for a table-driven approach */ int sshkey_curve_name_to_nid(const char *name) { if (strcmp(name, "nistp256") == 0) return NID_X9_62_prime256v1; else if (strcmp(name, "nistp384") == 0) return NID_secp384r1; # ifdef OPENSSL_HAS_NISTP521 else if (strcmp(name, "nistp521") == 0) return NID_secp521r1; # endif /* OPENSSL_HAS_NISTP521 */ else return -1; } u_int sshkey_curve_nid_to_bits(int nid) { switch (nid) { case NID_X9_62_prime256v1: return 256; case NID_secp384r1: return 384; # ifdef OPENSSL_HAS_NISTP521 case NID_secp521r1: return 521; # endif /* OPENSSL_HAS_NISTP521 */ default: return 0; } } int sshkey_ecdsa_bits_to_nid(int bits) { switch (bits) { case 256: return NID_X9_62_prime256v1; case 384: return NID_secp384r1; # ifdef OPENSSL_HAS_NISTP521 case 521: return NID_secp521r1; # endif /* OPENSSL_HAS_NISTP521 */ default: return -1; } } const char * sshkey_curve_nid_to_name(int nid) { switch (nid) { case NID_X9_62_prime256v1: return "nistp256"; case NID_secp384r1: return "nistp384"; # ifdef OPENSSL_HAS_NISTP521 case NID_secp521r1: return "nistp521"; # endif /* OPENSSL_HAS_NISTP521 */ default: return NULL; } } int sshkey_ec_nid_to_hash_alg(int nid) { int kbits = sshkey_curve_nid_to_bits(nid); if (kbits <= 0) return -1; /* RFC5656 section 6.2.1 */ if (kbits <= 256) return SSH_DIGEST_SHA256; else if (kbits <= 384) return SSH_DIGEST_SHA384; else return SSH_DIGEST_SHA512; } #endif /* WITH_OPENSSL */ static void cert_free(struct sshkey_cert *cert) { u_int i; if (cert == NULL) return; sshbuf_free(cert->certblob); sshbuf_free(cert->critical); sshbuf_free(cert->extensions); free(cert->key_id); for (i = 0; i < cert->nprincipals; i++) free(cert->principals[i]); free(cert->principals); sshkey_free(cert->signature_key); free(cert->signature_type); freezero(cert, sizeof(*cert)); } static struct sshkey_cert * cert_new(void) { struct sshkey_cert *cert; if ((cert = calloc(1, sizeof(*cert))) == NULL) return NULL; if ((cert->certblob = sshbuf_new()) == NULL || (cert->critical = sshbuf_new()) == NULL || (cert->extensions = sshbuf_new()) == NULL) { cert_free(cert); return NULL; } cert->key_id = NULL; cert->principals = NULL; cert->signature_key = NULL; cert->signature_type = NULL; return cert; } struct sshkey * sshkey_new(int type) { struct sshkey *k; const struct sshkey_impl *impl = NULL; if (type != KEY_UNSPEC && (impl = sshkey_impl_from_type(type)) == NULL) return NULL; /* All non-certificate types may act as CAs */ if ((k = calloc(1, sizeof(*k))) == NULL) return NULL; k->type = type; k->ecdsa_nid = -1; if (impl != NULL && impl->funcs->alloc != NULL) { if (impl->funcs->alloc(k) != 0) { free(k); return NULL; } } if (sshkey_is_cert(k)) { if ((k->cert = cert_new()) == NULL) { sshkey_free(k); return NULL; } } return k; } /* Frees common FIDO fields */ void sshkey_sk_cleanup(struct sshkey *k) { free(k->sk_application); sshbuf_free(k->sk_key_handle); sshbuf_free(k->sk_reserved); k->sk_application = NULL; k->sk_key_handle = k->sk_reserved = NULL; } #if defined(MAP_CONCEAL) # define PREKEY_MMAP_FLAG MAP_CONCEAL #elif defined(MAP_NOCORE) # define PREKEY_MMAP_FLAG MAP_NOCORE #else # define PREKEY_MMAP_FLAG 0 #endif static int sshkey_prekey_alloc(u_char **prekeyp, size_t len) { u_char *prekey; *prekeyp = NULL; if ((prekey = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|PREKEY_MMAP_FLAG, -1, 0)) == MAP_FAILED) return SSH_ERR_SYSTEM_ERROR; #if defined(MADV_DONTDUMP) && !defined(MAP_CONCEAL) && !defined(MAP_NOCORE) (void)madvise(prekey, len, MADV_DONTDUMP); #endif *prekeyp = prekey; return 0; } static void sshkey_prekey_free(void *prekey, size_t len) { if (prekey == NULL) return; munmap(prekey, len); } static void sshkey_free_contents(struct sshkey *k) { const struct sshkey_impl *impl; if (k == NULL) return; if ((impl = sshkey_impl_from_type(k->type)) != NULL && impl->funcs->cleanup != NULL) impl->funcs->cleanup(k); if (sshkey_is_cert(k)) cert_free(k->cert); freezero(k->shielded_private, k->shielded_len); sshkey_prekey_free(k->shield_prekey, k->shield_prekey_len); } void sshkey_free(struct sshkey *k) { sshkey_free_contents(k); freezero(k, sizeof(*k)); } static int cert_compare(struct sshkey_cert *a, struct sshkey_cert *b) { if (a == NULL && b == NULL) return 1; if (a == NULL || b == NULL) return 0; if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob)) return 0; if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob), sshbuf_len(a->certblob)) != 0) return 0; return 1; } /* Compares FIDO-specific pubkey fields only */ int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b) { if (a->sk_application == NULL || b->sk_application == NULL) return 0; if (strcmp(a->sk_application, b->sk_application) != 0) return 0; return 1; } /* * Compare public portions of key only, allowing comparisons between * certificates and plain keys too. */ int sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) { const struct sshkey_impl *impl; if (a == NULL || b == NULL || sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) return 0; if ((impl = sshkey_impl_from_type(a->type)) == NULL) return 0; return impl->funcs->equal(a, b); } int sshkey_equal(const struct sshkey *a, const struct sshkey *b) { if (a == NULL || b == NULL || a->type != b->type) return 0; if (sshkey_is_cert(a)) { if (!cert_compare(a->cert, b->cert)) return 0; } return sshkey_equal_public(a, b); } /* Serialise common FIDO key parts */ int sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b) { int r; if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0) return r; return 0; } static int to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, enum sshkey_serialize_rep opts) { int type, ret = SSH_ERR_INTERNAL_ERROR; const char *typename; const struct sshkey_impl *impl; if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; type = force_plain ? sshkey_type_plain(key->type) : key->type; if (sshkey_type_is_cert(type)) { if (key->cert == NULL) return SSH_ERR_EXPECTED_CERT; if (sshbuf_len(key->cert->certblob) == 0) return SSH_ERR_KEY_LACKS_CERTBLOB; /* Use the existing blob */ if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0) return ret; return 0; } if ((impl = sshkey_impl_from_type(type)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); if ((ret = sshbuf_put_cstring(b, typename)) != 0) return ret; return impl->funcs->serialize_public(key, b, opts); } int sshkey_putb(const struct sshkey *key, struct sshbuf *b) { return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { struct sshbuf *tmp; int r; if ((tmp = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; r = to_blob_buf(key, tmp, 0, opts); if (r == 0) r = sshbuf_put_stringb(b, tmp); sshbuf_free(tmp); return r; } int sshkey_puts(const struct sshkey *key, struct sshbuf *b) { return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b) { return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT); } static int to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain, enum sshkey_serialize_rep opts) { int ret = SSH_ERR_INTERNAL_ERROR; size_t len; struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; if (blobp != NULL) *blobp = NULL; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0) goto out; len = sshbuf_len(b); if (lenp != NULL) *lenp = len; if (blobp != NULL) { if ((*blobp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*blobp, sshbuf_ptr(b), len); } ret = 0; out: sshbuf_free(b); return ret; } int sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) { return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) { return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, u_char **retp, size_t *lenp) { u_char *blob = NULL, *ret = NULL; size_t blob_len = 0; int r = SSH_ERR_INTERNAL_ERROR; if (retp != NULL) *retp = NULL; if (lenp != NULL) *lenp = 0; if (ssh_digest_bytes(dgst_alg) == 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT)) != 0) goto out; if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = ssh_digest_memory(dgst_alg, blob, blob_len, ret, SSH_DIGEST_MAX_LENGTH)) != 0) goto out; /* success */ if (retp != NULL) { *retp = ret; ret = NULL; } if (lenp != NULL) *lenp = ssh_digest_bytes(dgst_alg); r = 0; out: free(ret); if (blob != NULL) freezero(blob, blob_len); return r; } static char * fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) { char *ret; size_t plen = strlen(alg) + 1; size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1; if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL) return NULL; strlcpy(ret, alg, rlen); strlcat(ret, ":", rlen); if (dgst_raw_len == 0) return ret; if (b64_ntop(dgst_raw, dgst_raw_len, ret + plen, rlen - plen) == -1) { freezero(ret, rlen); return NULL; } /* Trim padding characters from end */ ret[strcspn(ret, "=")] = '\0'; return ret; } static char * fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) { char *retval, hex[5]; size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2; if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL) return NULL; strlcpy(retval, alg, rlen); strlcat(retval, ":", rlen); for (i = 0; i < dgst_raw_len; i++) { snprintf(hex, sizeof(hex), "%s%02x", i > 0 ? ":" : "", dgst_raw[i]); strlcat(retval, hex, rlen); } return retval; } static char * fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len) { char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; u_int i, j = 0, rounds, seed = 1; char *retval; rounds = (dgst_raw_len / 2) + 1; if ((retval = calloc(rounds, 6)) == NULL) return NULL; retval[j++] = 'x'; for (i = 0; i < rounds; i++) { u_int idx0, idx1, idx2, idx3, idx4; if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + seed) % 6; idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + (seed / 6)) % 6; retval[j++] = vowels[idx0]; retval[j++] = consonants[idx1]; retval[j++] = vowels[idx2]; if ((i + 1) < rounds) { idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; retval[j++] = consonants[idx3]; retval[j++] = '-'; retval[j++] = consonants[idx4]; seed = ((seed * 5) + ((((u_int)(dgst_raw[2 * i])) * 7) + ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; } } else { idx0 = seed % 6; idx1 = 16; idx2 = seed / 6; retval[j++] = vowels[idx0]; retval[j++] = consonants[idx1]; retval[j++] = vowels[idx2]; } } retval[j++] = 'x'; retval[j++] = '\0'; return retval; } /* * Draw an ASCII-Art representing the fingerprint so human brain can * profit from its built-in pattern recognition ability. * This technique is called "random art" and can be found in some * scientific publications like this original paper: * * "Hash Visualization: a New Technique to improve Real-World Security", * Perrig A. and Song D., 1999, International Workshop on Cryptographic * Techniques and E-Commerce (CrypTEC '99) * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf * * The subject came up in a talk by Dan Kaminsky, too. * * If you see the picture is different, the key is different. * If the picture looks the same, you still know nothing. * * The algorithm used here is a worm crawling over a discrete plane, * leaving a trace (augmenting the field) everywhere it goes. * Movement is taken from dgst_raw 2bit-wise. Bumping into walls * makes the respective movement vector be ignored for this turn. * Graphs are not unambiguous, because circles in graphs can be * walked in either direction. */ /* * Field sizes for the random art. Have to be odd, so the starting point * can be in the exact middle of the picture, and FLDBASE should be >=8 . * Else pictures would be too dense, and drawing the frame would * fail, too, because the key type would not fit in anymore. */ #define FLDBASE 8 #define FLDSIZE_Y (FLDBASE + 1) #define FLDSIZE_X (FLDBASE * 2 + 1) static char * fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len, const struct sshkey *k) { /* * Chars to be used after each other every time the worm * intersects with itself. Matter of taste. */ char *augmentation_string = " .o+=*BOX@%&#/^SE"; char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X]; u_char field[FLDSIZE_X][FLDSIZE_Y]; size_t i, tlen, hlen; u_int b; int x, y, r; size_t len = strlen(augmentation_string) - 1; if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL) return NULL; /* initialize field */ memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); x = FLDSIZE_X / 2; y = FLDSIZE_Y / 2; /* process raw key */ for (i = 0; i < dgst_raw_len; i++) { int input; /* each byte conveys four 2-bit move commands */ input = dgst_raw[i]; for (b = 0; b < 4; b++) { /* evaluate 2 bit, rest is shifted later */ x += (input & 0x1) ? 1 : -1; y += (input & 0x2) ? 1 : -1; /* assure we are still in bounds */ x = MAXIMUM(x, 0); y = MAXIMUM(y, 0); x = MINIMUM(x, FLDSIZE_X - 1); y = MINIMUM(y, FLDSIZE_Y - 1); /* augment the field */ if (field[x][y] < len - 2) field[x][y]++; input = input >> 2; } } /* mark starting point and end point*/ field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; field[x][y] = len; /* assemble title */ r = snprintf(title, sizeof(title), "[%s %u]", sshkey_type(k), sshkey_size(k)); /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ if (r < 0 || r > (int)sizeof(title)) r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); tlen = (r <= 0) ? 0 : strlen(title); /* assemble hash ID. */ r = snprintf(hash, sizeof(hash), "[%s]", alg); hlen = (r <= 0) ? 0 : strlen(hash); /* output upper border */ p = retval; *p++ = '+'; for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++) *p++ = '-'; memcpy(p, title, tlen); p += tlen; for (i += tlen; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; *p++ = '\n'; /* output content */ for (y = 0; y < FLDSIZE_Y; y++) { *p++ = '|'; for (x = 0; x < FLDSIZE_X; x++) *p++ = augmentation_string[MINIMUM(field[x][y], len)]; *p++ = '|'; *p++ = '\n'; } /* output lower border */ *p++ = '+'; for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++) *p++ = '-'; memcpy(p, hash, hlen); p += hlen; for (i += hlen; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; return retval; } char * sshkey_fingerprint(const struct sshkey *k, int dgst_alg, enum sshkey_fp_rep dgst_rep) { char *retval = NULL; u_char *dgst_raw; size_t dgst_raw_len; if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0) return NULL; switch (dgst_rep) { case SSH_FP_DEFAULT: if (dgst_alg == SSH_DIGEST_MD5) { retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); } else { retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); } break; case SSH_FP_HEX: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); break; case SSH_FP_BASE64: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); break; case SSH_FP_BUBBLEBABBLE: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); break; case SSH_FP_RANDOMART: retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len, k); break; default: freezero(dgst_raw, dgst_raw_len); return NULL; } freezero(dgst_raw, dgst_raw_len); return retval; } static int peek_type_nid(const char *s, size_t l, int *nid) { const struct sshkey_impl *impl; int i; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; if (impl->name == NULL || strlen(impl->name) != l) continue; if (memcmp(s, impl->name, l) == 0) { *nid = -1; if (key_type_is_ecdsa_variant(impl->type)) *nid = impl->nid; return impl->type; } } return KEY_UNSPEC; } /* XXX this can now be made const char * */ int sshkey_read(struct sshkey *ret, char **cpp) { struct sshkey *k; char *cp, *blobcopy; size_t space; int r, type, curve_nid = -1; struct sshbuf *blob; if (ret == NULL) return SSH_ERR_INVALID_ARGUMENT; if (ret->type != KEY_UNSPEC && sshkey_impl_from_type(ret->type) == NULL) return SSH_ERR_INVALID_ARGUMENT; /* Decode type */ cp = *cpp; space = strcspn(cp, " \t"); if (space == strlen(cp)) return SSH_ERR_INVALID_FORMAT; if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC) return SSH_ERR_INVALID_FORMAT; /* skip whitespace */ for (cp += space; *cp == ' ' || *cp == '\t'; cp++) ; if (*cp == '\0') return SSH_ERR_INVALID_FORMAT; if (ret->type != KEY_UNSPEC && ret->type != type) return SSH_ERR_KEY_TYPE_MISMATCH; if ((blob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* find end of keyblob and decode */ space = strcspn(cp, " \t"); if ((blobcopy = strndup(cp, space)) == NULL) { sshbuf_free(blob); return SSH_ERR_ALLOC_FAIL; } if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) { free(blobcopy); sshbuf_free(blob); return r; } free(blobcopy); if ((r = sshkey_fromb(blob, &k)) != 0) { sshbuf_free(blob); return r; } sshbuf_free(blob); /* skip whitespace and leave cp at start of comment */ for (cp += space; *cp == ' ' || *cp == '\t'; cp++) ; /* ensure type of blob matches type at start of line */ if (k->type != type) { sshkey_free(k); return SSH_ERR_KEY_TYPE_MISMATCH; } if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) { sshkey_free(k); return SSH_ERR_EC_CURVE_MISMATCH; } /* Fill in ret from parsed key */ sshkey_free_contents(ret); *ret = *k; freezero(k, sizeof(*k)); /* success */ *cpp = cp; return 0; } int sshkey_to_base64(const struct sshkey *key, char **b64p) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; char *uu = NULL; if (b64p != NULL) *b64p = NULL; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_putb(key, b)) != 0) goto out; if ((uu = sshbuf_dtob64_string(b, 0)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* Success */ if (b64p != NULL) { *b64p = uu; uu = NULL; } r = 0; out: sshbuf_free(b); free(uu); return r; } int sshkey_format_text(const struct sshkey *key, struct sshbuf *b) { int r = SSH_ERR_INTERNAL_ERROR; char *uu = NULL; if ((r = sshkey_to_base64(key, &uu)) != 0) goto out; if ((r = sshbuf_putf(b, "%s %s", sshkey_ssh_name(key), uu)) != 0) goto out; r = 0; out: free(uu); return r; } int sshkey_write(const struct sshkey *key, FILE *f) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_format_text(key, b)) != 0) goto out; if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) { if (feof(f)) errno = EPIPE; r = SSH_ERR_SYSTEM_ERROR; goto out; } /* Success */ r = 0; out: sshbuf_free(b); return r; } const char * sshkey_cert_type(const struct sshkey *k) { switch (k->cert->type) { case SSH2_CERT_TYPE_USER: return "user"; case SSH2_CERT_TYPE_HOST: return "host"; default: return "unknown"; } } int sshkey_check_rsa_length(const struct sshkey *k, int min_size) { #ifdef WITH_OPENSSL int nbits; if (k == NULL || k->pkey == NULL || (k->type != KEY_RSA && k->type != KEY_RSA_CERT)) return 0; nbits = EVP_PKEY_bits(k->pkey); if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE || (min_size > 0 && nbits < min_size)) return SSH_ERR_KEY_LENGTH; #endif /* WITH_OPENSSL */ return 0; } #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) int sshkey_ecdsa_key_to_nid(const EC_KEY *k) { const EC_GROUP *g; int nid; if (k == NULL || (g = EC_KEY_get0_group(k)) == NULL) return -1; if ((nid = EC_GROUP_get_curve_name(g)) <= 0) return -1; return nid; } int sshkey_ecdsa_pkey_to_nid(EVP_PKEY *pkey) { return sshkey_ecdsa_key_to_nid(EVP_PKEY_get0_EC_KEY(pkey)); } #endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ int sshkey_generate(int type, u_int bits, struct sshkey **keyp) { struct sshkey *k; int ret = SSH_ERR_INTERNAL_ERROR; const struct sshkey_impl *impl; if (keyp == NULL || sshkey_type_is_cert(type)) return SSH_ERR_INVALID_ARGUMENT; *keyp = NULL; if ((impl = sshkey_impl_from_type(type)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if (impl->funcs->generate == NULL) return SSH_ERR_FEATURE_UNSUPPORTED; if ((k = sshkey_new(KEY_UNSPEC)) == NULL) return SSH_ERR_ALLOC_FAIL; k->type = type; if ((ret = impl->funcs->generate(k, bits)) != 0) { sshkey_free(k); return ret; } /* success */ *keyp = k; return 0; } int sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) { u_int i; const struct sshkey_cert *from; struct sshkey_cert *to; int r = SSH_ERR_INTERNAL_ERROR; if (to_key == NULL || (from = from_key->cert) == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((to = cert_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 || (r = sshbuf_putb(to->critical, from->critical)) != 0 || (r = sshbuf_putb(to->extensions, from->extensions)) != 0) goto out; to->serial = from->serial; to->type = from->type; if (from->key_id == NULL) to->key_id = NULL; else if ((to->key_id = strdup(from->key_id)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } to->valid_after = from->valid_after; to->valid_before = from->valid_before; if (from->signature_key == NULL) to->signature_key = NULL; else if ((r = sshkey_from_private(from->signature_key, &to->signature_key)) != 0) goto out; if (from->signature_type != NULL && (to->signature_type = strdup(from->signature_type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (from->nprincipals > 0) { if ((to->principals = calloc(from->nprincipals, sizeof(*to->principals))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < from->nprincipals; i++) { to->principals[i] = strdup(from->principals[i]); if (to->principals[i] == NULL) { to->nprincipals = i; r = SSH_ERR_ALLOC_FAIL; goto out; } } } to->nprincipals = from->nprincipals; /* success */ cert_free(to_key->cert); to_key->cert = to; to = NULL; r = 0; out: cert_free(to); return r; } int sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to) { /* Append security-key application string */ if ((to->sk_application = strdup(from->sk_application)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } int sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) { struct sshkey *n = NULL; int r = SSH_ERR_INTERNAL_ERROR; const struct sshkey_impl *impl; *pkp = NULL; if ((impl = sshkey_impl_from_key(k)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if ((n = sshkey_new(k->type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = impl->funcs->copy_public(k, n)) != 0) goto out; if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) goto out; /* success */ *pkp = n; n = NULL; r = 0; out: sshkey_free(n); return r; } int sshkey_is_shielded(struct sshkey *k) { return k != NULL && k->shielded_private != NULL; } int sshkey_shield_private(struct sshkey *k) { struct sshbuf *prvbuf = NULL; u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH]; struct sshcipher_ctx *cctx = NULL; const struct sshcipher *cipher; size_t i, enclen = 0; struct sshkey *kswap = NULL, tmp; int r = SSH_ERR_INTERNAL_ERROR; #ifdef DEBUG_PK fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k)); #endif if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (cipher_keylen(cipher) + cipher_ivlen(cipher) > ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) { r = SSH_ERR_INTERNAL_ERROR; goto out; } /* Prepare a random pre-key, and from it an ephemeral key */ if ((r = sshkey_prekey_alloc(&prekey, SSHKEY_SHIELD_PREKEY_LEN)) != 0) 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); sshkey_prekey_free(prekey, SSHKEY_SHIELD_PREKEY_LEN); sshkey_free(kswap); sshbuf_free(prvbuf); return r; } /* Check deterministic padding after private key */ static int private2_check_padding(struct sshbuf *decrypted) { u_char pad; size_t i; int r; i = 0; while (sshbuf_len(decrypted)) { if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) goto out; if (pad != (++i & 0xff)) { r = SSH_ERR_INVALID_FORMAT; goto out; } } /* success */ r = 0; out: explicit_bzero(&pad, sizeof(pad)); explicit_bzero(&i, sizeof(i)); return r; } int sshkey_unshield_private(struct sshkey *k) { struct sshbuf *prvbuf = NULL; u_char *cp, keyiv[SSH_DIGEST_MAX_LENGTH]; struct sshcipher_ctx *cctx = NULL; const struct sshcipher *cipher; struct sshkey *kswap = NULL, tmp; int r = SSH_ERR_INTERNAL_ERROR; #ifdef DEBUG_PK fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k)); #endif if (!sshkey_is_shielded(k)) return 0; /* nothing to do */ if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (cipher_keylen(cipher) + cipher_ivlen(cipher) > ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) { r = SSH_ERR_INTERNAL_ERROR; goto out; } /* check size of shielded key blob */ if (k->shielded_len < cipher_blocksize(cipher) || (k->shielded_len % cipher_blocksize(cipher)) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* Calculate the ephemeral key from the prekey */ if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH, k->shield_prekey, k->shield_prekey_len, keyiv, SSH_DIGEST_MAX_LENGTH)) != 0) goto out; if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher), keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0) goto out; #ifdef DEBUG_PK fprintf(stderr, "%s: key+iv\n", __func__); sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH), stderr); #endif /* Decrypt and parse the shielded private key using the ephemeral key */ if ((prvbuf = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0) goto out; /* decrypt */ #ifdef DEBUG_PK fprintf(stderr, "%s: encrypted\n", __func__); sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr); #endif if ((r = cipher_crypt(cctx, 0, cp, k->shielded_private, k->shielded_len, 0, 0)) != 0) goto out; #ifdef DEBUG_PK fprintf(stderr, "%s: serialised\n", __func__); sshbuf_dump(prvbuf, stderr); #endif /* Parse private key */ if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0) goto out; if ((r = private2_check_padding(prvbuf)) != 0) goto out; /* Swap the parsed key back into place */ tmp = *kswap; *kswap = *k; *k = tmp; /* success */ r = 0; out: cipher_free(cctx); explicit_bzero(keyiv, sizeof(keyiv)); explicit_bzero(&tmp, sizeof(tmp)); sshkey_free(kswap); sshbuf_free(prvbuf); return r; } static int cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) { struct sshbuf *principals = NULL, *crit = NULL; struct sshbuf *exts = NULL, *ca = NULL; u_char *sig = NULL; size_t signed_len = 0, slen = 0, kidlen = 0; int ret = SSH_ERR_INTERNAL_ERROR; /* Copy the entire key blob for verification and later serialisation */ if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0) return ret; /* Parse body of certificate up to signature */ if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 || (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || (ret = sshbuf_froms(b, &principals)) != 0 || (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || (ret = sshbuf_froms(b, &crit)) != 0 || (ret = sshbuf_froms(b, &exts)) != 0 || (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || (ret = sshbuf_froms(b, &ca)) != 0) { /* XXX debug print error for ret */ ret = SSH_ERR_INVALID_FORMAT; goto out; } /* Signature is left in the buffer so we can calculate this length */ signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b); if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (key->cert->type != SSH2_CERT_TYPE_USER && key->cert->type != SSH2_CERT_TYPE_HOST) { ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE; goto out; } /* Parse principals section */ while (sshbuf_len(principals) > 0) { char *principal = NULL; char **oprincipals = NULL; if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if ((ret = sshbuf_get_cstring(principals, &principal, NULL)) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } oprincipals = key->cert->principals; key->cert->principals = recallocarray(key->cert->principals, key->cert->nprincipals, key->cert->nprincipals + 1, sizeof(*key->cert->principals)); if (key->cert->principals == NULL) { free(principal); key->cert->principals = oprincipals; ret = SSH_ERR_ALLOC_FAIL; goto out; } key->cert->principals[key->cert->nprincipals++] = principal; } /* * Stash a copies of the critical options and extensions sections * for later use. */ if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 || (exts != NULL && (ret = sshbuf_putb(key->cert->extensions, exts)) != 0)) goto out; /* * Validate critical options and extensions sections format. */ while (sshbuf_len(crit) != 0) { if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 || (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) { sshbuf_reset(key->cert->critical); ret = SSH_ERR_INVALID_FORMAT; goto out; } } while (exts != NULL && sshbuf_len(exts) != 0) { if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 || (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) { sshbuf_reset(key->cert->extensions); ret = SSH_ERR_INVALID_FORMAT; goto out; } } /* Parse CA key and check signature */ if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) { ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) { ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0) goto out; if ((ret = sshkey_get_sigtype(sig, slen, &key->cert->signature_type)) != 0) goto out; /* Success */ ret = 0; out: sshbuf_free(ca); sshbuf_free(crit); sshbuf_free(exts); sshbuf_free(principals); free(sig); return ret; } int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key) { /* Parse additional security-key application string */ if (sshbuf_get_cstring(b, &key->sk_application, NULL) != 0) return SSH_ERR_INVALID_FORMAT; return 0; } static int sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, int allow_cert) { int type, ret = SSH_ERR_INTERNAL_ERROR; char *ktype = NULL; struct sshkey *key = NULL; struct sshbuf *copy; const struct sshkey_impl *impl; #ifdef DEBUG_PK /* XXX */ sshbuf_dump(b, stderr); #endif if (keyp != NULL) *keyp = NULL; if ((copy = sshbuf_fromb(b)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } type = sshkey_type_from_name(ktype); if (!allow_cert && sshkey_type_is_cert(type)) { ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } if ((impl = sshkey_impl_from_type(type)) == NULL) { ret = SSH_ERR_KEY_TYPE_UNKNOWN; goto out; } if ((key = sshkey_new(type)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (sshkey_type_is_cert(type)) { /* Skip nonce that precedes all certificates */ if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } } if ((ret = impl->funcs->deserialize_public(ktype, b, key)) != 0) goto out; /* Parse certificate potion */ if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0) goto out; if (key != NULL && sshbuf_len(b) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } ret = 0; if (keyp != NULL) { *keyp = key; key = NULL; } out: sshbuf_free(copy); sshkey_free(key); free(ktype); return ret; } int sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) { struct sshbuf *b; int r; if ((b = sshbuf_from(blob, blen)) == NULL) return SSH_ERR_ALLOC_FAIL; r = sshkey_from_blob_internal(b, keyp, 1); sshbuf_free(b); return r; } int sshkey_fromb(struct sshbuf *b, struct sshkey **keyp) { return sshkey_from_blob_internal(b, keyp, 1); } int sshkey_froms(struct sshbuf *buf, struct sshkey **keyp) { struct sshbuf *b; int r; if ((r = sshbuf_froms(buf, &b)) != 0) return r; r = sshkey_from_blob_internal(b, keyp, 1); sshbuf_free(b); return r; } int sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) { int r; struct sshbuf *b = NULL; char *sigtype = NULL; if (sigtypep != NULL) *sigtypep = NULL; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0) goto out; /* success */ if (sigtypep != NULL) { *sigtypep = sigtype; sigtype = NULL; } r = 0; out: free(sigtype); sshbuf_free(b); return r; } /* * * Checks whether a certificate's signature type is allowed. * Returns 0 (success) if the certificate signature type appears in the * "allowed" pattern-list, or the key is not a certificate to begin with. * Otherwise returns a ssherr.h code. */ int sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed) { if (key == NULL || allowed == NULL) return SSH_ERR_INVALID_ARGUMENT; if (!sshkey_type_is_cert(key->type)) return 0; if (key->cert == NULL || key->cert->signature_type == NULL) return SSH_ERR_INVALID_ARGUMENT; if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1) return SSH_ERR_SIGN_ALG_UNSUPPORTED; return 0; } /* * Returns the expected signature algorithm for a given public key algorithm. */ const char * sshkey_sigalg_by_name(const char *name) { const struct sshkey_impl *impl; int i; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; if (strcmp(impl->name, name) != 0) continue; if (impl->sigalg != NULL) return impl->sigalg; if (!impl->cert) return impl->name; return sshkey_ssh_name_from_type_nid( sshkey_type_plain(impl->type), impl->nid); } return NULL; } /* * Verifies that the signature algorithm appearing inside the signature blob * matches that which was requested. */ int sshkey_check_sigtype(const u_char *sig, size_t siglen, const char *requested_alg) { const char *expected_alg; char *sigtype = NULL; int r; if (requested_alg == NULL) return 0; if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) return r; r = strcmp(expected_alg, sigtype) == 0; free(sigtype); return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED; } int sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { int was_shielded = sshkey_is_shielded(key); int r2, r = SSH_ERR_INTERNAL_ERROR; const struct sshkey_impl *impl; if (sigp != NULL) *sigp = NULL; if (lenp != NULL) *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if ((r = sshkey_unshield_private(key)) != 0) return r; if (sshkey_is_sk(key)) { r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen, compat, sk_pin); } else { if (impl->funcs->sign == NULL) r = SSH_ERR_SIGN_ALG_UNSUPPORTED; else { r = impl->funcs->sign(key, sigp, lenp, data, datalen, alg, sk_provider, sk_pin, compat); } } if (was_shielded && (r2 = sshkey_shield_private(key)) != 0) return r2; return r; } /* * ssh_key_verify returns 0 for a correct signature and < 0 on error. * If "alg" specified, then the signature must use that algorithm. */ int sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { const struct sshkey_impl *impl; if (detailsp != NULL) *detailsp = NULL; if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; return impl->funcs->verify(key, sig, siglen, data, dlen, alg, compat, detailsp); } /* Convert a plain key to their _CERT equivalent */ int sshkey_to_certified(struct sshkey *k) { int newtype; if ((newtype = sshkey_type_certified(k->type)) == -1) return SSH_ERR_INVALID_ARGUMENT; if ((k->cert = cert_new()) == NULL) return SSH_ERR_ALLOC_FAIL; k->type = newtype; return 0; } /* Convert a certificate to its raw key equivalent */ int sshkey_drop_cert(struct sshkey *k) { if (!sshkey_type_is_cert(k->type)) return SSH_ERR_KEY_TYPE_UNKNOWN; cert_free(k->cert); k->cert = NULL; k->type = sshkey_type_plain(k->type); return 0; } /* Sign a certified key, (re-)generating the signed certblob. */ int sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, const char *sk_provider, const char *sk_pin, sshkey_certify_signer *signer, void *signer_ctx) { const struct sshkey_impl *impl; struct sshbuf *principals = NULL; u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; size_t i, ca_len, sig_len; int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *cert = NULL; char *sigtype = NULL; if (k == NULL || k->cert == NULL || k->cert->certblob == NULL || ca == NULL) return SSH_ERR_INVALID_ARGUMENT; if (!sshkey_is_cert(k)) return SSH_ERR_KEY_TYPE_UNKNOWN; if (!sshkey_type_is_valid_ca(ca->type)) return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; if ((impl = sshkey_impl_from_key(k)) == NULL) return SSH_ERR_INTERNAL_ERROR; /* * If no alg specified as argument but a signature_type was set, * then prefer that. If both were specified, then they must match. */ if (alg == NULL) alg = k->cert->signature_type; else if (k->cert->signature_type != NULL && strcmp(alg, k->cert->signature_type) != 0) return SSH_ERR_INVALID_ARGUMENT; /* * If no signing algorithm or signature_type was specified and we're * using a RSA key, then default to a good signature algorithm. */ if (alg == NULL && ca->type == KEY_RSA) alg = "rsa-sha2-512"; if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; cert = k->cert->certblob; /* for readability */ sshbuf_reset(cert); if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0) goto out; /* -v01 certs put nonce first */ arc4random_buf(&nonce, sizeof(nonce)); if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0) goto out; /* Public key next */ if ((ret = impl->funcs->serialize_public(k, cert, SSHKEY_SERIALIZE_DEFAULT)) != 0) goto out; /* Then remaining cert fields */ if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 || (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 || (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0) goto out; if ((principals = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < k->cert->nprincipals; i++) { if ((ret = sshbuf_put_cstring(principals, k->cert->principals[i])) != 0) goto out; } if ((ret = sshbuf_put_stringb(cert, principals)) != 0 || (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 || (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 || (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 || (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 || (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */ (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0) goto out; /* Sign the whole mess */ if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) goto out; /* Check and update signature_type against what was actually used */ if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0) goto out; if (alg != NULL && strcmp(alg, sigtype) != 0) { ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; goto out; } if (k->cert->signature_type == NULL) { k->cert->signature_type = sigtype; sigtype = NULL; } /* Append signature and we are done */ if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) goto out; ret = 0; out: if (ret != 0) sshbuf_reset(cert); free(sig_blob); free(ca_blob); free(sigtype); sshbuf_free(principals); return ret; } static int default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat, void *ctx) { if (ctx != NULL) return SSH_ERR_INVALID_ARGUMENT; return sshkey_sign(key, sigp, lenp, data, datalen, alg, sk_provider, sk_pin, compat); } int sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg, const char *sk_provider, const char *sk_pin) { return sshkey_certify_custom(k, ca, alg, sk_provider, sk_pin, default_key_sign, NULL); } int sshkey_cert_check_authority(const struct sshkey *k, int want_host, int require_principal, int wildcard_pattern, uint64_t verify_time, const char *name, const char **reason) { u_int i, principal_matches; if (reason == NULL) return SSH_ERR_INVALID_ARGUMENT; if (!sshkey_is_cert(k)) { *reason = "Key is not a certificate"; return SSH_ERR_KEY_CERT_INVALID; } if (want_host) { if (k->cert->type != SSH2_CERT_TYPE_HOST) { *reason = "Certificate invalid: not a host certificate"; return SSH_ERR_KEY_CERT_INVALID; } } else { if (k->cert->type != SSH2_CERT_TYPE_USER) { *reason = "Certificate invalid: not a user certificate"; return SSH_ERR_KEY_CERT_INVALID; } } if (verify_time < k->cert->valid_after) { *reason = "Certificate invalid: not yet valid"; return SSH_ERR_KEY_CERT_INVALID; } if (verify_time >= k->cert->valid_before) { *reason = "Certificate invalid: expired"; return SSH_ERR_KEY_CERT_INVALID; } if (k->cert->nprincipals == 0) { if (require_principal) { *reason = "Certificate lacks principal list"; return SSH_ERR_KEY_CERT_INVALID; } } else if (name != NULL) { principal_matches = 0; for (i = 0; i < k->cert->nprincipals; i++) { if (wildcard_pattern) { if (match_pattern(k->cert->principals[i], name)) { principal_matches = 1; break; } } else if (strcmp(name, k->cert->principals[i]) == 0) { principal_matches = 1; break; } } if (!principal_matches) { *reason = "Certificate invalid: name is not a listed " "principal"; return SSH_ERR_KEY_CERT_INVALID; } } return 0; } int sshkey_cert_check_authority_now(const struct sshkey *k, int want_host, int require_principal, int wildcard_pattern, const char *name, const char **reason) { time_t now; if ((now = time(NULL)) < 0) { /* yikes - system clock before epoch! */ *reason = "Certificate invalid: not yet valid"; return SSH_ERR_KEY_CERT_INVALID; } return sshkey_cert_check_authority(k, want_host, require_principal, wildcard_pattern, (uint64_t)now, name, reason); } int sshkey_cert_check_host(const struct sshkey *key, const char *host, int wildcard_principals, const char *ca_sign_algorithms, const char **reason) { int r; if ((r = sshkey_cert_check_authority_now(key, 1, 0, wildcard_principals, host, reason)) != 0) return r; if (sshbuf_len(key->cert->critical) != 0) { *reason = "Certificate contains unsupported critical options"; return SSH_ERR_KEY_CERT_INVALID; } if (ca_sign_algorithms != NULL && (r = sshkey_check_cert_sigtype(key, ca_sign_algorithms)) != 0) { *reason = "Certificate signed with disallowed algorithm"; return SSH_ERR_KEY_CERT_INVALID; } return 0; } size_t sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l) { char from[32], to[32], ret[128]; *from = *to = '\0'; if (cert->valid_after == 0 && cert->valid_before == 0xffffffffffffffffULL) return strlcpy(s, "forever", l); if (cert->valid_after != 0) format_absolute_time(cert->valid_after, from, sizeof(from)); if (cert->valid_before != 0xffffffffffffffffULL) format_absolute_time(cert->valid_before, to, sizeof(to)); if (cert->valid_after == 0) snprintf(ret, sizeof(ret), "before %s", to); else if (cert->valid_before == 0xffffffffffffffffULL) snprintf(ret, sizeof(ret), "after %s", from); else snprintf(ret, sizeof(ret), "from %s to %s", from, to); return strlcpy(s, ret, l); } /* Common serialization for FIDO private keys */ int sshkey_serialize_private_sk(const struct sshkey *key, struct sshbuf *b) { int r; if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0 || (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) return r; return 0; } int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { int r = SSH_ERR_INTERNAL_ERROR; int was_shielded = sshkey_is_shielded(key); struct sshbuf *b = NULL; const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_INTERNAL_ERROR; if ((r = sshkey_unshield_private(key)) != 0) return r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) goto out; if (sshkey_is_cert(key)) { if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0) goto out; } if ((r = impl->funcs->serialize_private(key, b, opts)) != 0) goto out; /* * success (but we still need to append the output to buf after * possibly re-shielding the private key) */ r = 0; out: if (was_shielded) r = sshkey_shield_private(key); if (r == 0) r = sshbuf_putb(buf, b); sshbuf_free(b); return r; } int sshkey_private_serialize(struct sshkey *key, struct sshbuf *b) { return sshkey_private_serialize_opt(key, b, SSHKEY_SERIALIZE_DEFAULT); } /* Shared deserialization of FIDO private key components */ int sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k) { int r; if ((k->sk_key_handle = sshbuf_new()) == NULL || (k->sk_reserved = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_cstring(buf, &k->sk_application, NULL)) != 0 || (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) return r; return 0; } int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) { const struct sshkey_impl *impl; char *tname = NULL; char *expect_sk_application = NULL; u_char *expect_ed25519_pk = NULL; struct sshkey *k = NULL; int type, r = SSH_ERR_INTERNAL_ERROR; if (kp != NULL) *kp = NULL; if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0) goto out; type = sshkey_type_from_name(tname); if (sshkey_type_is_cert(type)) { /* * Certificate key private keys begin with the certificate * itself. Make sure this matches the type of the enclosing * private key. */ if ((r = sshkey_froms(buf, &k)) != 0) goto out; if (k->type != type) { r = SSH_ERR_KEY_CERT_MISMATCH; goto out; } /* For ECDSA keys, the group must match too */ if (k->type == KEY_ECDSA && k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) { r = SSH_ERR_KEY_CERT_MISMATCH; goto out; } /* * Several fields are redundant between certificate and * private key body, we require these to match. */ expect_sk_application = k->sk_application; expect_ed25519_pk = k->ed25519_pk; k->sk_application = NULL; k->ed25519_pk = NULL; /* XXX xmss too or refactor */ } else { if ((k = sshkey_new(type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } } if ((impl = sshkey_impl_from_type(type)) == NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if ((r = impl->funcs->deserialize_private(tname, buf, k)) != 0) goto out; /* XXX xmss too or refactor */ if ((expect_sk_application != NULL && (k->sk_application == NULL || strcmp(expect_sk_application, k->sk_application) != 0)) || (expect_ed25519_pk != NULL && (k->ed25519_pk == NULL || memcmp(expect_ed25519_pk, k->ed25519_pk, ED25519_PK_SZ) != 0))) { r = SSH_ERR_KEY_CERT_MISMATCH; goto out; } /* success */ r = 0; if (kp != NULL) { *kp = k; k = NULL; } out: free(tname); sshkey_free(k); free(expect_sk_application); free(expect_ed25519_pk); return r; } #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) int sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) { EC_POINT *nq = NULL; BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL; int ret = SSH_ERR_KEY_INVALID_EC_VALUE; /* * NB. This assumes OpenSSL has already verified that the public * point lies on the curve. This is done by EC_POINT_oct2point() * implicitly calling EC_POINT_is_on_curve(). If this code is ever * reachable with public points not unmarshalled using * EC_POINT_oct2point then the caller will need to explicitly check. */ /* Q != infinity */ if (EC_POINT_is_at_infinity(group, public)) goto out; if ((x = BN_new()) == NULL || (y = BN_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ if (EC_GROUP_get_order(group, order, NULL) != 1 || EC_POINT_get_affine_coordinates_GFp(group, public, x, y, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_num_bits(x) <= BN_num_bits(order) / 2 || BN_num_bits(y) <= BN_num_bits(order) / 2) goto out; /* nQ == infinity (n == order of subgroup) */ if ((nq = EC_POINT_new(group)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (EC_POINT_is_at_infinity(group, nq) != 1) goto out; /* x < order - 1, y < order - 1 */ if (!BN_sub(tmp, order, BN_value_one())) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0) goto out; ret = 0; out: BN_clear_free(x); BN_clear_free(y); BN_clear_free(order); BN_clear_free(tmp); EC_POINT_free(nq); return ret; } int sshkey_ec_validate_private(const EC_KEY *key) { BIGNUM *order = NULL, *tmp = NULL; int ret = SSH_ERR_KEY_INVALID_EC_VALUE; if ((order = BN_new()) == NULL || (tmp = BN_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } /* log2(private) > log2(order)/2 */ if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_num_bits(EC_KEY_get0_private_key(key)) <= BN_num_bits(order) / 2) goto out; /* private < order - 1 */ if (!BN_sub(tmp, order, BN_value_one())) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) goto out; ret = 0; out: BN_clear_free(order); BN_clear_free(tmp); return ret; } void sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) { BIGNUM *x = NULL, *y = NULL; if (point == NULL) { fputs("point=(NULL)\n", stderr); return; } if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) { fprintf(stderr, "%s: BN_new failed\n", __func__); goto out; } if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, NULL) != 1) { fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n", __func__); goto out; } fputs("x=", stderr); BN_print_fp(stderr, x); fputs("\ny=", stderr); BN_print_fp(stderr, y); fputs("\n", stderr); out: BN_clear_free(x); BN_clear_free(y); } void sshkey_dump_ec_key(const EC_KEY *key) { const BIGNUM *exponent; sshkey_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key)); fputs("exponent=", stderr); if ((exponent = EC_KEY_get0_private_key(key)) == NULL) fputs("(NULL)", stderr); else BN_print_fp(stderr, EC_KEY_get0_private_key(key)); fputs("\n", stderr); } #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ static int sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob, const char *passphrase, const char *comment, const char *ciphername, int rounds) { u_char *cp, *key = NULL, *pubkeyblob = NULL; u_char salt[SALT_LEN]; size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; u_int check; int r = SSH_ERR_INTERNAL_ERROR; struct sshcipher_ctx *ciphercontext = NULL; const struct sshcipher *cipher; const char *kdfname = KDFNAME; struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL; if (rounds <= 0) rounds = DEFAULT_ROUNDS; if (passphrase == NULL || !strlen(passphrase)) { ciphername = "none"; kdfname = "none"; } else if (ciphername == NULL) ciphername = DEFAULT_CIPHERNAME; if ((cipher = cipher_by_name(ciphername)) == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((kdf = sshbuf_new()) == NULL || (encoded = sshbuf_new()) == NULL || (encrypted = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } blocksize = cipher_blocksize(cipher); keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if ((key = calloc(1, keylen + ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (strcmp(kdfname, "bcrypt") == 0) { arc4random_buf(salt, SALT_LEN); if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 || (r = sshbuf_put_u32(kdf, rounds)) != 0) goto out; } else if (strcmp(kdfname, "none") != 0) { /* Unsupported KDF type */ r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } if ((r = cipher_init(&ciphercontext, cipher, key, keylen, key + keylen, ivlen, 1)) != 0) goto out; if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 || (r = sshbuf_put_cstring(encoded, ciphername)) != 0 || (r = sshbuf_put_cstring(encoded, kdfname)) != 0 || (r = sshbuf_put_stringb(encoded, kdf)) != 0 || (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */ (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 || (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0) goto out; /* set up the buffer that will be encrypted */ /* Random check bytes */ check = arc4random(); if ((r = sshbuf_put_u32(encrypted, check)) != 0 || (r = sshbuf_put_u32(encrypted, check)) != 0) goto out; /* append private key and comment*/ if ((r = sshkey_private_serialize_opt(prv, encrypted, SSHKEY_SERIALIZE_FULL)) != 0 || (r = sshbuf_put_cstring(encrypted, comment)) != 0) goto out; /* padding */ i = 0; while (sshbuf_len(encrypted) % blocksize) { if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0) goto out; } /* length in destination buffer */ if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0) goto out; /* encrypt */ if ((r = sshbuf_reserve(encoded, sshbuf_len(encrypted) + authlen, &cp)) != 0) goto out; if ((r = cipher_crypt(ciphercontext, 0, cp, sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0) goto out; sshbuf_reset(blob); /* assemble uuencoded key */ if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 || (r = sshbuf_dtob64(encoded, blob, 1)) != 0 || (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(kdf); sshbuf_free(encoded); sshbuf_free(encrypted); cipher_free(ciphercontext); explicit_bzero(salt, sizeof(salt)); if (key != NULL) freezero(key, keylen + ivlen); if (pubkeyblob != NULL) freezero(pubkeyblob, pubkeylen); return r; } static int private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp) { const u_char *cp; size_t encoded_len; int r; u_char last; struct sshbuf *encoded = NULL, *decoded = NULL; if (blob == NULL || decodedp == NULL) return SSH_ERR_INVALID_ARGUMENT; *decodedp = NULL; if ((encoded = sshbuf_new()) == NULL || (decoded = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* check preamble */ cp = sshbuf_ptr(blob); encoded_len = sshbuf_len(blob); if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) || memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } cp += MARK_BEGIN_LEN; encoded_len -= MARK_BEGIN_LEN; /* Look for end marker, removing whitespace as we go */ while (encoded_len > 0) { if (*cp != '\n' && *cp != '\r') { if ((r = sshbuf_put_u8(encoded, *cp)) != 0) goto out; } last = *cp; encoded_len--; cp++; if (last == '\n') { if (encoded_len >= MARK_END_LEN && memcmp(cp, MARK_END, MARK_END_LEN) == 0) { /* \0 terminate */ if ((r = sshbuf_put_u8(encoded, 0)) != 0) goto out; break; } } } if (encoded_len == 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* decode base64 */ if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0) goto out; /* check magic */ if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) || memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ *decodedp = decoded; decoded = NULL; r = 0; out: sshbuf_free(encoded); sshbuf_free(decoded); return r; } static int private2_decrypt(struct sshbuf *decoded, const char *passphrase, struct sshbuf **decryptedp, struct sshkey **pubkeyp) { char *ciphername = NULL, *kdfname = NULL; const struct sshcipher *cipher = NULL; int r = SSH_ERR_INTERNAL_ERROR; size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0; struct sshbuf *kdf = NULL, *decrypted = NULL; struct sshcipher_ctx *ciphercontext = NULL; struct sshkey *pubkey = NULL; u_char *key = NULL, *salt = NULL, *dp; u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL) return SSH_ERR_INVALID_ARGUMENT; *decryptedp = NULL; *pubkeyp = NULL; if ((decrypted = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* parse public portion of key */ if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 || (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 || (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 || (r = sshbuf_froms(decoded, &kdf)) != 0 || (r = sshbuf_get_u32(decoded, &nkeys)) != 0) goto out; if (nkeys != 1) { /* XXX only one key supported at present */ r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshkey_froms(decoded, &pubkey)) != 0 || (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) goto out; if ((cipher = cipher_by_name(ciphername)) == NULL) { r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) { r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } if ((passphrase == NULL || strlen(passphrase) == 0) && strcmp(kdfname, "none") != 0) { /* passphrase required */ r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } /* check size of encrypted key blob */ blocksize = cipher_blocksize(cipher); if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* setup key */ keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if ((key = calloc(1, keylen + ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (strcmp(kdfname, "bcrypt") == 0) { if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 || (r = sshbuf_get_u32(kdf, &rounds)) != 0) goto out; if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, key, keylen + ivlen, rounds) < 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } } /* check that an appropriate amount of auth data is present */ if (sshbuf_len(decoded) < authlen || sshbuf_len(decoded) - authlen < encrypted_len) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* decrypt private portion of key */ if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 || (r = cipher_init(&ciphercontext, cipher, key, keylen, key + keylen, ivlen, 0)) != 0) goto out; if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded), encrypted_len, 0, authlen)) != 0) { /* an integrity error here indicates an incorrect passphrase */ if (r == SSH_ERR_MAC_INVALID) r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0) goto out; /* there should be no trailing data */ if (sshbuf_len(decoded) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* check check bytes */ if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 || (r = sshbuf_get_u32(decrypted, &check2)) != 0) goto out; if (check1 != check2) { r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } /* success */ *decryptedp = decrypted; decrypted = NULL; *pubkeyp = pubkey; pubkey = NULL; r = 0; out: cipher_free(ciphercontext); free(ciphername); free(kdfname); sshkey_free(pubkey); if (salt != NULL) { explicit_bzero(salt, slen); free(salt); } if (key != NULL) { explicit_bzero(key, keylen + ivlen); free(key); } sshbuf_free(kdf); sshbuf_free(decrypted); return r; } static int sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp, char **commentp) { char *comment = NULL; int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *decoded = NULL, *decrypted = NULL; struct sshkey *k = NULL, *pubkey = NULL; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; /* Undo base64 encoding and decrypt the private section */ if ((r = private2_uudecode(blob, &decoded)) != 0 || (r = private2_decrypt(decoded, passphrase, &decrypted, &pubkey)) != 0) goto out; if (type != KEY_UNSPEC && sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) { r = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } /* Load the private key and comment */ if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 || (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0) goto out; /* Check deterministic padding after private section */ if ((r = private2_check_padding(decrypted)) != 0) goto out; /* Check that the public key in the envelope matches the private key */ if (!sshkey_equal(pubkey, k)) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ r = 0; if (keyp != NULL) { *keyp = k; k = NULL; } if (commentp != NULL) { *commentp = comment; comment = NULL; } out: free(comment); sshbuf_free(decoded); sshbuf_free(decrypted); sshkey_free(k); sshkey_free(pubkey); return r; } static int sshkey_parse_private2_pubkey(struct sshbuf *blob, int type, struct sshkey **keyp) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *decoded = NULL; struct sshkey *pubkey = NULL; u_int nkeys = 0; if (keyp != NULL) *keyp = NULL; if ((r = private2_uudecode(blob, &decoded)) != 0) goto out; /* parse public key from unencrypted envelope */ if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 || (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */ (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */ (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */ (r = sshbuf_get_u32(decoded, &nkeys)) != 0) goto out; if (nkeys != 1) { /* XXX only one key supported at present */ r = SSH_ERR_INVALID_FORMAT; goto out; } /* Parse the public key */ if ((r = sshkey_froms(decoded, &pubkey)) != 0) goto out; if (type != KEY_UNSPEC && sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) { r = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } /* success */ r = 0; if (keyp != NULL) { *keyp = pubkey; pubkey = NULL; } out: sshbuf_free(decoded); sshkey_free(pubkey); return r; } #ifdef WITH_OPENSSL /* convert SSH v2 key to PEM or PKCS#8 format */ static int sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, int format, const char *_passphrase, const char *comment) { int was_shielded = sshkey_is_shielded(key); int success, r; int blen, len = strlen(_passphrase); u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; char *bptr; BIO *bio = NULL; struct sshbuf *blob; EVP_PKEY *pkey = NULL; if (len > 0 && len <= 4) return SSH_ERR_PASSPHRASE_TOO_SHORT; if ((blob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((bio = BIO_new(BIO_s_mem())) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshkey_unshield_private(key)) != 0) goto out; switch (key->type) { #ifdef WITH_DSA case KEY_DSA: if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, cipher, passphrase, len, NULL, NULL); } else { if ((pkey = EVP_PKEY_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } success = EVP_PKEY_set1_DSA(pkey, key->dsa); } break; #endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_ECPrivateKey(bio, EVP_PKEY_get0_EC_KEY(key->pkey), cipher, passphrase, len, NULL, NULL); } else { pkey = key->pkey; EVP_PKEY_up_ref(key->pkey); success = 1; } break; #endif case KEY_RSA: if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_RSAPrivateKey(bio, EVP_PKEY_get0_RSA(key->pkey), cipher, passphrase, len, NULL, NULL); } else { pkey = key->pkey; EVP_PKEY_up_ref(key->pkey); success = 1; } break; default: success = 0; break; } if (success == 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (format == SSHKEY_PRIVATE_PKCS8) { if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher, passphrase, len, NULL, NULL)) == 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } } if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if ((r = sshbuf_put(blob, bptr, blen)) != 0) goto out; r = 0; out: if (was_shielded) r = sshkey_shield_private(key); if (r == 0) r = sshbuf_putb(buf, blob); EVP_PKEY_free(pkey); sshbuf_free(blob); BIO_free(bio); return r; } #endif /* WITH_OPENSSL */ /* Serialise "key" to buffer "blob" */ int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, const char *passphrase, const char *comment, int format, const char *openssh_format_cipher, int openssh_format_rounds) { switch (key->type) { #ifdef WITH_OPENSSL case KEY_DSA: case KEY_ECDSA: case KEY_RSA: break; /* see below */ #endif /* WITH_OPENSSL */ case KEY_ED25519: case KEY_ED25519_SK: #ifdef WITH_XMSS case KEY_XMSS: #endif /* WITH_XMSS */ #ifdef WITH_OPENSSL case KEY_ECDSA_SK: #endif /* WITH_OPENSSL */ return sshkey_private_to_blob2(key, blob, passphrase, comment, openssh_format_cipher, openssh_format_rounds); default: return SSH_ERR_KEY_TYPE_UNKNOWN; } #ifdef WITH_OPENSSL switch (format) { case SSHKEY_PRIVATE_OPENSSH: return sshkey_private_to_blob2(key, blob, passphrase, comment, openssh_format_cipher, openssh_format_rounds); case SSHKEY_PRIVATE_PEM: case SSHKEY_PRIVATE_PKCS8: return sshkey_private_to_blob_pem_pkcs8(key, blob, format, passphrase, comment); default: return SSH_ERR_INVALID_ARGUMENT; } #endif /* WITH_OPENSSL */ } #ifdef WITH_OPENSSL static int translate_libcrypto_error(unsigned long pem_err) { int pem_reason = ERR_GET_REASON(pem_err); switch (ERR_GET_LIB(pem_err)) { case ERR_LIB_PEM: switch (pem_reason) { case PEM_R_BAD_PASSWORD_READ: #ifdef PEM_R_PROBLEMS_GETTING_PASSWORD case PEM_R_PROBLEMS_GETTING_PASSWORD: #endif #ifdef PEM_R_BAD_DECRYPT case PEM_R_BAD_DECRYPT: #endif return SSH_ERR_KEY_WRONG_PASSPHRASE; default: return SSH_ERR_INVALID_FORMAT; } case ERR_LIB_EVP: switch (pem_reason) { #ifdef EVP_R_BAD_DECRYPT case EVP_R_BAD_DECRYPT: return SSH_ERR_KEY_WRONG_PASSPHRASE; #endif #ifdef EVP_R_BN_DECODE_ERROR case EVP_R_BN_DECODE_ERROR: #endif case EVP_R_DECODE_ERROR: #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR case EVP_R_PRIVATE_KEY_DECODE_ERROR: #endif return SSH_ERR_INVALID_FORMAT; default: return SSH_ERR_LIBCRYPTO_ERROR; } case ERR_LIB_ASN1: return SSH_ERR_INVALID_FORMAT; } return SSH_ERR_LIBCRYPTO_ERROR; } static void clear_libcrypto_errors(void) { while (ERR_get_error() != 0) ; } /* * Translate OpenSSL error codes to determine whether * passphrase is required/incorrect. */ static int convert_libcrypto_error(void) { /* * Some password errors are reported at the beginning * of the error queue. */ if (translate_libcrypto_error(ERR_peek_error()) == SSH_ERR_KEY_WRONG_PASSPHRASE) return SSH_ERR_KEY_WRONG_PASSPHRASE; return translate_libcrypto_error(ERR_peek_last_error()); } static int pem_passphrase_cb(char *buf, int size, int rwflag, void *u) { char *p = (char *)u; size_t len; if (p == NULL || (len = strlen(p)) == 0) return -1; if (size < 0 || len > (size_t)size) return -1; memcpy(buf, p, len); return (int)len; } static int sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp) { EVP_PKEY *pk = NULL; struct sshkey *prv = NULL; BIO *bio = NULL; int r; RSA *rsa = NULL; EC_KEY *ecdsa = NULL; if (keyp != NULL) *keyp = NULL; if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) return SSH_ERR_ALLOC_FAIL; if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) != (int)sshbuf_len(blob)) { r = SSH_ERR_ALLOC_FAIL; goto out; } clear_libcrypto_errors(); if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb, (char *)passphrase)) == NULL) { /* * libcrypto may return various ASN.1 errors when attempting * to parse a key with an incorrect passphrase. * Treat all format errors as "incorrect passphrase" if a * passphrase was supplied. */ if (passphrase != NULL && *passphrase != '\0') r = SSH_ERR_KEY_WRONG_PASSPHRASE; else r = convert_libcrypto_error(); goto out; } if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA && (type == KEY_UNSPEC || type == KEY_RSA)) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((rsa = EVP_PKEY_get1_RSA(pk)) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } prv->type = KEY_RSA; #ifdef DEBUG_PK RSA_print_fp(stderr, rsa, 8); #endif if (RSA_blinding_on(rsa, NULL) != 1 || EVP_PKEY_set1_RSA(pk, rsa) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } EVP_PKEY_up_ref(pk); prv->pkey = pk; if ((r = sshkey_check_rsa_length(prv, 0)) != 0) goto out; #ifdef WITH_DSA } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && (type == KEY_UNSPEC || type == KEY_DSA)) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } prv->dsa = EVP_PKEY_get1_DSA(pk); prv->type = KEY_DSA; #ifdef DEBUG_PK DSA_print_fp(stderr, prv->dsa, 8); #endif #endif #ifdef OPENSSL_HAS_ECC } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC && (type == KEY_UNSPEC || type == KEY_ECDSA)) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((prv->ecdsa_nid = sshkey_ecdsa_fixup_group(pk)) == -1 || (ecdsa = EVP_PKEY_get1_EC_KEY(pk)) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } prv->type = KEY_ECDSA; if (sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || sshkey_ec_validate_public(EC_KEY_get0_group(ecdsa), EC_KEY_get0_public_key(ecdsa)) != 0 || sshkey_ec_validate_private(ecdsa) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } EVP_PKEY_up_ref(pk); prv->pkey = pk; #ifdef DEBUG_PK if (prv != NULL && prv->pkey != NULL) sshkey_dump_ec_key(EVP_PKEY_get0_EC_KEY(prv->pkey)); #endif #endif /* OPENSSL_HAS_ECC */ #ifdef OPENSSL_HAS_ED25519 } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_ED25519 && (type == KEY_UNSPEC || type == KEY_ED25519)) { size_t len; if ((prv = sshkey_new(KEY_UNSPEC)) == NULL || (prv->ed25519_sk = calloc(1, ED25519_SK_SZ)) == NULL || (prv->ed25519_pk = calloc(1, ED25519_PK_SZ)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } prv->type = KEY_ED25519; len = ED25519_PK_SZ; if (!EVP_PKEY_get_raw_public_key(pk, prv->ed25519_pk, &len)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (len != ED25519_PK_SZ) { r = SSH_ERR_INVALID_FORMAT; goto out; } len = ED25519_SK_SZ - ED25519_PK_SZ; if (!EVP_PKEY_get_raw_private_key(pk, prv->ed25519_sk, &len)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (len != ED25519_SK_SZ - ED25519_PK_SZ) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* Append the public key to our private key */ memcpy(prv->ed25519_sk + (ED25519_SK_SZ - ED25519_PK_SZ), prv->ed25519_pk, ED25519_PK_SZ); #ifdef DEBUG_PK sshbuf_dump_data(prv->ed25519_sk, ED25519_SK_SZ, stderr); #endif #endif /* OPENSSL_HAS_ED25519 */ } else { r = SSH_ERR_INVALID_FORMAT; goto out; } r = 0; if (keyp != NULL) { *keyp = prv; prv = NULL; } out: BIO_free(bio); EVP_PKEY_free(pk); RSA_free(rsa); #ifdef OPENSSL_HAS_ECC EC_KEY_free(ecdsa); #endif sshkey_free(prv); return r; } #endif /* WITH_OPENSSL */ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp, char **commentp) { int r = SSH_ERR_INTERNAL_ERROR; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; switch (type) { case KEY_XMSS: /* No fallback for new-format-only keys */ return sshkey_parse_private2(blob, type, passphrase, keyp, commentp); default: r = sshkey_parse_private2(blob, type, passphrase, keyp, commentp); /* Only fallback to PEM parser if a format error occurred. */ if (r != SSH_ERR_INVALID_FORMAT) return r; #ifdef WITH_OPENSSL return sshkey_parse_private_pem_fileblob(blob, type, passphrase, keyp); #else return SSH_ERR_INVALID_FORMAT; #endif /* WITH_OPENSSL */ } } int sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, struct sshkey **keyp, char **commentp) { if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, passphrase, keyp, commentp); } void sshkey_sig_details_free(struct sshkey_sig_details *details) { freezero(details, sizeof(*details)); } int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, struct sshkey **pubkeyp) { int r = SSH_ERR_INTERNAL_ERROR; if (pubkeyp != NULL) *pubkeyp = NULL; /* only new-format private keys bundle a public key inside */ if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0) return r; return 0; } #ifdef WITH_XMSS /* * serialize the key with the current state and forward the state * maxsign times. */ int sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, u_int32_t maxsign, int printerror) { int r, rupdate; if (maxsign == 0 || sshkey_type_plain(k->type) != KEY_XMSS) return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); if ((r = sshkey_xmss_get_state(k, printerror)) != 0 || (r = sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_STATE)) != 0 || (r = sshkey_xmss_forward_state(k, maxsign)) != 0) goto out; r = 0; out: if ((rupdate = sshkey_xmss_update_state(k, printerror)) != 0) { if (r == 0) r = rupdate; } return r; } u_int32_t sshkey_signatures_left(const struct sshkey *k) { if (sshkey_type_plain(k->type) == KEY_XMSS) return sshkey_xmss_signatures_left(k); return 0; } int sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign) { if (sshkey_type_plain(k->type) != KEY_XMSS) return SSH_ERR_INVALID_ARGUMENT; return sshkey_xmss_enable_maxsign(k, maxsign); } int sshkey_set_filename(struct sshkey *k, const char *filename) { if (k == NULL) return SSH_ERR_INVALID_ARGUMENT; if (sshkey_type_plain(k->type) != KEY_XMSS) return 0; if (filename == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((k->xmss_filename = strdup(filename)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } #else int sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, u_int32_t maxsign, int printerror) { return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); } u_int32_t sshkey_signatures_left(const struct sshkey *k) { return 0; } int sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign) { return SSH_ERR_INVALID_ARGUMENT; } int sshkey_set_filename(struct sshkey *k, const char *filename) { if (k == NULL) return SSH_ERR_INVALID_ARGUMENT; return 0; } #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/sshkey.h100644 001750 001750 0000000003614775415623 0014633xustar0030 atime=1744182234.889476289 openssh-10.0p1/sshkey.h010064400017500001750000000314431477541562300132230ustar00djmdjm/* $OpenBSD: sshkey.h,v 1.66 2025/04/02 04:28:03 tb 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 SSHKEY_H #define SSHKEY_H #include #ifdef WITH_OPENSSL #include #ifdef WITH_DSA #include #endif #include # ifdef OPENSSL_HAS_ECC # include # include # else /* OPENSSL_HAS_ECC */ # define EC_KEY void # define EC_GROUP void # define EC_POINT void # endif /* OPENSSL_HAS_ECC */ #define SSH_OPENSSL_VERSION OpenSSL_version(OPENSSL_VERSION) #else /* WITH_OPENSSL */ # define BIGNUM void # define RSA void # define DSA void # define EC_KEY void # define EC_GROUP void # define EC_POINT void # define EVP_PKEY void #define SSH_OPENSSL_VERSION "without OpenSSL" #endif /* WITH_OPENSSL */ #define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) struct sshbuf; /* Key types */ enum sshkey_types { KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_ED25519, KEY_RSA_CERT, KEY_DSA_CERT, KEY_ECDSA_CERT, KEY_ED25519_CERT, KEY_XMSS, KEY_XMSS_CERT, KEY_ECDSA_SK, KEY_ECDSA_SK_CERT, KEY_ED25519_SK, KEY_ED25519_SK_CERT, KEY_UNSPEC }; /* Default fingerprint hash */ #define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256 /* Fingerprint representation formats */ enum sshkey_fp_rep { SSH_FP_DEFAULT = 0, SSH_FP_HEX, SSH_FP_BASE64, SSH_FP_BUBBLEBABBLE, 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 #define SSHKEY_CERT_MAX_PRINCIPALS 256 /* XXX opaquify? */ struct sshkey_cert { struct sshbuf *certblob; /* Kept around for use on wire */ u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ u_int64_t serial; char *key_id; u_int nprincipals; char **principals; u_int64_t valid_after, valid_before; struct sshbuf *critical; struct sshbuf *extensions; struct sshkey *signature_key; char *signature_type; }; /* XXX opaquify? */ struct sshkey { int type; int flags; /* KEY_DSA */ DSA *dsa; /* KEY_ECDSA and KEY_ECDSA_SK */ int ecdsa_nid; /* NID of curve */ /* libcrypto-backed keys */ EVP_PKEY *pkey; /* 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_impl_funcs { u_int (*size)(const struct sshkey *); /* optional */ int (*alloc)(struct sshkey *); /* optional */ void (*cleanup)(struct sshkey *); /* optional */ int (*equal)(const struct sshkey *, const struct sshkey *); int (*serialize_public)(const struct sshkey *, struct sshbuf *, enum sshkey_serialize_rep); int (*deserialize_public)(const char *, struct sshbuf *, struct sshkey *); int (*serialize_private)(const struct sshkey *, struct sshbuf *, enum sshkey_serialize_rep); int (*deserialize_private)(const char *, struct sshbuf *, struct sshkey *); int (*generate)(struct sshkey *, int); /* optional */ int (*copy_public)(const struct sshkey *, struct sshkey *); int (*sign)(struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *, const char *, const char *, u_int); /* optional */ int (*verify)(const struct sshkey *, const u_char *, size_t, const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); }; struct sshkey_impl { const char *name; const char *shortname; const char *sigalg; int type; int nid; int cert; int sigonly; int keybits; const struct sshkey_impl_funcs *funcs; }; struct sshkey *sshkey_new(int); void sshkey_free(struct sshkey *); int sshkey_equal_public(const struct sshkey *, const struct sshkey *); int sshkey_equal(const struct sshkey *, const struct sshkey *); char *sshkey_fingerprint(const struct sshkey *, int, enum sshkey_fp_rep); 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_type_from_shortname(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); /* Returns non-zero if key name match sigalgs pattern list. (handles RSA) */ int sshkey_match_keyname_to_sigalgs(const char *, const char *); int sshkey_to_certified(struct sshkey *); int sshkey_drop_cert(struct sshkey *); int sshkey_cert_copy(const struct sshkey *, struct sshkey *); int sshkey_cert_check_authority(const struct sshkey *, int, int, int, uint64_t, const char *, const char **); int sshkey_cert_check_authority_now(const struct sshkey *, int, int, int, const char *, const char **); int sshkey_cert_check_host(const struct sshkey *, const char *, int , const char *, const char **); size_t sshkey_format_cert_validity(const struct sshkey_cert *, char *, size_t) __attribute__((__bounded__(__string__, 2, 3))); int sshkey_check_cert_sigtype(const struct sshkey *, const char *); int sshkey_certify(struct sshkey *, struct sshkey *, const char *, const char *, const char *); /* 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 *, const char *, u_int, void *); int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *, const char *, const char *, sshkey_certify_signer *, void *); int sshkey_ecdsa_nid_from_name(const char *); int sshkey_curve_name_to_nid(const char *); const char * sshkey_curve_nid_to_name(int); u_int sshkey_curve_nid_to_bits(int); int sshkey_ecdsa_bits_to_nid(int); int sshkey_ecdsa_key_to_nid(const EC_KEY *); int sshkey_ecdsa_pkey_to_nid(EVP_PKEY *); int sshkey_ec_nid_to_hash_alg(int nid); int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *); 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, 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(struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *, const char *, const char *, u_int); int sshkey_verify(const struct sshkey *, const u_char *, size_t, const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); int sshkey_check_sigtype(const u_char *, size_t, const char *); const char *sshkey_sigalg_by_name(const char *); int sshkey_get_sigtype(const u_char *, size_t, char **); /* Signing and verification backend for libcrypto-backed keys */ int sshkey_pkey_digest_sign(EVP_PKEY*, int, u_char **, size_t *, const u_char *, size_t); int sshkey_pkey_digest_verify(EVP_PKEY *, int, const u_char *, size_t, u_char *, size_t); /* 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(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 format, const char *openssh_format_cipher, int openssh_format_rounds); int sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, struct sshkey **keyp, char **commentp); int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp, char **commentp); int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, struct sshkey **pubkeyp); int sshkey_check_rsa_length(const struct sshkey *, int); /* XXX should be internal, but used by ssh-keygen */ int ssh_rsa_complete_crt_parameters(const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, BIGNUM **, BIGNUM **); /* stateful keys (e.g. XMSS) */ int sshkey_set_filename(struct sshkey *, const char *); int sshkey_enable_maxsign(struct sshkey *, u_int32_t); u_int32_t sshkey_signatures_left(const struct sshkey *); int sshkey_private_serialize_maxsign(struct sshkey *key, struct sshbuf *buf, u_int32_t maxsign, int); void sshkey_sig_details_free(struct sshkey_sig_details *); #ifdef WITH_OPENSSL int sshkey_ecdsa_fixup_group(EVP_PKEY *k); /* ssh-ecdsa.c */ #endif #ifdef SSHKEY_INTERNAL int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b); void sshkey_sk_cleanup(struct sshkey *k); int sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b); int sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to); int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key); int sshkey_serialize_private_sk(const struct sshkey *key, struct sshbuf *buf); int sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k); #ifdef WITH_OPENSSL int check_rsa_length(const RSA *rsa); /* XXX remove */ #endif #endif #if !defined(WITH_OPENSSL) # undef RSA # undef DSA # undef EC_KEY # undef EC_GROUP # undef EC_POINT # undef EVP_PKEY #elif !defined(OPENSSL_HAS_ECC) # undef EC_KEY # undef EC_GROUP # undef EC_POINT #endif #endif /* SSHKEY_H */ openssh-10.0p1/PaxHeaders.10889/sshlogin.c100644 001750 001750 0000000003614775415623 0015146xustar0030 atime=1744182234.889476289 openssh-10.0p1/sshlogin.c010064400017500001750000000124611477541562300135350ustar00djmdjm/* $OpenBSD: sshlogin.c,v 1.35 2020/10/18 11:32:02 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * This file performs some of the things login(1) normally does. We cannot * easily use something like login -p -h host -f user, because there are * several different logins around, and it is hard to determined what kind of * login the current system has. Also, we want to be able to execute commands * on a tty. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 1999 Theo de Raadt. All rights reserved. * Copyright (c) 1999 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "sshlogin.h" #include "ssherr.h" #include "loginrec.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "servconf.h" extern struct sshbuf *loginmsg; extern ServerOptions options; /* * Returns the time when the user last logged in. Returns 0 if the * information is not available. This must be called before record_login. * The host the user logged in from will be returned in buf. */ time_t get_last_login_time(uid_t uid, const char *logname, char *buf, size_t bufsize) { struct logininfo li; login_get_lastlog(&li, uid); strlcpy(buf, li.hostname, bufsize); return (time_t)li.tv_sec; } /* * Generate and store last login message. This must be done before * login_login() is called and lastlog is updated. */ static void store_lastlog_message(const char *user, uid_t uid) { #ifndef NO_SSH_LASTLOG # 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; # ifdef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG time_string = sys_auth_get_lastlogin_msg(user, uid); if (time_string != NULL) { if ((r = sshbuf_put(loginmsg, time_string, strlen(time_string))) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(time_string); } # else last_login_time = get_last_login_time(uid, user, hostname, sizeof(hostname)); if (last_login_time != 0) { time_string = ctime(&last_login_time); time_string[strcspn(time_string, "\n")] = '\0'; if (strcmp(hostname, "") == 0) r = sshbuf_putf(loginmsg, "Last login: %s\r\n", time_string); else r = sshbuf_putf(loginmsg, "Last login: %s from %s\r\n", time_string, hostname); if (r != 0) fatal_fr(r, "sshbuf_putf"); } # endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */ #endif /* NO_SSH_LASTLOG */ } /* * Records that the user has logged in. I wish these parts of operating * systems were more standardized. */ void record_login(pid_t pid, const char *tty, const char *user, uid_t uid, const char *host, struct sockaddr *addr, socklen_t addrlen) { struct logininfo *li; /* save previous login details before writing new */ store_lastlog_message(user, uid); li = login_alloc_entry(pid, user, host, tty); login_set_addr(li, addr, addrlen); login_login(li); login_free_entry(li); } #ifdef LOGIN_NEEDS_UTMPX void record_utmp_only(pid_t pid, const char *ttyname, const char *user, const char *host, struct sockaddr *addr, socklen_t addrlen) { struct logininfo *li; li = login_alloc_entry(pid, user, host, ttyname); login_set_addr(li, addr, addrlen); login_utmp_only(li); login_free_entry(li); } #endif /* Records that the user has logged out. */ void record_logout(pid_t pid, const char *tty, const char *user) { struct logininfo *li; li = login_alloc_entry(pid, user, NULL, tty); login_logout(li); login_free_entry(li); } openssh-10.0p1/PaxHeaders.10889/sshlogin.h100644 001750 001750 0000000003614775415623 0015153xustar0030 atime=1744182234.890452706 openssh-10.0p1/sshlogin.h010064400017500001750000000016471477541562300135460ustar00djmdjm/* $OpenBSD: sshlogin.h,v 1.8 2006/08/03 03:34:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ void record_login(pid_t, const char *, const char *, uid_t, const char *, struct sockaddr *, socklen_t); void record_logout(pid_t, const char *, const char *); time_t get_last_login_time(uid_t, const char *, char *, size_t); #ifdef LOGIN_NEEDS_UTMPX void record_utmp_only(pid_t, const char *, const char *, const char *, struct sockaddr *, socklen_t); #endif openssh-10.0p1/PaxHeaders.10889/sshpty.c100644 001750 001750 0000000003614775415623 0014652xustar0030 atime=1744182234.890452706 openssh-10.0p1/sshpty.c010064400017500001750000000132761477541562300132460ustar00djmdjm/* $OpenBSD: sshpty.c,v 1.34 2019/07/04 16:20:10 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Allocating a pseudo-terminal, and making it the controlling tty. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #ifdef HAVE_UTIL_H # include #endif #include #include "sshpty.h" #include "log.h" #include "misc.h" #ifdef HAVE_PTY_H # include #endif #ifndef O_NOCTTY #define O_NOCTTY 0 #endif #ifdef __APPLE__ # include # if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) # define __APPLE_PRIVPTY__ # endif #endif /* * Allocates and opens a pty. Returns 0 if no pty could be allocated, or * nonzero if a pty was successfully allocated. On success, open file * descriptors for the pty and tty sides and the name of the tty side are * returned (the buffer must be able to hold at least 64 characters). */ int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) { /* openpty(3) exists in OSF/1 and some other os'es */ char *name; int i; i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); if (i == -1) { error("openpty: %.100s", strerror(errno)); return 0; } name = ttyname(*ttyfd); if (!name) fatal("openpty returns device for which ttyname fails."); strlcpy(namebuf, name, namebuflen); /* possible truncation */ return 1; } /* Releases the tty. Its ownership is returned to root, and permissions to 0666. */ void pty_release(const char *tty) { #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) == -1) error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno)); #endif /* !__APPLE_PRIVPTY__ && !HAVE_OPENPTY */ } /* Makes the tty the process's controlling tty and sets it to sane modes. */ void pty_make_controlling_tty(int *ttyfd, const char *tty) { int fd; /* First disconnect from the old controlling tty. */ #ifdef TIOCNOTTY fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); if (fd >= 0) { (void) ioctl(fd, TIOCNOTTY, NULL); close(fd); } #endif /* TIOCNOTTY */ if (setsid() == -1) error("setsid: %.100s", strerror(errno)); /* * Verify that we are successfully disconnected from the controlling * tty. */ fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); if (fd >= 0) { error("Failed to disconnect from controlling tty."); close(fd); } /* Make it our controlling tty. */ #ifdef TIOCSCTTY debug("Setting controlling tty using TIOCSCTTY."); if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) error("ioctl(TIOCSCTTY): %.100s", strerror(errno)); #endif /* TIOCSCTTY */ #ifdef NEED_SETPGRP if (setpgrp(0,0) < 0) error("SETPGRP %s",strerror(errno)); #endif /* NEED_SETPGRP */ fd = open(tty, O_RDWR); if (fd == -1) error("%.100s: %.100s", tty, strerror(errno)); else close(fd); /* Verify that we now have a controlling tty. */ fd = open(_PATH_TTY, O_WRONLY); if (fd == -1) error("open /dev/tty failed - could not set controlling tty: %.100s", strerror(errno)); else close(fd); } /* Changes the window size associated with the pty. */ void pty_change_window_size(int ptyfd, u_int row, u_int col, u_int xpixel, u_int ypixel) { struct winsize w; /* may truncate u_int -> u_short */ w.ws_row = row; w.ws_col = col; w.ws_xpixel = xpixel; w.ws_ypixel = ypixel; (void) ioctl(ptyfd, TIOCSWINSZ, &w); } void pty_setowner(struct passwd *pw, const char *tty) { struct group *grp; gid_t gid; mode_t mode; struct stat st; /* 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) ? 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) == -1) fatal("stat(%.100s) failed: %.100s", tty, strerror(errno)); #ifdef WITH_SELINUX ssh_selinux_setup_pty(pw->pw_name, tty); #endif if (st.st_uid != pw->pw_uid || st.st_gid != gid) { 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", tty, (u_int)pw->pw_uid, (u_int)gid, strerror(errno)); else fatal("chown(%.100s, %u, %u) failed: %.100s", tty, (u_int)pw->pw_uid, (u_int)gid, strerror(errno)); } } if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) { if (chmod(tty, mode) == -1) { if (errno == EROFS && (st.st_mode & (S_IRGRP | S_IROTH)) == 0) debug("chmod(%.100s, 0%o) failed: %.100s", tty, (u_int)mode, strerror(errno)); else fatal("chmod(%.100s, 0%o) failed: %.100s", tty, (u_int)mode, strerror(errno)); } } } /* 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 */ } openssh-10.0p1/PaxHeaders.10889/sshpty.h100644 001750 001750 0000000003614775415623 0014657xustar0030 atime=1744182234.890452706 openssh-10.0p1/sshpty.h010064400017500001750000000020351477541562300132420ustar00djmdjm/* $OpenBSD: sshpty.h,v 1.13 2016/11/29 03:54:50 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for allocating a pseudo-terminal and making it the controlling * tty. * * 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 struct termios *get_saved_tio(void); void leave_raw_mode(int); void enter_raw_mode(int); int pty_allocate(int *, int *, char *, size_t); 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); openssh-10.0p1/PaxHeaders.10889/sshsig.c100644 001750 001750 0000000003614775415623 0014620xustar0030 atime=1744182234.890452706 openssh-10.0p1/sshsig.c010064400017500001750000000727501477541562300132160ustar00djmdjm/* $OpenBSD: sshsig.c,v 1.38 2025/02/18 08:02:48 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include #include #include #include #include #include #include "authfd.h" #include "authfile.h" #include "log.h" #include "misc.h" #include "sshbuf.h" #include "sshsig.h" #include "ssherr.h" #include "sshkey.h" #include "match.h" #include "digest.h" #define SIG_VERSION 0x01 #define MAGIC_PREAMBLE "SSHSIG" #define MAGIC_PREAMBLE_LEN (sizeof(MAGIC_PREAMBLE) - 1) #define BEGIN_SIGNATURE "-----BEGIN SSH SIGNATURE-----" #define END_SIGNATURE "-----END SSH SIGNATURE-----" #define RSA_SIGN_ALG "rsa-sha2-512" #define RSA_SIGN_ALLOWED "rsa-sha2-512,rsa-sha2-256" #define HASHALG_DEFAULT "sha512" #define HASHALG_ALLOWED "sha256,sha512" int sshsig_armor(const struct sshbuf *blob, struct sshbuf **out) { struct sshbuf *buf = NULL; int r = SSH_ERR_INTERNAL_ERROR; *out = NULL; if ((buf = sshbuf_new()) == NULL) { error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_putf(buf, "%s\n", BEGIN_SIGNATURE)) != 0) { error_fr(r, "sshbuf_putf"); goto out; } if ((r = sshbuf_dtob64(blob, buf, 1)) != 0) { error_fr(r, "base64 encode signature"); goto out; } if ((r = sshbuf_put(buf, END_SIGNATURE, sizeof(END_SIGNATURE)-1)) != 0 || (r = sshbuf_put_u8(buf, '\n')) != 0) { error_fr(r, "sshbuf_put"); goto out; } /* success */ *out = buf; buf = NULL; /* transferred */ r = 0; out: sshbuf_free(buf); return r; } int sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out) { int r; size_t eoffset = 0; struct sshbuf *buf = NULL; struct sshbuf *sbuf = NULL; char *b64 = NULL; if ((sbuf = sshbuf_fromb(sig)) == NULL) { error_f("sshbuf_fromb failed"); return SSH_ERR_ALLOC_FAIL; } /* Expect and consume preamble + lf/crlf */ if ((r = sshbuf_cmp(sbuf, 0, BEGIN_SIGNATURE, sizeof(BEGIN_SIGNATURE)-1)) != 0) { error("Couldn't parse signature: missing header"); goto done; } if ((r = sshbuf_consume(sbuf, sizeof(BEGIN_SIGNATURE)-1)) != 0) { error_fr(r, "consume"); goto done; } if ((r = sshbuf_cmp(sbuf, 0, "\r\n", 2)) == 0) eoffset = 2; else if ((r = sshbuf_cmp(sbuf, 0, "\n", 1)) == 0) eoffset = 1; else { r = SSH_ERR_INVALID_FORMAT; error_f("no header eol"); goto done; } if ((r = sshbuf_consume(sbuf, eoffset)) != 0) { error_fr(r, "consume eol"); goto done; } /* Find and consume lf + suffix (any prior cr would be ignored) */ if ((r = sshbuf_find(sbuf, 0, "\n" END_SIGNATURE, sizeof(END_SIGNATURE), &eoffset)) != 0) { error("Couldn't parse signature: missing footer"); goto done; } if ((r = sshbuf_consume_end(sbuf, sshbuf_len(sbuf)-eoffset)) != 0) { error_fr(r, "consume"); goto done; } if ((b64 = sshbuf_dup_string(sbuf)) == NULL) { error_f("sshbuf_dup_string failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((buf = sshbuf_new()) == NULL) { error_f("sshbuf_new() failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((r = sshbuf_b64tod(buf, b64)) != 0) { error_fr(r, "decode base64"); goto done; } /* success */ *out = buf; r = 0; buf = NULL; /* transferred */ done: sshbuf_free(buf); sshbuf_free(sbuf); free(b64); return r; } static int sshsig_wrap_sign(struct sshkey *key, const char *hashalg, const char *sk_provider, const char *sk_pin, const struct sshbuf *h_message, const char *sig_namespace, struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) { int r; size_t slen = 0; u_char *sig = NULL; struct sshbuf *blob = NULL; struct sshbuf *tosign = NULL; const char *sign_alg = NULL; if ((tosign = sshbuf_new()) == NULL || (blob = sshbuf_new()) == NULL) { error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((r = sshbuf_put(tosign, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_put_cstring(tosign, sig_namespace)) != 0 || (r = sshbuf_put_string(tosign, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_cstring(tosign, hashalg)) != 0 || (r = sshbuf_put_stringb(tosign, h_message)) != 0) { error_fr(r, "assemble message to sign"); goto done; } /* If using RSA keys then default to a good signature algorithm */ if (sshkey_type_plain(key->type) == KEY_RSA) { sign_alg = RSA_SIGN_ALG; if (strcmp(hashalg, "sha256") == 0) sign_alg = "rsa-sha2-256"; else if (strcmp(hashalg, "sha512") == 0) sign_alg = "rsa-sha2-512"; } if (signer != NULL) { if ((r = signer(key, &sig, &slen, sshbuf_ptr(tosign), sshbuf_len(tosign), sign_alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) { error_r(r, "Couldn't sign message (signer)"); goto done; } } else { if ((r = sshkey_sign(key, &sig, &slen, sshbuf_ptr(tosign), sshbuf_len(tosign), sign_alg, sk_provider, sk_pin, 0)) != 0) { error_r(r, "Couldn't sign message"); goto done; } } if ((r = sshbuf_put(blob, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_put_u32(blob, SIG_VERSION)) != 0 || (r = sshkey_puts(key, blob)) != 0 || (r = sshbuf_put_cstring(blob, sig_namespace)) != 0 || (r = sshbuf_put_string(blob, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_cstring(blob, hashalg)) != 0 || (r = sshbuf_put_string(blob, sig, slen)) != 0) { error_fr(r, "assemble signature object"); goto done; } if (out != NULL) { *out = blob; blob = NULL; } r = 0; done: free(sig); sshbuf_free(blob); sshbuf_free(tosign); return r; } /* Check preamble and version. */ static int sshsig_parse_preamble(struct sshbuf *buf) { int r = SSH_ERR_INTERNAL_ERROR; uint32_t sversion; if ((r = sshbuf_cmp(buf, 0, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_consume(buf, (sizeof(MAGIC_PREAMBLE)-1))) != 0 || (r = sshbuf_get_u32(buf, &sversion)) != 0) { error("Couldn't verify signature: invalid format"); return r; } if (sversion > SIG_VERSION) { error("Signature version %lu is larger than supported " "version %u", (unsigned long)sversion, SIG_VERSION); return SSH_ERR_INVALID_FORMAT; } return 0; } static int sshsig_check_hashalg(const char *hashalg) { if (hashalg == NULL || match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1) return 0; error_f("unsupported hash algorithm \"%.100s\"", hashalg); return SSH_ERR_SIGN_ALG_UNSUPPORTED; } static int sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp) { struct sshbuf *buf = NULL; char *hashalg = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (hashalgp != NULL) *hashalgp = NULL; if ((buf = sshbuf_fromb(signature)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshsig_parse_preamble(buf)) != 0) goto done; if ((r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 || (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 || (r = sshbuf_get_string(buf, NULL, NULL)) != 0 || (r = sshbuf_get_cstring(buf, &hashalg, NULL)) != 0 || (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0) { error_fr(r, "parse signature object"); goto done; } /* success */ r = 0; *hashalgp = hashalg; hashalg = NULL; done: free(hashalg); sshbuf_free(buf); return r; } static int sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, const struct sshbuf *h_message, const char *expect_namespace, struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *buf = NULL, *toverify = NULL; struct sshkey *key = NULL; const u_char *sig; char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL; size_t siglen; debug_f("verify message length %zu", sshbuf_len(h_message)); if (sig_details != NULL) *sig_details = NULL; if (sign_keyp != NULL) *sign_keyp = NULL; if ((toverify = sshbuf_new()) == NULL) { error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 || (r = sshbuf_put_string(toverify, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_cstring(toverify, hashalg)) != 0 || (r = sshbuf_put_stringb(toverify, h_message)) != 0) { error_fr(r, "assemble message to verify"); goto done; } if ((r = sshsig_parse_preamble(signature)) != 0) goto done; if ((r = sshkey_froms(signature, &key)) != 0 || (r = sshbuf_get_cstring(signature, &got_namespace, NULL)) != 0 || (r = sshbuf_get_string(signature, NULL, NULL)) != 0 || (r = sshbuf_get_cstring(signature, &sig_hashalg, NULL)) != 0 || (r = sshbuf_get_string_direct(signature, &sig, &siglen)) != 0) { error_fr(r, "parse signature object"); goto done; } if (sshbuf_len(signature) != 0) { error("Signature contains trailing data"); r = SSH_ERR_INVALID_FORMAT; goto done; } if (strcmp(expect_namespace, got_namespace) != 0) { error("Couldn't verify signature: namespace does not match"); debug_f("expected namespace \"%s\" received \"%s\"", expect_namespace, got_namespace); r = SSH_ERR_SIGNATURE_INVALID; goto done; } if (strcmp(hashalg, sig_hashalg) != 0) { error("Couldn't verify signature: hash algorithm mismatch"); debug_f("expected algorithm \"%s\" received \"%s\"", hashalg, sig_hashalg); r = SSH_ERR_SIGNATURE_INVALID; goto done; } /* Ensure that RSA keys use an acceptable signature algorithm */ if (sshkey_type_plain(key->type) == KEY_RSA) { if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) { error_r(r, "Couldn't verify signature: unable to get " "signature type"); goto done; } if (match_pattern_list(sigtype, RSA_SIGN_ALLOWED, 0) != 1) { error("Couldn't verify signature: unsupported RSA " "signature algorithm %s", sigtype); r = SSH_ERR_SIGN_ALG_UNSUPPORTED; goto done; } } if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify), sshbuf_len(toverify), NULL, 0, sig_details)) != 0) { error_r(r, "Signature verification failed"); goto done; } /* success */ r = 0; if (sign_keyp != NULL) { *sign_keyp = key; key = NULL; /* transferred */ } done: free(got_namespace); free(sigtype); free(sig_hashalg); sshbuf_free(buf); sshbuf_free(toverify); sshkey_free(key); return r; } static int hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp) { char *hex, hash[SSH_DIGEST_MAX_LENGTH]; int alg, r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; *bp = NULL; memset(hash, 0, sizeof(hash)); if ((r = sshsig_check_hashalg(hashalg)) != 0) return r; if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { error_f("can't look up hash algorithm %s", hashalg); return SSH_ERR_INTERNAL_ERROR; } if ((r = ssh_digest_buffer(alg, m, hash, sizeof(hash))) != 0) { error_fr(r, "ssh_digest_buffer"); return r; } if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { debug3_f("final hash: %s", hex); freezero(hex, strlen(hex)); } if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { error_fr(r, "sshbuf_put"); goto out; } *bp = b; b = NULL; /* transferred */ /* success */ r = 0; out: sshbuf_free(b); explicit_bzero(hash, sizeof(hash)); return r; } int sshsig_signb(struct sshkey *key, const char *hashalg, const char *sk_provider, const char *sk_pin, const struct sshbuf *message, const char *sig_namespace, struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (hashalg == NULL) hashalg = HASHALG_DEFAULT; if (out != NULL) *out = NULL; if ((r = hash_buffer(message, hashalg, &b)) != 0) { error_fr(r, "hash buffer"); goto out; } if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, sig_namespace, out, signer, signer_ctx)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } int sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message, const char *expect_namespace, struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; char *hashalg = NULL; if (sig_details != NULL) *sig_details = NULL; if (sign_keyp != NULL) *sign_keyp = NULL; if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) return r; debug_f("signature made with hash \"%s\"", hashalg); if ((r = hash_buffer(message, hashalg, &b)) != 0) { error_fr(r, "hash buffer"); goto out; } if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, sign_keyp, sig_details)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); free(hashalg); return r; } static int hash_file(int fd, const char *hashalg, struct sshbuf **bp) { char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH]; ssize_t n, total = 0; struct ssh_digest_ctx *ctx = NULL; int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; *bp = NULL; memset(hash, 0, sizeof(hash)); if ((r = sshsig_check_hashalg(hashalg)) != 0) return r; if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { error_f("can't look up hash algorithm %s", hashalg); return SSH_ERR_INTERNAL_ERROR; } if ((ctx = ssh_digest_start(alg)) == NULL) { error_f("ssh_digest_start failed"); return SSH_ERR_INTERNAL_ERROR; } for (;;) { if ((n = read(fd, rbuf, sizeof(rbuf))) == -1) { if (errno == EINTR || errno == EAGAIN) continue; oerrno = errno; error_f("read: %s", strerror(errno)); errno = oerrno; r = SSH_ERR_SYSTEM_ERROR; goto out; } else if (n == 0) { debug2_f("hashed %zu bytes", total); break; /* EOF */ } total += (size_t)n; if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) { error_fr(r, "ssh_digest_update"); goto out; } } if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) { error_fr(r, "ssh_digest_final"); goto out; } if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { debug3_f("final hash: %s", hex); freezero(hex, strlen(hex)); } if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { error_fr(r, "sshbuf_put"); goto out; } *bp = b; b = NULL; /* transferred */ /* success */ r = 0; out: oerrno = errno; sshbuf_free(b); ssh_digest_free(ctx); explicit_bzero(hash, sizeof(hash)); errno = oerrno; return r; } int sshsig_sign_fd(struct sshkey *key, const char *hashalg, const char *sk_provider, const char *sk_pin, int fd, const char *sig_namespace, struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (hashalg == NULL) hashalg = HASHALG_DEFAULT; if (out != NULL) *out = NULL; if ((r = hash_file(fd, hashalg, &b)) != 0) { error_fr(r, "hash_file"); return r; } if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, sig_namespace, out, signer, signer_ctx)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } int sshsig_verify_fd(struct sshbuf *signature, int fd, const char *expect_namespace, struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; char *hashalg = NULL; if (sig_details != NULL) *sig_details = NULL; if (sign_keyp != NULL) *sign_keyp = NULL; if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) return r; debug_f("signature made with hash \"%s\"", hashalg); if ((r = hash_file(fd, hashalg, &b)) != 0) { error_fr(r, "hash_file"); goto out; } if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, sign_keyp, sig_details)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); free(hashalg); return r; } struct sshsigopt { int ca; char *namespaces; uint64_t valid_after, valid_before; }; struct sshsigopt * sshsigopt_parse(const char *opts, const char *path, u_long linenum, const char **errstrp) { struct sshsigopt *ret; int r; char *opt; const char *errstr = NULL; if ((ret = calloc(1, sizeof(*ret))) == NULL) return NULL; if (opts == NULL || *opts == '\0') return ret; /* Empty options yields empty options :) */ while (*opts && *opts != ' ' && *opts != '\t') { /* flag options */ if ((r = opt_flag("cert-authority", 0, &opts)) != -1) { ret->ca = 1; } else if (opt_match(&opts, "namespaces")) { if (ret->namespaces != NULL) { errstr = "multiple \"namespaces\" clauses"; goto fail; } ret->namespaces = opt_dequote(&opts, &errstr); if (ret->namespaces == NULL) goto fail; } else if (opt_match(&opts, "valid-after")) { if (ret->valid_after != 0) { errstr = "multiple \"valid-after\" clauses"; goto fail; } if ((opt = opt_dequote(&opts, &errstr)) == NULL) goto fail; if (parse_absolute_time(opt, &ret->valid_after) != 0 || ret->valid_after == 0) { free(opt); errstr = "invalid \"valid-after\" time"; goto fail; } free(opt); } else if (opt_match(&opts, "valid-before")) { if (ret->valid_before != 0) { errstr = "multiple \"valid-before\" clauses"; goto fail; } if ((opt = opt_dequote(&opts, &errstr)) == NULL) goto fail; if (parse_absolute_time(opt, &ret->valid_before) != 0 || ret->valid_before == 0) { free(opt); errstr = "invalid \"valid-before\" time"; goto fail; } free(opt); } /* * Skip the comma, and move to the next option * (or break out if there are no more). */ if (*opts == '\0' || *opts == ' ' || *opts == '\t') break; /* End of options. */ /* Anything other than a comma is an unknown option */ if (*opts != ',') { errstr = "unknown key option"; goto fail; } opts++; if (*opts == '\0') { errstr = "unexpected end-of-options"; goto fail; } } /* final consistency check */ if (ret->valid_after != 0 && ret->valid_before != 0 && ret->valid_before <= ret->valid_after) { errstr = "\"valid-before\" time is before \"valid-after\""; goto fail; } /* success */ return ret; fail: if (errstrp != NULL) *errstrp = errstr; sshsigopt_free(ret); return NULL; } void sshsigopt_free(struct sshsigopt *opts) { if (opts == NULL) return; free(opts->namespaces); free(opts); } static int parse_principals_key_and_options(const char *path, u_long linenum, char *line, const char *required_principal, char **principalsp, struct sshkey **keyp, struct sshsigopt **sigoptsp) { char *opts = NULL, *tmp, *cp, *principals = NULL; const char *reason = NULL; struct sshsigopt *sigopts = NULL; struct sshkey *key = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (principalsp != NULL) *principalsp = NULL; if (sigoptsp != NULL) *sigoptsp = NULL; if (keyp != NULL) *keyp = NULL; cp = line; cp = cp + strspn(cp, " \t\n\r"); /* skip leading whitespace */ if (*cp == '#' || *cp == '\0') return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */ /* format: identity[,identity...] [option[,option...]] key */ if ((tmp = strdelimw(&cp)) == NULL || cp == NULL) { error("%s:%lu: invalid line", path, linenum); r = SSH_ERR_INVALID_FORMAT; goto out; } if ((principals = strdup(tmp)) == NULL) { error_f("strdup failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } /* * Bail out early if we're looking for a particular principal and this * line does not list it. */ if (required_principal != NULL) { if (match_pattern_list(required_principal, principals, 0) != 1) { /* principal didn't match */ r = SSH_ERR_KEY_NOT_FOUND; goto out; } debug_f("%s:%lu: matched principal \"%s\"", path, linenum, required_principal); } if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { error_f("sshkey_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if (sshkey_read(key, &cp) != 0) { /* no key? Check for options */ opts = cp; if (sshkey_advance_past_options(&cp) != 0) { error("%s:%lu: invalid options", path, linenum); r = SSH_ERR_INVALID_FORMAT; goto out; } if (cp == NULL || *cp == '\0') { error("%s:%lu: missing key", path, linenum); r = SSH_ERR_INVALID_FORMAT; goto out; } *cp++ = '\0'; skip_space(&cp); if (sshkey_read(key, &cp) != 0) { error("%s:%lu: invalid key", path, linenum); r = SSH_ERR_INVALID_FORMAT; goto out; } } debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts); if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) { error("%s:%lu: bad options: %s", path, linenum, reason); r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ if (principalsp != NULL) { *principalsp = principals; principals = NULL; /* transferred */ } if (sigoptsp != NULL) { *sigoptsp = sigopts; sigopts = NULL; /* transferred */ } if (keyp != NULL) { *keyp = key; key = NULL; /* transferred */ } r = 0; out: free(principals); sshsigopt_free(sigopts); sshkey_free(key); return r; } static int cert_filter_principals(const char *path, u_long linenum, char **principalsp, const struct sshkey *cert, uint64_t verify_time) { char *cp, *oprincipals, *principals; const char *reason; struct sshbuf *nprincipals; int r = SSH_ERR_INTERNAL_ERROR, success = 0; u_int i; oprincipals = principals = *principalsp; *principalsp = NULL; if ((nprincipals = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } while ((cp = strsep(&principals, ",")) != NULL && *cp != '\0') { /* Check certificate validity */ if ((r = sshkey_cert_check_authority(cert, 0, 1, 0, verify_time, NULL, &reason)) != 0) { debug("%s:%lu: principal \"%s\" not authorized: %s", path, linenum, cp, reason); continue; } /* Return all matching principal names from the cert */ for (i = 0; i < cert->cert->nprincipals; i++) { if (match_pattern(cert->cert->principals[i], cp)) { if ((r = sshbuf_putf(nprincipals, "%s%s", sshbuf_len(nprincipals) != 0 ? "," : "", cert->cert->principals[i])) != 0) { error_f("buffer error"); goto out; } } } } if (sshbuf_len(nprincipals) == 0) { error("%s:%lu: no valid principals found", path, linenum); r = SSH_ERR_KEY_CERT_INVALID; goto out; } if ((principals = sshbuf_dup_string(nprincipals)) == NULL) { error_f("buffer error"); r = SSH_ERR_ALLOC_FAIL; goto out; } /* success */ success = 1; *principalsp = principals; out: sshbuf_free(nprincipals); free(oprincipals); return success ? 0 : r; } static int check_allowed_keys_line(const char *path, u_long linenum, char *line, const struct sshkey *sign_key, const char *principal, const char *sig_namespace, uint64_t verify_time, char **principalsp) { struct sshkey *found_key = NULL; char *principals = NULL; int r, success = 0; const char *reason = NULL; struct sshsigopt *sigopts = NULL; char tvalid[64], tverify[64]; if (principalsp != NULL) *principalsp = NULL; /* Parse the line */ if ((r = parse_principals_key_and_options(path, linenum, line, principal, &principals, &found_key, &sigopts)) != 0) { /* error already logged */ goto done; } if (!sigopts->ca && sshkey_equal(found_key, sign_key)) { /* Exact match of key */ debug("%s:%lu: matched key", path, linenum); } else if (sigopts->ca && sshkey_is_cert(sign_key) && sshkey_equal_public(sign_key->cert->signature_key, found_key)) { if (principal) { /* Match certificate CA key with specified principal */ if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0, verify_time, principal, &reason)) != 0) { error("%s:%lu: certificate not authorized: %s", path, linenum, reason); goto done; } debug("%s:%lu: matched certificate CA key", path, linenum); } else { /* No principal specified - find all matching ones */ if ((r = cert_filter_principals(path, linenum, &principals, sign_key, verify_time)) != 0) { /* error already displayed */ debug_r(r, "%s:%lu: cert_filter_principals", path, linenum); goto done; } debug("%s:%lu: matched certificate CA key", path, linenum); } } else { /* Didn't match key */ goto done; } /* Check whether options preclude the use of this key */ if (sigopts->namespaces != NULL && sig_namespace != NULL && match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) { error("%s:%lu: key is not permitted for use in signature " "namespace \"%s\"", path, linenum, sig_namespace); goto done; } /* check key time validity */ format_absolute_time((uint64_t)verify_time, tverify, sizeof(tverify)); if (sigopts->valid_after != 0 && (uint64_t)verify_time < sigopts->valid_after) { format_absolute_time(sigopts->valid_after, tvalid, sizeof(tvalid)); error("%s:%lu: key is not yet valid: " "verify time %s < valid-after %s", path, linenum, tverify, tvalid); goto done; } if (sigopts->valid_before != 0 && (uint64_t)verify_time > sigopts->valid_before) { format_absolute_time(sigopts->valid_before, tvalid, sizeof(tvalid)); error("%s:%lu: key has expired: " "verify time %s > valid-before %s", path, linenum, tverify, tvalid); goto done; } success = 1; done: if (success && principalsp != NULL) { *principalsp = principals; principals = NULL; /* transferred */ } free(principals); sshkey_free(found_key); sshsigopt_free(sigopts); return success ? 0 : SSH_ERR_KEY_NOT_FOUND; } int sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key, const char *principal, const char *sig_namespace, uint64_t verify_time) { FILE *f = NULL; char *line = NULL; size_t linesize = 0; u_long linenum = 0; int r = SSH_ERR_KEY_NOT_FOUND, oerrno; /* Check key and principal against file */ if ((f = fopen(path, "r")) == NULL) { oerrno = errno; error("Unable to open allowed keys file \"%s\": %s", path, strerror(errno)); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } while (getline(&line, &linesize, f) != -1) { linenum++; r = check_allowed_keys_line(path, linenum, line, sign_key, principal, sig_namespace, verify_time, NULL); free(line); line = NULL; linesize = 0; if (r == SSH_ERR_KEY_NOT_FOUND) continue; else if (r == 0) { /* success */ fclose(f); return 0; } else break; } /* Either we hit an error parsing or we simply didn't find the key */ fclose(f); free(line); return r; } int sshsig_find_principals(const char *path, const struct sshkey *sign_key, uint64_t verify_time, char **principals) { FILE *f = NULL; char *line = NULL; size_t linesize = 0; u_long linenum = 0; int r = SSH_ERR_KEY_NOT_FOUND, oerrno; if ((f = fopen(path, "r")) == NULL) { oerrno = errno; error("Unable to open allowed keys file \"%s\": %s", path, strerror(errno)); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } while (getline(&line, &linesize, f) != -1) { linenum++; r = check_allowed_keys_line(path, linenum, line, sign_key, NULL, NULL, verify_time, principals); free(line); line = NULL; linesize = 0; if (r == SSH_ERR_KEY_NOT_FOUND) continue; else if (r == 0) { /* success */ fclose(f); return 0; } else break; } free(line); /* Either we hit an error parsing or we simply didn't find the key */ if (ferror(f) != 0) { oerrno = errno; fclose(f); error("Unable to read allowed keys file \"%s\": %s", path, strerror(errno)); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } fclose(f); return r; } int sshsig_match_principals(const char *path, const char *principal, char ***principalsp, size_t *nprincipalsp) { FILE *f = NULL; char *found, *line = NULL, **principals = NULL, **tmp; size_t i, nprincipals = 0, linesize = 0; u_long linenum = 0; int oerrno = 0, r, ret = 0; if (principalsp != NULL) *principalsp = NULL; if (nprincipalsp != NULL) *nprincipalsp = 0; /* Check key and principal against file */ if ((f = fopen(path, "r")) == NULL) { oerrno = errno; error("Unable to open allowed keys file \"%s\": %s", path, strerror(errno)); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } while (getline(&line, &linesize, f) != -1) { linenum++; /* Parse the line */ if ((r = parse_principals_key_and_options(path, linenum, line, principal, &found, NULL, NULL)) != 0) { if (r == SSH_ERR_KEY_NOT_FOUND) continue; ret = r; oerrno = errno; break; /* unexpected error */ } if ((tmp = recallocarray(principals, nprincipals, nprincipals + 1, sizeof(*principals))) == NULL) { ret = SSH_ERR_ALLOC_FAIL; free(found); break; } principals = tmp; principals[nprincipals++] = found; /* transferred */ free(line); line = NULL; linesize = 0; } fclose(f); if (ret == 0) { if (nprincipals == 0) ret = SSH_ERR_KEY_NOT_FOUND; if (nprincipalsp != 0) *nprincipalsp = nprincipals; if (principalsp != NULL) { *principalsp = principals; principals = NULL; /* transferred */ nprincipals = 0; } } for (i = 0; i < nprincipals; i++) free(principals[i]); free(principals); errno = oerrno; return ret; } int sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey) { struct sshkey *pk = NULL; int r = SSH_ERR_SIGNATURE_INVALID; if (pubkey == NULL) return SSH_ERR_INTERNAL_ERROR; if ((r = sshsig_parse_preamble(signature)) != 0) return r; if ((r = sshkey_froms(signature, &pk)) != 0) return r; *pubkey = pk; pk = NULL; return 0; } openssh-10.0p1/PaxHeaders.10889/sshsig.h100644 001750 001750 0000000003614775415623 0014625xustar0030 atime=1744182234.890452706 openssh-10.0p1/sshsig.h010064400017500001750000000077441477541562300132240ustar00djmdjm/* $OpenBSD: sshsig.h,v 1.11 2021/11/27 07:14:46 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 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 *, 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 char *sk_pin, const struct sshbuf *message, const char *sig_namespace, struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); /* * Verifies that a detached signature is valid and optionally returns key * 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, const char *sk_pin, int fd, const char *sig_namespace, struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); /* * Verifies that a detached signature over a file is valid and optionally * 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, uint64_t verify_time); /* 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, uint64_t verify_time, char **principal); /* Find all principals in allowed_keys file matching *principal */ int sshsig_match_principals(const char *path, const char *principal, char ***principalsp, size_t *nprincipalsp); #endif /* SSHSIG_H */ openssh-10.0p1/PaxHeaders.10889/sshtty.c100644 001750 001750 0000000003614775415623 0014656xustar0030 atime=1744182234.890452706 openssh-10.0p1/sshtty.c010064400017500001750000000057131477541562300132470ustar00djmdjm/* $OpenBSD: sshtty.c,v 1.14 2010/01/09 05:04:24 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Kevin Steves. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include "sshpty.h" static struct termios _saved_tio; static int _in_raw_mode = 0; struct termios * get_saved_tio(void) { return _in_raw_mode ? &_saved_tio : NULL; } void leave_raw_mode(int quiet) { if (!_in_raw_mode) return; if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) { if (!quiet) perror("tcsetattr"); } else _in_raw_mode = 0; } void enter_raw_mode(int quiet) { struct termios tio; if (tcgetattr(fileno(stdin), &tio) == -1) { if (!quiet) perror("tcgetattr"); return; } _saved_tio = tio; tio.c_iflag |= IGNPAR; tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); #ifdef IUCLC tio.c_iflag &= ~IUCLC; #endif tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); #ifdef IEXTEN tio.c_lflag &= ~IEXTEN; #endif tio.c_oflag &= ~OPOST; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1) { if (!quiet) perror("tcsetattr"); } else _in_raw_mode = 1; } openssh-10.0p1/PaxHeaders.10889/survey.sh.in100644 001750 001750 0000000003614775415623 0015452xustar0030 atime=1744182234.890452706 openssh-10.0p1/survey.sh.in010064400017500001750000000032711477541562300140400ustar00djmdjm#!/bin/sh # # Copyright (c) 2004, 2005 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. host="@host@" AWK="@AWK@" CC="@CC@" CPP="@CPP@" CFLAGS="@CFLAGS@" CPPFLAGS="@CPPFLAGS@" LDFLAGS="@LDFLAGS@" LIBS="@LIBS@" # Note format: # identifier: [data] CRCR echo "openssh-survey-version: 1" echo echo "openssh-version: `./ssh -V 2>&1`" echo configinv=`$AWK '/^ \\\$.*configure/' config.log | sed 's/^ \\\$ //g'` echo "configure-invocation: $configinv" echo echo "host: $host" echo echo "uname: `uname`" echo echo "uname-r: `uname -r`" echo echo "uname-m: `uname -m`" echo echo "uname-p: `uname -p`" echo echo "oslevel: `oslevel 2>/dev/null`" echo echo "oslevel-r: `oslevel -r 2>/dev/null`" echo echo "cc: $CC" echo echo "cflags: $CFLAGS" echo echo "cppflags: $CPPFLAGS" echo echo "ldflags: $LDFLAGS" echo echo "libs: $LIBS" echo echo "ccver-v: `$CC -v 2>&1 | sed '/^[ \t]*$/d'`" echo echo "ccver-V: `$CC -V 2>&1 | sed '/^[ \t]*$/d'`" echo echo "cppdefines:" ${CPP} -dM - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * SSH2 tty modes support by Kevin Steves. * Copyright (c) 2001 Kevin Steves. 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. */ /* * Encoding and decoding of terminal modes in a portable way. * Much of the format is defined in ttymodes.h; it is included multiple times * into this file with the appropriate macro definitions to generate the * suitable code. */ #include "includes.h" #include #include #include #include #include #include "packet.h" #include "log.h" #include "compat.h" #include "sshbuf.h" #include "ssherr.h" #define TTY_OP_END 0 /* * uint32 (u_int) follows speed. */ #define TTY_OP_ISPEED 128 #define TTY_OP_OSPEED 129 /* * Converts POSIX speed_t to a baud rate. The values of the * constants for speed_t are not themselves portable. */ static int speed_to_baud(speed_t speed) { switch (speed) { case B0: return 0; case B50: return 50; case B75: return 75; case B110: return 110; case B134: return 134; case B150: return 150; case B200: return 200; case B300: return 300; case B600: return 600; case B1200: return 1200; case B1800: return 1800; case B2400: return 2400; case B4800: return 4800; case B9600: return 9600; #ifdef B19200 case B19200: return 19200; #else /* B19200 */ #ifdef EXTA case EXTA: return 19200; #endif /* EXTA */ #endif /* B19200 */ #ifdef B38400 case B38400: return 38400; #else /* B38400 */ #ifdef EXTB case EXTB: return 38400; #endif /* EXTB */ #endif /* B38400 */ #ifdef B7200 case B7200: return 7200; #endif /* B7200 */ #ifdef B14400 case B14400: return 14400; #endif /* B14400 */ #ifdef B28800 case B28800: return 28800; #endif /* B28800 */ #ifdef B57600 case B57600: return 57600; #endif /* B57600 */ #ifdef B76800 case B76800: return 76800; #endif /* B76800 */ #ifdef B115200 case B115200: return 115200; #endif /* B115200 */ #ifdef B230400 case B230400: return 230400; #endif /* B230400 */ default: return 9600; } } /* * Converts a numeric baud rate to a POSIX speed_t. */ static speed_t baud_to_speed(int baud) { switch (baud) { case 0: return B0; case 50: return B50; case 75: return B75; case 110: return B110; case 134: return B134; case 150: return B150; case 200: return B200; case 300: return B300; case 600: return B600; case 1200: return B1200; case 1800: return B1800; case 2400: return B2400; case 4800: return B4800; case 9600: return B9600; #ifdef B19200 case 19200: return B19200; #else /* B19200 */ #ifdef EXTA case 19200: return EXTA; #endif /* EXTA */ #endif /* B19200 */ #ifdef B38400 case 38400: return B38400; #else /* B38400 */ #ifdef EXTB case 38400: return EXTB; #endif /* EXTB */ #endif /* B38400 */ #ifdef B7200 case 7200: return B7200; #endif /* B7200 */ #ifdef B14400 case 14400: return B14400; #endif /* B14400 */ #ifdef B28800 case 28800: return B28800; #endif /* B28800 */ #ifdef B57600 case 57600: return B57600; #endif /* B57600 */ #ifdef B76800 case 76800: return B76800; #endif /* B76800 */ #ifdef B115200 case 115200: return B115200; #endif /* B115200 */ #ifdef B230400 case 230400: return B230400; #endif /* B230400 */ default: return B9600; } } /* * Encode a special character into SSH line format. */ static u_int special_char_encode(cc_t c) { #ifdef _POSIX_VDISABLE if (c == _POSIX_VDISABLE) return 255; #endif /* _POSIX_VDISABLE */ return c; } /* * Decode a special character from SSH line format. */ static cc_t special_char_decode(u_int c) { #ifdef _POSIX_VDISABLE if (c == 255) return _POSIX_VDISABLE; #endif /* _POSIX_VDISABLE */ return c; } /* * Encodes terminal modes for the terminal referenced by fd * or tiop in a portable manner, and appends the modes to a packet * being constructed. */ void ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop) { struct termios tio; struct sshbuf *buf; int r, ibaud, obaud; if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (tiop == NULL) { if (fd == -1) { debug_f("no fd or tio"); goto end; } if (tcgetattr(fd, &tio) == -1) { logit("tcgetattr: %.100s", strerror(errno)); goto end; } } else tio = *tiop; /* Store input and output baud rates. */ 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_fr(r, "compose"); /* Store values of mode flags. */ #define TTYCHAR(NAME, OP) \ if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ (r = sshbuf_put_u32(buf, \ special_char_encode(tio.c_cc[NAME]))) != 0) \ fatal_fr(r, "compose %s", #NAME); #define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */ #define TTYMODE(NAME, FIELD, OP) \ if (OP == SSH_TTYMODE_IUTF8 && (ssh->compat & SSH_BUG_UTF8TTYMODE)) { \ debug3_f("SSH_BUG_UTF8TTYMODE"); \ } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \ fatal_fr(r, "compose %s", #NAME); #include "ttymodes.h" #undef TTYCHAR #undef TTYMODE end: /* Mark end of mode data. */ if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 || (r = sshpkt_put_stringb(ssh, buf)) != 0) fatal_fr(r, "compose end"); sshbuf_free(buf); } /* * Decodes terminal modes for the terminal referenced by fd in a portable * manner from a packet being read. */ void ssh_tty_parse_modes(struct ssh *ssh, int fd) { struct termios tio; 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_fr(r, "parse"); if (len == 0) return; if ((buf = sshbuf_from(data, len)) == NULL) { error_f("sshbuf_from failed"); return; } /* * Get old attributes for the terminal. We will modify these * flags. I am hoping that if there are any machine-specific * modes, they will initially have reasonable values. */ if (tcgetattr(fd, &tio) == -1) { logit("tcgetattr: %.100s", strerror(errno)); failure = -1; } while (sshbuf_len(buf) > 0) { if ((r = sshbuf_get_u8(buf, &opcode)) != 0) fatal_fr(r, "parse opcode"); switch (opcode) { case TTY_OP_END: goto set; case TTY_OP_ISPEED: if ((r = sshbuf_get_u32(buf, &baud)) != 0) fatal_fr(r, "parse ispeed"); if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) error("cfsetispeed failed for %d", baud); break; case TTY_OP_OSPEED: if ((r = sshbuf_get_u32(buf, &baud)) != 0) fatal_fr(r, "parse ospeed"); if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) error("cfsetospeed failed for %d", baud); break; #define TTYCHAR(NAME, OP) \ case OP: \ if ((r = sshbuf_get_u32(buf, &u)) != 0) \ fatal_fr(r, "parse %s", #NAME); \ tio.c_cc[NAME] = special_char_decode(u); \ break; #define TTYMODE(NAME, FIELD, OP) \ case OP: \ if ((r = sshbuf_get_u32(buf, &u)) != 0) \ fatal_fr(r, "parse %s", #NAME); \ if (u) \ tio.FIELD |= NAME; \ else \ tio.FIELD &= ~NAME; \ break; #include "ttymodes.h" #undef TTYCHAR #undef TTYMODE default: debug("Ignoring unsupported tty mode opcode %d (0x%x)", opcode, opcode); /* * 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_fr(r, "parse arg"); break; } else { logit_f("unknown opcode %d", opcode); goto set; } } } set: len = sshbuf_len(buf); sshbuf_free(buf); if (len > 0) { logit_f("%zu bytes left", len); return; /* Don't process bytes passed */ } if (failure == -1) return; /* Packet parsed ok but tcgetattr() failed */ /* Set the new modes for the terminal. */ if (tcsetattr(fd, TCSANOW, &tio) == -1) logit("Setting tty modes failed: %.100s", strerror(errno)); } openssh-10.0p1/PaxHeaders.10889/ttymodes.h100644 001750 001750 0000000003614775415623 0015175xustar0030 atime=1744182234.891429974 openssh-10.0p1/ttymodes.h010064400017500001750000000115471477541562300135700ustar00djmdjm/* $OpenBSD: ttymodes.h,v 1.16 2017/04/30 23:26:54 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * SSH2 tty modes support by Kevin Steves. * Copyright (c) 2001 Kevin Steves. 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. */ /* * The tty mode description is a string, consisting of * opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0). * 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). * * 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 * require reimplementing as mode names would likely be different. */ /* * Some constants and prototypes are defined in packet.h; this file * is only intended for including from ttymodes.c. */ /* termios macro */ /* name, op */ TTYCHAR(VINTR, 1) TTYCHAR(VQUIT, 2) TTYCHAR(VERASE, 3) #if defined(VKILL) TTYCHAR(VKILL, 4) #endif /* VKILL */ TTYCHAR(VEOF, 5) #if defined(VEOL) TTYCHAR(VEOL, 6) #endif /* VEOL */ #ifdef VEOL2 TTYCHAR(VEOL2, 7) #endif /* VEOL2 */ TTYCHAR(VSTART, 8) TTYCHAR(VSTOP, 9) #if defined(VSUSP) TTYCHAR(VSUSP, 10) #endif /* VSUSP */ #if defined(VDSUSP) TTYCHAR(VDSUSP, 11) #endif /* VDSUSP */ #if defined(VREPRINT) TTYCHAR(VREPRINT, 12) #endif /* VREPRINT */ #if defined(VWERASE) TTYCHAR(VWERASE, 13) #endif /* VWERASE */ #if defined(VLNEXT) TTYCHAR(VLNEXT, 14) #endif /* VLNEXT */ #if defined(VFLUSH) TTYCHAR(VFLUSH, 15) #endif /* VFLUSH */ #ifdef VSWTCH TTYCHAR(VSWTCH, 16) #endif /* VSWTCH */ #if defined(VSTATUS) TTYCHAR(VSTATUS, 17) #endif /* VSTATUS */ #ifdef VDISCARD TTYCHAR(VDISCARD, 18) #endif /* VDISCARD */ /* name, field, op */ TTYMODE(IGNPAR, c_iflag, 30) TTYMODE(PARMRK, c_iflag, 31) TTYMODE(INPCK, c_iflag, 32) TTYMODE(ISTRIP, c_iflag, 33) TTYMODE(INLCR, c_iflag, 34) TTYMODE(IGNCR, c_iflag, 35) TTYMODE(ICRNL, c_iflag, 36) #if defined(IUCLC) TTYMODE(IUCLC, c_iflag, 37) #endif TTYMODE(IXON, c_iflag, 38) TTYMODE(IXANY, c_iflag, 39) 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) #ifdef XCASE TTYMODE(XCASE, c_lflag, 52) #endif TTYMODE(ECHO, c_lflag, 53) TTYMODE(ECHOE, c_lflag, 54) TTYMODE(ECHOK, c_lflag, 55) TTYMODE(ECHONL, c_lflag, 56) TTYMODE(NOFLSH, c_lflag, 57) TTYMODE(TOSTOP, c_lflag, 58) #ifdef IEXTEN TTYMODE(IEXTEN, c_lflag, 59) #endif /* IEXTEN */ #if defined(ECHOCTL) TTYMODE(ECHOCTL,c_lflag, 60) #endif /* ECHOCTL */ #ifdef ECHOKE TTYMODE(ECHOKE, c_lflag, 61) #endif /* ECHOKE */ #if defined(PENDIN) TTYMODE(PENDIN, c_lflag, 62) #endif /* PENDIN */ TTYMODE(OPOST, c_oflag, 70) #if defined(OLCUC) TTYMODE(OLCUC, c_oflag, 71) #endif #ifdef ONLCR TTYMODE(ONLCR, c_oflag, 72) #endif #ifdef OCRNL TTYMODE(OCRNL, c_oflag, 73) #endif #ifdef ONOCR TTYMODE(ONOCR, c_oflag, 74) #endif #ifdef ONLRET TTYMODE(ONLRET, c_oflag, 75) #endif TTYMODE(CS7, c_cflag, 90) TTYMODE(CS8, c_cflag, 91) TTYMODE(PARENB, c_cflag, 92) TTYMODE(PARODD, c_cflag, 93) openssh-10.0p1/PaxHeaders.10889/uidswap.c100644 001750 001750 0000000003614775415623 0014774xustar0030 atime=1744182234.891429974 openssh-10.0p1/uidswap.c010064400017500001750000000164101477541562300133610ustar00djmdjm/* $OpenBSD: uidswap.c,v 1.42 2019/06/28 13:35:04 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Code for uid-swapping. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #include #include #include #include #include "log.h" #include "uidswap.h" #include "xmalloc.h" /* * Note: all these functions must work in all of the following cases: * 1. euid=0, ruid=0 * 2. euid=0, ruid!=0 * 3. euid!=0, ruid!=0 * Additionally, they must work regardless of whether the system has * POSIX saved uids or not. */ #if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS) /* Lets assume that posix saved ids also work with seteuid, even though that is not part of the posix specification. */ #define SAVED_IDS_WORK_WITH_SETEUID /* Saved effective uid. */ static uid_t saved_euid = 0; static gid_t saved_egid = 0; #endif /* 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; /* * Temporarily changes to the given uid. If the effective user * id is not root, this does nothing. This call cannot be nested. */ void temporarily_use_uid(struct passwd *pw) { /* Save the current euid, and egroups. */ #ifdef SAVED_IDS_WORK_WITH_SETEUID saved_euid = geteuid(); saved_egid = getegid(); debug("temporarily_use_uid: %u/%u (e=%u/%u)", (u_int)pw->pw_uid, (u_int)pw->pw_gid, (u_int)saved_euid, (u_int)saved_egid); #ifndef HAVE_CYGWIN if (saved_euid != 0) { privileged = 0; return; } #endif #else if (geteuid() != 0) { privileged = 0; return; } #endif /* SAVED_IDS_WORK_WITH_SETEUID */ privileged = 1; temporarily_use_uid_effective = 1; saved_egroupslen = getgroups(0, NULL); if (saved_egroupslen == -1) fatal("getgroups: %.100s", strerror(errno)); if (saved_egroupslen > 0) { saved_egroups = xreallocarray(saved_egroups, saved_egroupslen, sizeof(gid_t)); 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 || 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 == -1) fatal("getgroups: %.100s", strerror(errno)); if (user_groupslen > 0) { user_groups = xreallocarray(user_groups, user_groupslen, sizeof(gid_t)); 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) == -1) fatal("setgroups: %.100s", strerror(errno)); #ifndef SAVED_IDS_WORK_WITH_SETEUID /* Propagate the privileged gid to all of our gids. */ 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()) == -1) debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno)); #endif /* SAVED_IDS_WORK_WITH_SETEUID */ if (setegid(pw->pw_gid) == -1) fatal("setegid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); if (seteuid(pw->pw_uid) == -1) fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); } /* * Restores to the original (privileged) uid. */ void restore_uid(void) { /* it's a no-op unless privileged */ if (!privileged) { debug("restore_uid: (unprivileged)"); return; } if (!temporarily_use_uid_effective) fatal("restore_uid: temporarily_use_uid not effective"); #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) == -1) fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno)); if (setegid(saved_egid) == -1) fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno)); #else /* SAVED_IDS_WORK_WITH_SETEUID */ /* * We are unable to restore the real uid to its unprivileged value. * Propagate the real uid (usually more privileged) to effective uid * as well. */ 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) == -1) fatal("setgroups: %.100s", strerror(errno)); temporarily_use_uid_effective = 0; } /* * Permanently sets all uids to the given uid. This cannot be * called while temporarily_use_uid is effective. */ void permanently_set_uid(struct passwd *pw) { #ifndef NO_UID_RESTORATION_TEST uid_t old_uid = getuid(); gid_t old_gid = getgid(); #endif if (pw == NULL) fatal("permanently_set_uid: no user given"); if (temporarily_use_uid_effective) fatal("permanently_set_uid: temporarily_use_uid effective"); debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, (u_int)pw->pw_gid); 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__ /* * OS X requires initgroups after setgid to opt back into * memberd support for >16 supplemental groups. */ 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) == -1) fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); #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)) fatal("%s: was able to restore old [e]gid", __func__); #endif /* Verify GID drop was successful */ if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) { fatal("%s: egid incorrect gid:%u egid:%u (should be %u)", __func__, (u_int)getgid(), (u_int)getegid(), (u_int)pw->pw_gid); } #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)) fatal("%s: was able to restore old [e]uid", __func__); #endif /* Verify UID drop was successful */ if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) { fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", __func__, (u_int)getuid(), (u_int)geteuid(), (u_int)pw->pw_uid); } } openssh-10.0p1/PaxHeaders.10889/uidswap.h100644 001750 001750 0000000003614775415623 0015001xustar0030 atime=1744182234.891429974 openssh-10.0p1/uidswap.h010064400017500001750000000012501477541562300133620ustar00djmdjm/* $OpenBSD: uidswap.h,v 1.14 2018/07/18 11:34:05 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ void temporarily_use_uid(struct passwd *); void restore_uid(void); void permanently_set_uid(struct passwd *); openssh-10.0p1/PaxHeaders.10889/umac.c100644 001750 001750 0000000003614775415623 0014245xustar0030 atime=1744182234.892406101 openssh-10.0p1/umac.c010064400017500001750000001316551477541562300126430ustar00djmdjm/* $OpenBSD: umac.c,v 1.23 2023/03/07 01:30:52 djm Exp $ */ /* ----------------------------------------------------------------------- * * umac.c -- C Implementation UMAC Message Authentication * * Version 0.93b of rfc4418.txt -- 2006 July 18 * * For a full description of UMAC message authentication see the UMAC * world-wide-web page at http://www.cs.ucdavis.edu/~rogaway/umac * 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 * and in supporting documentation, and that the name of the copyright * 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) * * ---------------------------------------------------------------------- */ /* ////////////////////// IMPORTANT NOTES ///////////////////////////////// * * 1) This version does not work properly on messages larger than 16MB * * 2) If you set the switch to use SSE2, then all data must be 16-byte * aligned * * 3) When calling the function umac(), it is assumed that msg is in * a writable buffer of length divisible by 32 bytes. The message itself * does not have to fill the entire buffer, but bytes beyond msg may be * zeroed. * * 4) Three free AES implementations are supported by this implementation of * UMAC. Paulo Barreto's version is in the public domain and can be found * 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 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. * * 5) With FORCE_C_ONLY flags set to 0, incorrect results are sometimes * produced under gcc with optimizations set -O3 or higher. Dunno why. * /////////////////////////////////////////////////////////////////////// */ /* ---------------------------------------------------------------------- */ /* --- User Switches ---------------------------------------------------- */ /* ---------------------------------------------------------------------- */ #ifndef UMAC_OUTPUT_LEN #define UMAC_OUTPUT_LEN 8 /* Alowable: 4, 8, 12, 16 */ #endif #if UMAC_OUTPUT_LEN != 4 && UMAC_OUTPUT_LEN != 8 && \ UMAC_OUTPUT_LEN != 12 && UMAC_OUTPUT_LEN != 16 # error UMAC_OUTPUT_LEN must be defined to 4, 8, 12 or 16 #endif /* #define FORCE_C_ONLY 1 ANSI C and 64-bit integers req'd */ /* #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 authenticated encryption */ /* ---------------------------------------------------------------------- */ /* -- Global Includes --------------------------------------------------- */ /* ---------------------------------------------------------------------- */ #include "includes.h" #include #include #include #include #include #include #include "xmalloc.h" #include "umac.h" #include "misc.h" /* ---------------------------------------------------------------------- */ /* --- Primitive Data Types --- */ /* ---------------------------------------------------------------------- */ /* The following assumptions may need change on your system */ typedef u_int8_t UINT8; /* 1 byte */ typedef u_int16_t UINT16; /* 2 byte */ typedef u_int32_t UINT32; /* 4 byte */ typedef u_int64_t UINT64; /* 8 bytes */ typedef unsigned int UWORD; /* Register */ /* ---------------------------------------------------------------------- */ /* --- Constants -------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ #define UMAC_KEY_LEN 16 /* UMAC takes 16 bytes of external key */ /* Message "words" are read from memory in an endian-specific manner. */ /* For this implementation to behave correctly, __LITTLE_ENDIAN__ must */ /* be set true if the host computer is little-endian. */ #if BYTE_ORDER == LITTLE_ENDIAN #define __LITTLE_ENDIAN__ 1 #else #define __LITTLE_ENDIAN__ 0 #endif /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Architecture Specific ------------------------------------------ */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Primitive Routines --------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* --- 32-bit by 32-bit to 64-bit Multiplication ------------------------ */ /* ---------------------------------------------------------------------- */ #define MUL64(a,b) ((UINT64)((UINT64)(UINT32)(a) * (UINT64)(UINT32)(b))) /* ---------------------------------------------------------------------- */ /* --- Endian Conversion --- Forcing assembly on some platforms */ /* ---------------------------------------------------------------------- */ #if (__LITTLE_ENDIAN__) #define LOAD_UINT32_REVERSED(p) get_u32(p) #define STORE_UINT32_REVERSED(p,v) put_u32(p,v) #else #define LOAD_UINT32_REVERSED(p) get_u32_le(p) #define STORE_UINT32_REVERSED(p,v) put_u32_le(p,v) #endif #define LOAD_UINT32_LITTLE(p) (get_u32_le(p)) #define STORE_UINT32_BIG(p,v) put_u32(p, v) /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Begin KDF & PDF Section ---------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* UMAC uses AES with 16 byte block and key lengths */ #define AES_BLOCK_LEN 16 /* OpenSSL's AES */ #ifdef WITH_OPENSSL #include "openbsd-compat/openssl-compat.h" #ifndef USE_BUILTIN_RIJNDAEL # include #endif typedef AES_KEY aes_int_key[1]; #define aes_encryption(in,out,int_key) \ AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key) #define aes_key_setup(key,int_key) \ AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key) #else #include "rijndael.h" #define AES_ROUNDS ((UMAC_KEY_LEN / 4) + 6) typedef UINT8 aes_int_key[AES_ROUNDS+1][4][4]; /* AES internal */ #define aes_encryption(in,out,int_key) \ rijndaelEncrypt((u32 *)(int_key), AES_ROUNDS, (u8 *)(in), (u8 *)(out)) #define aes_key_setup(key,int_key) \ rijndaelKeySetupEnc((u32 *)(int_key), (const unsigned char *)(key), \ UMAC_KEY_LEN*8) #endif /* The user-supplied UMAC key is stretched using AES in a counter * mode to supply all random bits needed by UMAC. The kdf function takes * an AES internal key representation 'key' and writes a stream of * 'nbytes' bytes to the memory pointed at by 'bufp'. Each distinct * 'ndx' causes a distinct byte stream. */ static void kdf(void *bufp, aes_int_key key, UINT8 ndx, int nbytes) { UINT8 in_buf[AES_BLOCK_LEN] = {0}; 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); in_buf[AES_BLOCK_LEN-1] = ++i; nbytes -= AES_BLOCK_LEN; dst_buf += AES_BLOCK_LEN; } if (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 * xor the appropriate bytes depending on the last bits of nonce. * This scheme is optimized for sequential, increasing big-endian nonces. */ typedef struct { UINT8 cache[AES_BLOCK_LEN]; /* Previous AES output is saved */ UINT8 nonce[AES_BLOCK_LEN]; /* The AES input making above cache */ aes_int_key prf_key; /* Expanded AES key for PDF */ } pdf_ctx; 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[UMAC_OUTPUT_LEN]) { /* 'ndx' indicates that we'll be using the 0th or 1st eight bytes * 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) #define LOW_BIT_MASK 1 #elif (UMAC_OUTPUT_LEN > 8) #define LOW_BIT_MASK 0 #endif union { UINT8 tmp_nonce_lo[4]; UINT32 align; } t; #if LOW_BIT_MASK != 0 int ndx = nonce[7] & LOW_BIT_MASK; #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]) ) { ((UINT32 *)pc->nonce)[0] = ((const UINT32 *)nonce)[0]; ((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) *((UINT64 *)buf) ^= ((UINT64 *)pc->cache)[ndx]; #elif (UMAC_OUTPUT_LEN == 12) ((UINT64 *)buf)[0] ^= ((UINT64 *)pc->cache)[0]; ((UINT32 *)buf)[2] ^= ((UINT32 *)pc->cache)[2]; #elif (UMAC_OUTPUT_LEN == 16) ((UINT64 *)buf)[0] ^= ((UINT64 *)pc->cache)[0]; ((UINT64 *)buf)[1] ^= ((UINT64 *)pc->cache)[1]; #endif } /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Begin NH Hash Section ------------------------------------------ */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* 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 * 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 * multiple-buffer interface, the client calls the routine nh_update() as * many times as necessary. When there is no more data to be fed to the * hash, the client calls nh_final() which calculates the hash output. * Before beginning another hash calculation the nh_reset() routine * 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, * allowing the parallel implementation of the streams. */ #define STREAMS (UMAC_OUTPUT_LEN / 4) /* Number of times hash is applied */ #define L1_KEY_LEN 1024 /* Internal key bytes */ #define L1_KEY_SHIFT 16 /* Toeplitz key shift between streams */ #define L1_PAD_BOUNDARY 32 /* pad message to boundary multiple */ #define ALLOC_BOUNDARY 16 /* Keep buffers aligned to this */ #define HASH_BUF_BYTES 64 /* nh_aux_hb buffer multiple */ 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; /* Bookkeeping variable for data buffer. */ int bytes_hashed; /* Bytes (out of L1_KEY_LEN) incorporated. */ UINT64 state[STREAMS]; /* on-line state */ } nh_ctx; #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 * 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. */ { UINT64 h; UWORD c = dlen / 32; UINT32 *k = (UINT32 *)kp; 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); d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3); d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5); d6 = LOAD_UINT32_LITTLE(d+6); d7 = LOAD_UINT32_LITTLE(d+7); k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3); k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7); h += MUL64((k0 + d0), (k4 + d4)); h += MUL64((k1 + d1), (k5 + d5)); h += MUL64((k2 + d2), (k6 + d6)); h += MUL64((k3 + d3), (k7 + d7)); d += 8; k += 8; } while (--c); *((UINT64 *)hp) = h; } #elif (UMAC_OUTPUT_LEN == 8) static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen) /* Same as previous nh_aux, but two streams are handled in one pass, * reading and writing 16 bytes of hash-state per call. */ { UINT64 h1,h2; UWORD c = dlen / 32; UINT32 *k = (UINT32 *)kp; const UINT32 *d = (const UINT32 *)dp; UINT32 d0,d1,d2,d3,d4,d5,d6,d7; UINT32 k0,k1,k2,k3,k4,k5,k6,k7, k8,k9,k10,k11; h1 = *((UINT64 *)hp); h2 = *((UINT64 *)hp + 1); k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3); do { d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1); d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3); d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5); d6 = LOAD_UINT32_LITTLE(d+6); d7 = LOAD_UINT32_LITTLE(d+7); k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7); k8 = *(k+8); k9 = *(k+9); k10 = *(k+10); k11 = *(k+11); h1 += MUL64((k0 + d0), (k4 + d4)); h2 += MUL64((k4 + d0), (k8 + d4)); h1 += MUL64((k1 + d1), (k5 + d5)); h2 += MUL64((k5 + d1), (k9 + d5)); h1 += MUL64((k2 + d2), (k6 + d6)); h2 += MUL64((k6 + d2), (k10 + d6)); h1 += MUL64((k3 + d3), (k7 + d7)); h2 += MUL64((k7 + d3), (k11 + d7)); k0 = k8; k1 = k9; k2 = k10; k3 = k11; d += 8; k += 8; } while (--c); ((UINT64 *)hp)[0] = h1; ((UINT64 *)hp)[1] = h2; } #elif (UMAC_OUTPUT_LEN == 12) static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen) /* Same as previous nh_aux, but two streams are handled in one pass, * reading and writing 24 bytes of hash-state per call. */ { UINT64 h1,h2,h3; UWORD c = dlen / 32; UINT32 *k = (UINT32 *)kp; const UINT32 *d = (const UINT32 *)dp; 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); k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3); k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7); do { d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1); d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3); d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5); 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); ((UINT64 *)hp)[0] = h1; ((UINT64 *)hp)[1] = h2; ((UINT64 *)hp)[2] = h3; } #elif (UMAC_OUTPUT_LEN == 16) static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen) /* Same as previous nh_aux, but two streams are handled in one pass, * reading and writing 24 bytes of hash-state per call. */ { UINT64 h1,h2,h3,h4; UWORD c = dlen / 32; UINT32 *k = (UINT32 *)kp; const UINT32 *d = (const UINT32 *)dp; 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, k16,k17,k18,k19; h1 = *((UINT64 *)hp); h2 = *((UINT64 *)hp + 1); h3 = *((UINT64 *)hp + 2); h4 = *((UINT64 *)hp + 3); k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3); k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7); do { d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1); d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3); d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5); 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); 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); ((UINT64 *)hp)[0] = h1; ((UINT64 *)hp)[1] = h2; ((UINT64 *)hp)[2] = h3; ((UINT64 *)hp)[3] = h4; } /* ---------------------------------------------------------------------- */ #endif /* UMAC_OUTPUT_LENGTH */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ static void nh_transform(nh_ctx *hc, const UINT8 *buf, UINT32 nbytes) /* This function is a wrapper for the primitive NH hash functions. It takes * as argument "hc" the current hash context and a buffer which must be a * multiple of L1_PAD_BOUNDARY. The key passed to nh_aux is offset * appropriately according to how much message has been hashed already. */ { UINT8 *key; key = hc->nh_key + hc->bytes_hashed; nh_aux(key, buf, hc->state, nbytes); } /* ---------------------------------------------------------------------- */ #if (__LITTLE_ENDIAN__) static void endian_convert(void *buf, UWORD bpw, UINT32 num_bytes) /* We endian convert the keys on little-endian computers to */ /* compensate for the lack of big-endian memory reads during hashing. */ { UWORD iters = num_bytes / bpw; if (bpw == 4) { UINT32 *p = (UINT32 *)buf; do { *p = LOAD_UINT32_REVERSED(p); p++; } while (--iters); } else if (bpw == 8) { UINT32 *p = (UINT32 *)buf; UINT32 t; do { t = LOAD_UINT32_REVERSED(p+1); p[1] = LOAD_UINT32_REVERSED(p); p[0] = t; p += 2; } while (--iters); } } #define endian_convert_if_le(x,y,z) endian_convert((x),(y),(z)) #else #define endian_convert_if_le(x,y,z) do{}while(0) /* Do nothing */ #endif /* ---------------------------------------------------------------------- */ static void nh_reset(nh_ctx *hc) /* Reset nh_ctx to ready for hashing of new data */ { hc->bytes_hashed = 0; hc->next_data_empty = 0; hc->state[0] = 0; #if (UMAC_OUTPUT_LEN >= 8) hc->state[1] = 0; #endif #if (UMAC_OUTPUT_LEN >= 12) hc->state[2] = 0; #endif #if (UMAC_OUTPUT_LEN == 16) hc->state[3] = 0; #endif } /* ---------------------------------------------------------------------- */ static void nh_init(nh_ctx *hc, aes_int_key prf_key) /* Generate nh_key, endian convert and reset to be ready for hashing. */ { kdf(hc->nh_key, prf_key, 1, sizeof(hc->nh_key)); endian_convert_if_le(hc->nh_key, 4, sizeof(hc->nh_key)); nh_reset(hc); } /* ---------------------------------------------------------------------- */ static void nh_update(nh_ctx *hc, const UINT8 *buf, UINT32 nbytes) /* Incorporate nbytes of data into a nh_ctx, buffer whatever is not an */ /* even multiple of HASH_BUF_BYTES. */ { UINT32 i,j; j = hc->next_data_empty; if ((j + nbytes) >= HASH_BUF_BYTES) { if (j) { i = HASH_BUF_BYTES - j; memcpy(hc->data+j, buf, i); nh_transform(hc,hc->data,HASH_BUF_BYTES); nbytes -= i; buf += i; hc->bytes_hashed += HASH_BUF_BYTES; } if (nbytes >= HASH_BUF_BYTES) { i = nbytes & ~(HASH_BUF_BYTES - 1); nh_transform(hc, buf, i); nbytes -= i; buf += i; hc->bytes_hashed += i; } j = 0; } memcpy(hc->data + j, buf, nbytes); hc->next_data_empty = j + nbytes; } /* ---------------------------------------------------------------------- */ static void zero_pad(UINT8 *p, int nbytes) { /* Write "nbytes" of zeroes, beginning at "p" */ if (nbytes >= (int)sizeof(UWORD)) { while ((ptrdiff_t)p % sizeof(UWORD)) { *p = 0; nbytes--; p++; } while (nbytes >= (int)sizeof(UWORD)) { *(UWORD *)p = 0; nbytes -= sizeof(UWORD); p += sizeof(UWORD); } } while (nbytes) { *p = 0; nbytes--; p++; } } /* ---------------------------------------------------------------------- */ static void nh_final(nh_ctx *hc, UINT8 *result) /* After passing some number of data buffers to nh_update() for integration * into an NH context, nh_final is called to produce a hash result. If any * bytes are in the buffer hc->data, incorporate them into the * NH context. Finally, add into the NH accumulation "state" the total number * of bits hashed. The resulting numbers are written to the buffer "result". * If nh_update was never called, L1_PAD_BOUNDARY zeroes are incorporated. */ { int nh_len, nbits; 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, 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; zero_pad(hc->data, L1_PAD_BOUNDARY); nh_transform(hc, hc->data, nh_len); } nbits = (hc->bytes_hashed << 3); ((UINT64 *)result)[0] = ((UINT64 *)hc->state)[0] + nbits; #if (UMAC_OUTPUT_LEN >= 8) ((UINT64 *)result)[1] = ((UINT64 *)hc->state)[1] + nbits; #endif #if (UMAC_OUTPUT_LEN >= 12) ((UINT64 *)result)[2] = ((UINT64 *)hc->state)[2] + nbits; #endif #if (UMAC_OUTPUT_LEN == 16) ((UINT64 *)result)[3] = ((UINT64 *)hc->state)[3] + nbits; #endif nh_reset(hc); } /* ---------------------------------------------------------------------- */ static void nh(nh_ctx *hc, const UINT8 *buf, UINT32 padded_len, UINT32 unpadded_len, UINT8 *result) /* All-in-one nh_update() and nh_final() equivalent. * Assumes that padded_len is divisible by L1_PAD_BOUNDARY and result is * well aligned */ { UINT32 nbits; /* Initialize the hash state */ nbits = (unpadded_len << 3); ((UINT64 *)result)[0] = nbits; #if (UMAC_OUTPUT_LEN >= 8) ((UINT64 *)result)[1] = nbits; #endif #if (UMAC_OUTPUT_LEN >= 12) ((UINT64 *)result)[2] = nbits; #endif #if (UMAC_OUTPUT_LEN == 16) ((UINT64 *)result)[3] = nbits; #endif nh_aux(hc->nh_key, buf, result, padded_len); } /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Begin UHASH Section -------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* UHASH is a multi-layered algorithm. Data presented to UHASH is first * hashed by NH. The NH output is then hashed by a polynomial-hash layer * unless the initial data to be hashed is short. After the polynomial- * layer, an inner-product hash is used to produce the final UHASH output. * * UHASH provides two interfaces, one all-at-once and another where data * 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 * must be called once, before any other UHASH routine. */ /* ---------------------------------------------------------------------- */ /* ----- Constants and uhash_ctx ---------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Poly hash and Inner-Product hash Constants --------------------- */ /* ---------------------------------------------------------------------- */ /* Primes and masks */ #define p36 ((UINT64)0x0000000FFFFFFFFBull) /* 2^36 - 5 */ #define p64 ((UINT64)0xFFFFFFFFFFFFFFC5ull) /* 2^64 - 59 */ #define m36 ((UINT64)0x0000000FFFFFFFFFull) /* The low 36 of 64 bits */ /* ---------------------------------------------------------------------- */ typedef struct uhash_ctx { nh_ctx hash; /* Hash context for L1 NH hash */ UINT64 poly_key_8[STREAMS]; /* p64 poly keys */ UINT64 poly_accum[STREAMS]; /* poly hash result */ UINT64 ip_keys[STREAMS*4]; /* Inner-product keys */ UINT32 ip_trans[STREAMS]; /* Inner-product translation */ UINT32 msg_len; /* Total length of data passed */ /* to uhash */ } uhash_ctx; typedef struct uhash_ctx *uhash_ctx_t; /* ---------------------------------------------------------------------- */ /* The polynomial hashes use Horner's rule to evaluate a polynomial one * word at a time. As described in the specification, poly32 and poly64 * require keys from special domains. The following implementations exploit * the special domains to avoid overflow. The results are not guaranteed to * be within Z_p32 and Z_p64, but the Inner-Product hash implementation * patches any errant values. */ static UINT64 poly64(UINT64 cur, UINT64 key, UINT64 data) { UINT32 key_hi = (UINT32)(key >> 32), key_lo = (UINT32)key, cur_hi = (UINT32)(cur >> 32), cur_lo = (UINT32)cur, 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) res += 59; res += data; if (res < data) res += 59; return res; } /* Although UMAC is specified to use a ramped polynomial hash scheme, this * implementation does not handle all ramp levels. Because we don't handle * the ramp up to p128 modulus in this implementation, we are limited to * 2^14 poly_hash() invocations per stream (for a total capacity of 2^24 * bytes input to UMAC per tag, ie. 16MB). */ 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_key_8[i], p64 - 1); hc->poly_accum[i] = poly64(hc->poly_accum[i], hc->poly_key_8[i], (data[i] - 59)); } else { hc->poly_accum[i] = poly64(hc->poly_accum[i], hc->poly_key_8[i], data[i]); } } } /* ---------------------------------------------------------------------- */ /* The final step in UHASH is an inner-product hash. The poly hash * 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. */ static UINT64 ip_aux(UINT64 t, UINT64 *ipkp, UINT64 data) { t = t + ipkp[0] * (UINT64)(UINT16)(data >> 48); 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; } static UINT32 ip_reduce_p36(UINT64 t) { /* Divisionless modular reduction */ UINT64 ret; ret = (t & m36) + 5 * (t >> 36); if (ret >= p36) ret -= p36; /* return least significant 32 bits */ return (UINT32)(ret); } /* If the data being hashed by UHASH is no longer than L1_KEY_LEN, then * the polyhash stage is skipped and ip_short is applied directly to the * NH output. */ 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) t = ip_aux(0,ahc->ip_keys+4, nhp[1]); STORE_UINT32_BIG((UINT32 *)res+1, ip_reduce_p36(t) ^ ahc->ip_trans[1]); #endif #if (UMAC_OUTPUT_LEN >= 12) t = ip_aux(0,ahc->ip_keys+8, nhp[2]); STORE_UINT32_BIG((UINT32 *)res+2, ip_reduce_p36(t) ^ ahc->ip_trans[2]); #endif #if (UMAC_OUTPUT_LEN == 16) t = ip_aux(0,ahc->ip_keys+12, nhp[3]); STORE_UINT32_BIG((UINT32 *)res+3, ip_reduce_p36(t) ^ ahc->ip_trans[3]); #endif } /* If the data being hashed by UHASH is longer than L1_KEY_LEN, then * the polyhash stage is not skipped and ip_long is applied to the * polyhash output. */ static void ip_long(uhash_ctx_t ahc, u_char *res) { int i; UINT64 t; for (i = 0; i < STREAMS; i++) { /* fix polyhash output not in Z_p64 */ 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, ip_reduce_p36(t) ^ ahc->ip_trans[i]); } } /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* Reset uhash context for next hash session */ static int uhash_reset(uhash_ctx_t pc) { nh_reset(&pc->hash); pc->msg_len = 0; pc->poly_accum[0] = 1; #if (UMAC_OUTPUT_LEN >= 8) pc->poly_accum[1] = 1; #endif #if (UMAC_OUTPUT_LEN >= 12) pc->poly_accum[2] = 1; #endif #if (UMAC_OUTPUT_LEN == 16) pc->poly_accum[3] = 1; #endif return 1; } /* ---------------------------------------------------------------------- */ /* Given a pointer to the internal key needed by kdf() and a uhash context, * initialize the NH context and generate keys needed for poly and inner- * product hashing. All keys are endian adjusted in memory so that native * loads cause correct keys to be in registers during calculation. */ 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++) { /* Fill keys from the buffer, skipping bytes in the buffer not * used by this implementation. Endian reverse the keys if on a * little-endian computer. */ memcpy(ahc->poly_key_8+i, buf+24*i, 8); endian_convert_if_le(ahc->poly_key_8+i, 8, 8); /* Mask the 64-bit keys to their special domain */ 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), 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)); } /* ---------------------------------------------------------------------- */ #if 0 static uhash_ctx_t uhash_alloc(u_char key[]) { /* Allocate memory and force to a 16-byte boundary. */ 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) { bytes_to_add = ALLOC_BOUNDARY - ((ptrdiff_t)ctx & (ALLOC_BOUNDARY -1)); ctx = (uhash_ctx_t)((u_char *)ctx + bytes_to_add); *((u_char *)ctx - 1) = bytes_to_add; } aes_key_setup(key,prf_key); uhash_init(ctx, prf_key); } return (ctx); } #endif /* ---------------------------------------------------------------------- */ #if 0 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); ctx = (uhash_ctx_t)((u_char *)ctx - bytes_to_sub); } free(ctx); } return (1); } #endif /* ---------------------------------------------------------------------- */ static int uhash_update(uhash_ctx_t ctx, const u_char *input, long len) /* Given len bytes of data, we parse it into L1_KEY_LEN chunks and * hash each one with NH, calling the polyhash on each NH output. */ { 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; if (bytes_hashed + len >= L1_KEY_LEN) { /* If some bytes have been passed to the hash function */ /* then we want to pass at most (L1_KEY_LEN - bytes_hashed) */ /* bytes to complete the current nh_block. */ if (bytes_hashed) { bytes_remaining = (L1_KEY_LEN - bytes_hashed); nh_update(&ctx->hash, (const UINT8 *)input, bytes_remaining); nh_final(&ctx->hash, nh_result); ctx->msg_len += bytes_remaining; poly_hash(ctx,(UINT32 *)nh_result); len -= bytes_remaining; input += bytes_remaining; } /* Hash directly from input stream if enough bytes */ while (len >= L1_KEY_LEN) { nh(&ctx->hash, (const UINT8 *)input, L1_KEY_LEN, L1_KEY_LEN, nh_result); ctx->msg_len += L1_KEY_LEN; len -= L1_KEY_LEN; input += L1_KEY_LEN; poly_hash(ctx,(UINT32 *)nh_result); } } /* pass remaining < L1_KEY_LEN bytes of input data to NH */ if (len) { nh_update(&ctx->hash, (const UINT8 *)input, len); ctx->msg_len += len; } } return (1); } /* ---------------------------------------------------------------------- */ static int uhash_final(uhash_ctx_t ctx, u_char *res) /* Incorporate any pending data, pad, and generate tag */ { UINT64 result_buf[STREAMS]; UINT8 *nh_result = (UINT8 *)&result_buf; if (ctx->msg_len > L1_KEY_LEN) { if (ctx->msg_len % L1_KEY_LEN) { nh_final(&ctx->hash, nh_result); poly_hash(ctx,(UINT32 *)nh_result); } ip_long(ctx, res); } else { nh_final(&ctx->hash, nh_result); ip_short(ctx,nh_result, res); } uhash_reset(ctx); return (1); } /* ---------------------------------------------------------------------- */ #if 0 static int uhash(uhash_ctx_t ahc, u_char *msg, long len, u_char *res) /* assumes that msg is in a writable buffer of length divisible by */ /* L1_PAD_BOUNDARY. Bytes beyond msg[len] may be zeroed. */ { 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)); extra_zeroes_needed = nh_len - len; zero_pad((UINT8 *)msg + len, extra_zeroes_needed); nh(&ahc->hash, (UINT8 *)msg, nh_len, len, nh_result); ip_short(ahc,nh_result, res); } else { /* Otherwise, we hash each L1_KEY_LEN chunk with NH, passing the NH * output to poly_hash(). */ do { nh(&ahc->hash, (UINT8 *)msg, L1_KEY_LEN, L1_KEY_LEN, nh_result); poly_hash(ahc,(UINT32 *)nh_result); len -= L1_KEY_LEN; msg += L1_KEY_LEN; } while (len >= L1_KEY_LEN); if (len) { 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); poly_hash(ahc,(UINT32 *)nh_result); } ip_long(ahc, res); } uhash_reset(ahc); return 1; } #endif /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Begin UMAC Section --------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* 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 * time. The all-at-once is more optimized than the sequential version and * should be preferred when the sequential interface is not required. */ struct umac_ctx { uhash_ctx hash; /* Hash function for message compression */ pdf_ctx pdf; /* PDF for hashed output */ void *free_ptr; /* Address to free this struct via */ } umac_ctx; /* ---------------------------------------------------------------------- */ #if 0 int umac_reset(struct umac_ctx *ctx) /* Reset the hash function to begin a new authentication. */ { uhash_reset(&ctx->hash); return (1); } #endif /* ---------------------------------------------------------------------- */ int umac_delete(struct umac_ctx *ctx) /* Deallocate the ctx structure */ { if (ctx) { if (ALLOC_BOUNDARY) ctx = (struct umac_ctx *)ctx->free_ptr; freezero(ctx, sizeof(*ctx) + ALLOC_BOUNDARY); } return (1); } /* ---------------------------------------------------------------------- */ struct umac_ctx *umac_new(const u_char key[]) /* 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) { bytes_to_add = ALLOC_BOUNDARY - ((ptrdiff_t)ctx & (ALLOC_BOUNDARY - 1)); ctx = (struct umac_ctx *)((u_char *)ctx + bytes_to_add); } ctx->free_ptr = octx; 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); } /* ---------------------------------------------------------------------- */ int umac_final(struct umac_ctx *ctx, u_char tag[], const u_char nonce[8]) /* Incorporate any pending data, pad, and generate tag */ { uhash_final(&ctx->hash, (u_char *)tag); pdf_gen_xor(&ctx->pdf, (const UINT8 *)nonce, (UINT8 *)tag); return (1); } /* ---------------------------------------------------------------------- */ int umac_update(struct umac_ctx *ctx, const u_char *input, long len) /* Given len bytes of data, we parse it into L1_KEY_LEN chunks and */ /* hash each one, calling the PDF on the hashed output whenever the hash- */ /* output buffer is full. */ { uhash_update(&ctx->hash, input, len); return (1); } /* ---------------------------------------------------------------------- */ #if 0 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 /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- End UMAC Section ----------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ openssh-10.0p1/PaxHeaders.10889/umac.h100644 001750 001750 0000000003614775415623 0014252xustar0030 atime=1744182234.892406101 openssh-10.0p1/umac.h010064400017500001750000000111261477541562300126360ustar00djmdjm/* $OpenBSD: umac.h,v 1.5 2022/01/01 01:55:30 jsg Exp $ */ /* ----------------------------------------------------------------------- * * umac.h -- C Implementation UMAC Message Authentication * * Version 0.93a of rfc4418.txt -- 2006 July 14 * * For a full description of UMAC message authentication see the UMAC * world-wide-web page at http://www.cs.ucdavis.edu/~rogaway/umac * Please report bugs and suggestions to the UMAC webpage. * * Copyright (c) 1999-2004 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 * and in supporting documentation, and that the name of the copyright * 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) * * ---------------------------------------------------------------------- */ /* ////////////////////// IMPORTANT NOTES ///////////////////////////////// * * 1) This version does not work properly on messages larger than 16MB * * 2) If you set the switch to use SSE2, then all data must be 16-byte * aligned * * 3) When calling the function umac(), it is assumed that msg is in * a writable buffer of length divisible by 32 bytes. The message itself * does not have to fill the entire buffer, but bytes beyond msg may be * zeroed. * * 4) Two free AES implementations are supported by this implementation of * UMAC. Paulo Barreto's version is in the public domain and can be found * 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 license * and can be found at http://fp.gladman.plus.com/AES/index.htm. It * includes a fast IA-32 assembly version. * /////////////////////////////////////////////////////////////////////// */ #ifndef HEADER_UMAC_H #define HEADER_UMAC_H #ifdef __cplusplus extern "C" { #endif struct umac_ctx *umac_new(const u_char key[]); /* Dynamically allocate a umac_ctx struct, initialize variables, * generate subkeys from key. */ #if 0 int umac_reset(struct umac_ctx *ctx); /* Reset a umac_ctx to begin authenticating a new message */ #endif int umac_update(struct umac_ctx *ctx, const u_char *input, long len); /* Incorporate len bytes pointed to by input into context ctx */ int umac_final(struct umac_ctx *ctx, u_char tag[], const u_char nonce[8]); /* Incorporate any pending data and the ctr value, and return tag. * This function returns error code if ctr < 0. */ int umac_delete(struct umac_ctx *ctx); /* Deallocate the context structure */ #if 0 int umac(struct umac_ctx *ctx, u_char *input, long len, u_char tag[], u_char nonce[8]); /* All-in-one implementation of the functions Reset, Update and Final */ #endif /* uhash.h */ #if 0 typedef struct uhash_ctx *uhash_ctx_t; /* The uhash_ctx structure is defined by the implementation of the */ /* UHASH functions. */ uhash_ctx_t uhash_alloc(u_char key[16]); /* Dynamically allocate a uhash_ctx struct and generate subkeys using */ /* the kdf and kdf_key passed in. If kdf_key_len is 0 then RC6 is */ /* used to generate key with a fixed key. If kdf_key_len > 0 but kdf */ /* is NULL then the first 16 bytes pointed at by kdf_key is used as a */ /* key for an RC6 based KDF. */ int uhash_free(uhash_ctx_t ctx); int uhash_set_params(uhash_ctx_t ctx, void *params); int uhash_reset(uhash_ctx_t ctx); int uhash_update(uhash_ctx_t ctx, u_char *input, long len); int uhash_final(uhash_ctx_t ctx, u_char output[]); int uhash(uhash_ctx_t ctx, u_char *input, long len, u_char output[]); #endif /* matching umac-128 API, we reuse umac_ctx, since it's opaque */ struct umac_ctx *umac128_new(const u_char key[]); int umac128_update(struct umac_ctx *ctx, const u_char *input, long len); int umac128_final(struct umac_ctx *ctx, u_char tag[], const u_char nonce[8]); int umac128_delete(struct umac_ctx *ctx); #ifdef __cplusplus } #endif #endif /* HEADER_UMAC_H */ openssh-10.0p1/PaxHeaders.10889/umac128.c100644 001750 001750 0000000003614775415623 0014500xustar0030 atime=1744182234.892406101 openssh-10.0p1/umac128.c010064400017500001750000000004221477541562300130610ustar00djmdjm/* $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_ctx umac128_ctx #include "umac.c" openssh-10.0p1/PaxHeaders.10889/utf8.c100644 001750 001750 0000000003614775415623 0014206xustar0030 atime=1744182234.892406101 openssh-10.0p1/utf8.c010064400017500001750000000203671477541562300126010ustar00djmdjm/* $OpenBSD: utf8.c,v 1.11 2020/05/01 06:28:52 djm Exp $ */ /* * Copyright (c) 2016 Ingo Schwarze * * 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 #ifdef HAVE_LANGINFO_H # include #endif #include #include #include #include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) # include #endif #ifdef HAVE_WCHAR_H # include #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, ""); } openssh-10.0p1/PaxHeaders.10889/utf8.h100644 001750 001750 0000000003614775415623 0014213xustar0030 atime=1744182234.892406101 openssh-10.0p1/utf8.h010064400017500001750000000025131477541562300125770ustar00djmdjm/* $OpenBSD: utf8.h,v 1.4 2021/04/03 06:18:41 djm Exp $ */ /* * Copyright (c) 2016 Ingo Schwarze * * 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); openssh-10.0p1/PaxHeaders.10889/version.h100644 001750 001750 0000000003614775415623 0015012xustar0030 atime=1744182234.892406101 openssh-10.0p1/version.h010064400017500001750000000002541477541562300133760ustar00djmdjm/* $OpenBSD: version.h,v 1.105 2025/04/09 07:00:21 djm Exp $ */ #define SSH_VERSION "OpenSSH_10.0" #define SSH_PORTABLE "p2" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE openssh-10.0p1/PaxHeaders.10889/xmalloc.c100644 001750 001750 0000000003614775415623 0014757xustar0030 atime=1744182234.893383029 openssh-10.0p1/xmalloc.c010064400017500001750000000047221477541562300133470ustar00djmdjm/* $OpenBSD: xmalloc.c,v 1.37 2022/03/13 23:27:54 cheloha Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Versions of malloc and friends that check their results, and never return * failure (they call fatal if they encounter an error). * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include "xmalloc.h" #include "log.h" #if defined(__OpenBSD__) char *malloc_options = "S"; #endif /* __OpenBSD__ */ void * xmalloc(size_t size) { void *ptr; if (size == 0) fatal("xmalloc: zero size"); ptr = malloc(size); if (ptr == NULL) fatal("xmalloc: out of memory (allocating %zu bytes)", size); return ptr; } void * xcalloc(size_t nmemb, size_t size) { void *ptr; if (size == 0 || nmemb == 0) fatal("xcalloc: zero size"); if (SIZE_MAX / nmemb < size) fatal("xcalloc: nmemb * size > SIZE_MAX"); ptr = calloc(nmemb, size); if (ptr == NULL) fatal("xcalloc: out of memory (allocating %zu bytes)", size * nmemb); return ptr; } void * xreallocarray(void *ptr, size_t nmemb, size_t size) { void *new_ptr; 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("xrecallocarray: out of memory (%zu elements of %zu bytes)", nmemb, size); return new_ptr; } char * xstrdup(const char *str) { size_t len; char *cp; len = strlen(str) + 1; cp = xmalloc(len); return memcpy(cp, str, len); } 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 = xvasprintf(ret, fmt, ap); va_end(ap); return i; } openssh-10.0p1/PaxHeaders.10889/xmalloc.h100644 001750 001750 0000000003614775415623 0014764xustar0030 atime=1744182234.893383029 openssh-10.0p1/xmalloc.h010064400017500001750000000021551477541562300133520ustar00djmdjm/* $OpenBSD: xmalloc.h,v 1.20 2021/04/03 06:18:41 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Created: Mon Mar 20 22:09:17 1995 ylo * * Versions of malloc and friends that check their results, and never return * failure (they call fatal if they encounter an error). * * 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". */ void *xmalloc(size_t); void *xcalloc(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))); openssh-10.0p1/PaxHeaders.10889/xmss_commons.c100644 001750 001750 0000000003614775415623 0016045xustar0030 atime=1744182234.893383029 openssh-10.0p1/xmss_commons.c010064400017500001750000000011671477541562300144350ustar00djmdjm/* $OpenBSD: xmss_commons.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ /* xmss_commons.c 20160722 Andreas Hülsing Joost Rijneveld Public domain. */ #include "includes.h" #ifdef WITH_XMSS #include "xmss_commons.h" #include #include #ifdef HAVE_STDINT_H # include #endif void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes) { int32_t i; for (i = bytes-1; i >= 0; i--) { out[i] = in & 0xff; in = in >> 8; } } #if 0 void hexdump(const unsigned char *a, size_t len) { size_t i; for (i = 0; i < len; i++) printf("%02x", a[i]); } #endif #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/xmss_commons.h100644 001750 001750 0000000003614775415623 0016052xustar0030 atime=1744182234.893383029 openssh-10.0p1/xmss_commons.h010064400017500001750000000007021477541562300144340ustar00djmdjm#ifdef WITH_XMSS /* $OpenBSD: xmss_commons.h,v 1.3 2018/02/26 03:56:44 dtucker Exp $ */ /* xmss_commons.h 20160722 Andreas Hülsing Joost Rijneveld Public domain. */ #ifndef XMSS_COMMONS_H #define XMSS_COMMONS_H #include #ifdef HAVE_STDINT_H #include #endif #endif void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes); #if 0 void hexdump(const unsigned char *a, size_t len); #endif #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/xmss_fast.c100644 001750 001750 0000000003614775415623 0015327xustar0030 atime=1744182234.895335732 openssh-10.0p1/xmss_fast.c010064400017500001750000001002451477541562300137140ustar00djmdjm/* $OpenBSD: xmss_fast.c,v 1.3 2018/03/22 07:06:11 markus Exp $ */ /* xmss_fast.c version 20160722 Andreas Hülsing Joost Rijneveld Public domain. */ #include "includes.h" #ifdef WITH_XMSS #include #include #ifdef HAVE_STDINT_H # include #endif #include "xmss_fast.h" #include "crypto_api.h" #include "xmss_wots.h" #include "xmss_hash.h" #include "xmss_commons.h" #include "xmss_hash_address.h" // For testing #include "stdio.h" /** * Used for pseudorandom keygeneration, * generates the seed for the WOTS keypair at address addr * * takes n byte sk_seed and returns n byte seed using 32 byte address addr. */ static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) { unsigned char bytes[32]; // Make sure that chain addr, hash addr, and key bit are 0! setChainADRS(addr,0); setHashADRS(addr,0); setKeyAndMask(addr,0); // Generate pseudorandom value addr_to_byte(bytes, addr); prf(seed, bytes, sk_seed, n); } /** * Initialize xmss params struct * parameter names are the same as in the draft * parameter k is K as used in the BDS algorithm */ int xmss_set_params(xmss_params *params, int n, int h, int w, int k) { if (k >= h || k < 2 || (h - k) % 2) { fprintf(stderr, "For BDS traversal, H - K must be even, with H > K >= 2!\n"); return 1; } params->h = h; params->n = n; params->k = k; wots_params wots_par; wots_set_params(&wots_par, n, w); params->wots_par = wots_par; return 0; } /** * Initialize BDS state struct * parameter names are the same as used in the description of the BDS traversal */ void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf) { state->stack = stack; state->stackoffset = stackoffset; state->stacklevels = stacklevels; state->auth = auth; state->keep = keep; state->treehash = treehash; state->retain = retain; state->next_leaf = next_leaf; } /** * Initialize xmssmt_params struct * parameter names are the same as in the draft * * Especially h is the total tree height, i.e. the XMSS trees have height h/d */ int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k) { if (h % d) { fprintf(stderr, "d must divide h without remainder!\n"); return 1; } params->h = h; params->d = d; params->n = n; params->index_len = (h + 7) / 8; xmss_params xmss_par; if (xmss_set_params(&xmss_par, n, (h/d), w, k)) { return 1; } params->xmss_par = xmss_par; return 0; } /** * Computes a leaf from a WOTS public key using an L-tree. */ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { unsigned int l = params->wots_par.len; unsigned int n = params->n; uint32_t i = 0; uint32_t height = 0; uint32_t bound; //ADRS.setTreeHeight(0); setTreeHeight(addr, height); while (l > 1) { bound = l >> 1; //floor(l / 2); for (i = 0; i < bound; i++) { //ADRS.setTreeIndex(i); setTreeIndex(addr, i); //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS); hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n); } //if ( l % 2 == 1 ) { if (l & 1) { //pk[floor(l / 2) + 1] = pk[l]; memcpy(wots_pk+(l>>1)*n, wots_pk+(l-1)*n, n); //l = ceil(l / 2); l=(l>>1)+1; } else { //l = ceil(l / 2); l=(l>>1); } //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); height++; setTreeHeight(addr, height); } //return pk[0]; memcpy(leaf, wots_pk, n); } /** * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address. */ static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8]) { unsigned char seed[params->n]; unsigned char pk[params->wots_par.keysize]; get_seed(seed, sk_seed, params->n, ots_addr); wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr); l_tree(leaf, pk, params, pub_seed, ltree_addr); } static int treehash_minheight_on_stack(bds_state* state, const xmss_params *params, const treehash_inst *treehash) { unsigned int r = params->h, i; for (i = 0; i < treehash->stackusage; i++) { if (state->stacklevels[state->stackoffset - i - 1] < r) { r = state->stacklevels[state->stackoffset - i - 1]; } } return r; } /** * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash. * Currently only used for key generation. * */ static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) { unsigned int idx = index; unsigned int n = params->n; unsigned int h = params->h; unsigned int k = params->k; // use three different addresses because at this point we use all three formats in parallel uint32_t ots_addr[8]; uint32_t ltree_addr[8]; uint32_t node_addr[8]; // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots setType(ots_addr, 0); memcpy(ltree_addr, addr, 12); setType(ltree_addr, 1); memcpy(node_addr, addr, 12); setType(node_addr, 2); uint32_t lastnode, i; unsigned char stack[(height+1)*n]; unsigned int stacklevels[height+1]; unsigned int stackoffset=0; unsigned int nodeh; lastnode = idx+(1<treehash[i].h = i; state->treehash[i].completed = 1; state->treehash[i].stackusage = 0; } i = 0; for (; idx < lastnode; idx++) { setLtreeADRS(ltree_addr, idx); setOTSADRS(ots_addr, idx); gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); stacklevels[stackoffset] = 0; stackoffset++; if (h - k > 0 && i == 3) { memcpy(state->treehash[0].node, stack+stackoffset*n, n); } while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { nodeh = stacklevels[stackoffset-1]; if (i >> nodeh == 1) { memcpy(state->auth + nodeh*n, stack+(stackoffset-1)*n, n); } else { if (nodeh < h - k && i >> nodeh == 3) { memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*n, n); } else if (nodeh >= h - k) { memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((i >> nodeh) - 3) >> 1)) * n, stack+(stackoffset-1)*n, n); } } setTreeHeight(node_addr, stacklevels[stackoffset-1]); setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed, node_addr, n); stacklevels[stackoffset-2]++; stackoffset--; } i++; } for (i = 0; i < n; i++) node[i] = stack[i]; } static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) { int n = params->n; uint32_t ots_addr[8]; uint32_t ltree_addr[8]; uint32_t node_addr[8]; // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots setType(ots_addr, 0); memcpy(ltree_addr, addr, 12); setType(ltree_addr, 1); memcpy(node_addr, addr, 12); setType(node_addr, 2); setLtreeADRS(ltree_addr, treehash->next_idx); setOTSADRS(ots_addr, treehash->next_idx); unsigned char nodebuffer[2 * n]; unsigned int nodeheight = 0; gen_leaf_wots(nodebuffer, sk_seed, params, pub_seed, ltree_addr, ots_addr); while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) { memcpy(nodebuffer + n, nodebuffer, n); memcpy(nodebuffer, state->stack + (state->stackoffset-1)*n, n); setTreeHeight(node_addr, nodeheight); setTreeIndex(node_addr, (treehash->next_idx >> (nodeheight+1))); hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, n); nodeheight++; treehash->stackusage--; state->stackoffset--; } if (nodeheight == treehash->h) { // this also implies stackusage == 0 memcpy(treehash->node, nodebuffer, n); treehash->completed = 1; } else { memcpy(state->stack + state->stackoffset*n, nodebuffer, n); treehash->stackusage++; state->stacklevels[state->stackoffset] = nodeheight; state->stackoffset++; treehash->next_idx++; } } /** * Computes a root node given a leaf and an authapth */ static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { unsigned int n = params->n; uint32_t i, j; unsigned char buffer[2*n]; // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left. // Otherwise, it is the other way around if (leafidx & 1) { for (j = 0; j < n; j++) buffer[n+j] = leaf[j]; for (j = 0; j < n; j++) buffer[j] = authpath[j]; } else { for (j = 0; j < n; j++) buffer[j] = leaf[j]; for (j = 0; j < n; j++) buffer[n+j] = authpath[j]; } authpath += n; for (i=0; i < params->h-1; i++) { setTreeHeight(addr, i); leafidx >>= 1; setTreeIndex(addr, leafidx); if (leafidx&1) { hash_h(buffer+n, buffer, pub_seed, addr, n); for (j = 0; j < n; j++) buffer[j] = authpath[j]; } else { hash_h(buffer, buffer, pub_seed, addr, n); for (j = 0; j < n; j++) buffer[j+n] = authpath[j]; } authpath += n; } setTreeHeight(addr, (params->h-1)); leafidx >>= 1; setTreeIndex(addr, leafidx); hash_h(root, buffer, pub_seed, addr, n); } /** * Performs one treehash update on the instance that needs it the most. * Returns 1 if such an instance was not found **/ static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { uint32_t i, j; unsigned int level, l_min, low; unsigned int h = params->h; unsigned int k = params->k; unsigned int used = 0; for (j = 0; j < updates; j++) { l_min = h; level = h - k; for (i = 0; i < h - k; i++) { if (state->treehash[i].completed) { low = h; } else if (state->treehash[i].stackusage == 0) { low = i; } else { low = treehash_minheight_on_stack(state, params, &(state->treehash[i])); } if (low < l_min) { level = i; l_min = low; } } if (level == h - k) { break; } treehash_update(&(state->treehash[level]), state, sk_seed, params, pub_seed, addr); used++; } return updates - used; } /** * Updates the state (typically NEXT_i) by adding a leaf and updating the stack * Returns 1 if all leaf nodes have already been processed **/ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { uint32_t ltree_addr[8]; uint32_t node_addr[8]; uint32_t ots_addr[8]; int n = params->n; int h = params->h; int k = params->k; int nodeh; int idx = state->next_leaf; if (idx == 1 << h) { return 1; } // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots setType(ots_addr, 0); memcpy(ltree_addr, addr, 12); setType(ltree_addr, 1); memcpy(node_addr, addr, 12); setType(node_addr, 2); setOTSADRS(ots_addr, idx); setLtreeADRS(ltree_addr, idx); gen_leaf_wots(state->stack+state->stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); state->stacklevels[state->stackoffset] = 0; state->stackoffset++; if (h - k > 0 && idx == 3) { memcpy(state->treehash[0].node, state->stack+state->stackoffset*n, n); } while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) { nodeh = state->stacklevels[state->stackoffset-1]; if (idx >> nodeh == 1) { memcpy(state->auth + nodeh*n, state->stack+(state->stackoffset-1)*n, n); } else { if (nodeh < h - k && idx >> nodeh == 3) { memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*n, n); } else if (nodeh >= h - k) { memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((idx >> nodeh) - 3) >> 1)) * n, state->stack+(state->stackoffset-1)*n, n); } } setTreeHeight(node_addr, state->stacklevels[state->stackoffset-1]); setTreeIndex(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1))); hash_h(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n); state->stacklevels[state->stackoffset-2]++; state->stackoffset--; } state->next_leaf++; return 0; } /** * Returns the auth path for node leaf_idx and computes the auth path for the * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo * in "Post Quantum Cryptography", Springer 2009. */ static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8]) { unsigned int i; unsigned int n = params->n; unsigned int h = params->h; unsigned int k = params->k; unsigned int tau = h; unsigned int startidx; unsigned int offset, rowidx; unsigned char buf[2 * n]; uint32_t ots_addr[8]; uint32_t ltree_addr[8]; uint32_t node_addr[8]; // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots setType(ots_addr, 0); memcpy(ltree_addr, addr, 12); setType(ltree_addr, 1); memcpy(node_addr, addr, 12); setType(node_addr, 2); for (i = 0; i < h; i++) { if (! ((leaf_idx >> i) & 1)) { tau = i; break; } } if (tau > 0) { memcpy(buf, state->auth + (tau-1) * n, n); // we need to do this before refreshing state->keep to prevent overwriting memcpy(buf + n, state->keep + ((tau-1) >> 1) * n, n); } if (!((leaf_idx >> (tau + 1)) & 1) && (tau < h - 1)) { memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n); } if (tau == 0) { setLtreeADRS(ltree_addr, leaf_idx); setOTSADRS(ots_addr, leaf_idx); gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr); } else { setTreeHeight(node_addr, (tau-1)); setTreeIndex(node_addr, leaf_idx >> tau); hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n); for (i = 0; i < tau; i++) { if (i < h - k) { memcpy(state->auth + i * n, state->treehash[i].node, n); } else { offset = (1 << (h - 1 - i)) + i - h; rowidx = ((leaf_idx >> i) - 1) >> 1; memcpy(state->auth + i * n, state->retain + (offset + rowidx) * n, n); } } for (i = 0; i < ((tau < h - k) ? tau : (h - k)); i++) { startidx = leaf_idx + 1 + 3 * (1 << i); if (startidx < 1U << h) { state->treehash[i].h = i; state->treehash[i].next_idx = startidx; state->treehash[i].completed = 0; state->treehash[i].stackusage = 0; } } } } /* * Generates a XMSS key pair for a given parameter set. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params) { unsigned int n = params->n; // Set idx = 0 sk[0] = 0; sk[1] = 0; sk[2] = 0; sk[3] = 0; // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) randombytes(sk+4, 3*n); // Copy PUB_SEED to public key memcpy(pk+n, sk+4+2*n, n); uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Compute root treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+2*n, addr); // copy root to sk memcpy(sk+4+3*n, pk, n); return 0; } /** * Signs a message. * Returns * 1. an array containing the signature followed by the message AND * 2. an updated secret key! * */ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params) { unsigned int h = params->h; unsigned int n = params->n; unsigned int k = params->k; uint16_t i = 0; // Extract SK unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; unsigned char sk_seed[n]; memcpy(sk_seed, sk+4, n); unsigned char sk_prf[n]; memcpy(sk_prf, sk+4+n, n); unsigned char pub_seed[n]; memcpy(pub_seed, sk+4+2*n, n); // index as 32 bytes string unsigned char idx_bytes_32[32]; to_byte(idx_bytes_32, idx, 32); unsigned char hash_key[3*n]; // Update SK sk[0] = ((idx + 1) >> 24) & 255; sk[1] = ((idx + 1) >> 16) & 255; sk[2] = ((idx + 1) >> 8) & 255; sk[3] = (idx + 1) & 255; // -- Secret key for this non-forward-secure version is now updated. // -- A productive implementation should use a file handle instead and write the updated secret key at this point! // Init working params unsigned char R[n]; unsigned char msg_h[n]; unsigned char ots_seed[n]; uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // --------------------------------- // Message Hashing // --------------------------------- // Message Hash: // First compute pseudorandom value prf(R, idx_bytes_32, sk_prf, n); // Generate hash key (R || root || idx) memcpy(hash_key, R, n); memcpy(hash_key+n, sk+4+3*n, n); to_byte(hash_key+2*n, idx, n); // Then use it for message digest h_msg(msg_h, msg, msglen, hash_key, 3*n, n); // Start collecting signature *sig_msg_len = 0; // Copy index to signature sig_msg[0] = (idx >> 24) & 255; sig_msg[1] = (idx >> 16) & 255; sig_msg[2] = (idx >> 8) & 255; sig_msg[3] = idx & 255; sig_msg += 4; *sig_msg_len += 4; // Copy R to signature for (i = 0; i < n; i++) sig_msg[i] = R[i]; sig_msg += n; *sig_msg_len += n; // ---------------------------------- // Now we start to "really sign" // ---------------------------------- // Prepare Address setType(ots_addr, 0); setOTSADRS(ots_addr, idx); // Compute seed for OTS key pair get_seed(ots_seed, sk_seed, n, ots_addr); // Compute WOTS signature wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr); sig_msg += params->wots_par.keysize; *sig_msg_len += params->wots_par.keysize; // the auth path was already computed during the previous round memcpy(sig_msg, state->auth, h*n); if (idx < (1U << h) - 1) { bds_round(state, idx, sk_seed, params, pub_seed, ots_addr); bds_treehash_update(state, (h - k) >> 1, sk_seed, params, pub_seed, ots_addr); } /* TODO: save key/bds state here! */ sig_msg += params->h*n; *sig_msg_len += params->h*n; //Whipe secret elements? //zerobytes(tsk, CRYPTO_SECRETKEYBYTES); memcpy(sig_msg, msg, msglen); *sig_msg_len += msglen; return 0; } /** * Verifies a given message signature pair under a given public key. */ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params) { unsigned int n = params->n; unsigned long long i, m_len; unsigned long idx=0; unsigned char wots_pk[params->wots_par.keysize]; unsigned char pkhash[n]; unsigned char root[n]; unsigned char msg_h[n]; unsigned char hash_key[3*n]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); // Init addresses uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; setType(ots_addr, 0); setType(ltree_addr, 1); setType(node_addr, 2); // Extract index idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3]; printf("verify:: idx = %lu\n", idx); // Generate hash key (R || root || idx) memcpy(hash_key, sig_msg+4,n); memcpy(hash_key+n, pk, n); to_byte(hash_key+2*n, idx, n); sig_msg += (n+4); sig_msg_len -= (n+4); // hash message unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n; m_len = sig_msg_len - tmp_sig_len; h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); //----------------------- // Verify signature //----------------------- // Prepare Address setOTSADRS(ots_addr, idx); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr); sig_msg += params->wots_par.keysize; sig_msg_len -= params->wots_par.keysize; // Compute Ltree setLtreeADRS(ltree_addr, idx); l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr); // Compute root validate_authpath(root, pkhash, idx, sig_msg, params, pub_seed, node_addr); sig_msg += params->h*n; sig_msg_len -= params->h*n; for (i = 0; i < n; i++) if (root[i] != pk[i]) goto fail; *msglen = sig_msg_len; for (i = 0; i < *msglen; i++) msg[i] = sig_msg[i]; return 0; fail: *msglen = sig_msg_len; for (i = 0; i < *msglen; i++) msg[i] = 0; *msglen = -1; return -1; } /* * Generates a XMSSMT key pair for a given parameter set. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params) { unsigned int n = params->n; unsigned int i; unsigned char ots_seed[params->n]; // Set idx = 0 for (i = 0; i < params->index_len; i++) { sk[i] = 0; } // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) randombytes(sk+params->index_len, 3*n); // Copy PUB_SEED to public key memcpy(pk+n, sk+params->index_len+2*n, n); // Set address to point on the single tree on layer d-1 uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; setLayerADRS(addr, (params->d-1)); // Set up state and compute wots signatures for all but topmost tree root for (i = 0; i < params->d - 1; i++) { // Compute seed for OTS key pair treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); setLayerADRS(addr, (i+1)); get_seed(ots_seed, sk+params->index_len, n, addr); wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, pk, ots_seed, &(params->xmss_par.wots_par), pk+n, addr); } treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); memcpy(sk+params->index_len+3*n, pk, n); return 0; } /** * Signs a message. * Returns * 1. an array containing the signature followed by the message AND * 2. an updated secret key! * */ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params) { unsigned int n = params->n; unsigned int tree_h = params->xmss_par.h; unsigned int h = params->h; unsigned int k = params->xmss_par.k; unsigned int idx_len = params->index_len; uint64_t idx_tree; uint32_t idx_leaf; uint64_t i, j; int needswap_upto = -1; unsigned int updates; unsigned char sk_seed[n]; unsigned char sk_prf[n]; unsigned char pub_seed[n]; // Init working params unsigned char R[n]; unsigned char msg_h[n]; unsigned char hash_key[3*n]; unsigned char ots_seed[n]; uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; unsigned char idx_bytes_32[32]; bds_state tmp; // Extract SK unsigned long long idx = 0; for (i = 0; i < idx_len; i++) { idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i); } memcpy(sk_seed, sk+idx_len, n); memcpy(sk_prf, sk+idx_len+n, n); memcpy(pub_seed, sk+idx_len+2*n, n); // Update SK for (i = 0; i < idx_len; i++) { sk[i] = ((idx + 1) >> 8*(idx_len - 1 - i)) & 255; } // -- Secret key for this non-forward-secure version is now updated. // -- A productive implementation should use a file handle instead and write the updated secret key at this point! // --------------------------------- // Message Hashing // --------------------------------- // Message Hash: // First compute pseudorandom value to_byte(idx_bytes_32, idx, 32); prf(R, idx_bytes_32, sk_prf, n); // Generate hash key (R || root || idx) memcpy(hash_key, R, n); memcpy(hash_key+n, sk+idx_len+3*n, n); to_byte(hash_key+2*n, idx, n); // Then use it for message digest h_msg(msg_h, msg, msglen, hash_key, 3*n, n); // Start collecting signature *sig_msg_len = 0; // Copy index to signature for (i = 0; i < idx_len; i++) { sig_msg[i] = (idx >> 8*(idx_len - 1 - i)) & 255; } sig_msg += idx_len; *sig_msg_len += idx_len; // Copy R to signature for (i = 0; i < n; i++) sig_msg[i] = R[i]; sig_msg += n; *sig_msg_len += n; // ---------------------------------- // Now we start to "really sign" // ---------------------------------- // Handle lowest layer separately as it is slightly different... // Prepare Address setType(ots_addr, 0); idx_tree = idx >> tree_h; idx_leaf = (idx & ((1 << tree_h)-1)); setLayerADRS(ots_addr, 0); setTreeADRS(ots_addr, idx_tree); setOTSADRS(ots_addr, idx_leaf); // Compute seed for OTS key pair get_seed(ots_seed, sk_seed, n, ots_addr); // Compute WOTS signature wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); sig_msg += params->xmss_par.wots_par.keysize; *sig_msg_len += params->xmss_par.wots_par.keysize; memcpy(sig_msg, states[0].auth, tree_h*n); sig_msg += tree_h*n; *sig_msg_len += tree_h*n; // prepare signature of remaining layers for (i = 1; i < params->d; i++) { // put WOTS signature in place memcpy(sig_msg, wots_sigs + (i-1)*params->xmss_par.wots_par.keysize, params->xmss_par.wots_par.keysize); sig_msg += params->xmss_par.wots_par.keysize; *sig_msg_len += params->xmss_par.wots_par.keysize; // put AUTH nodes in place memcpy(sig_msg, states[i].auth, tree_h*n); sig_msg += tree_h*n; *sig_msg_len += tree_h*n; } updates = (tree_h - k) >> 1; setTreeADRS(addr, (idx_tree + 1)); // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << h)) { bds_state_update(&states[params->d], sk_seed, &(params->xmss_par), pub_seed, addr); } for (i = 0; i < params->d; i++) { // check if we're not at the end of a tree if (! (((idx + 1) & ((1ULL << ((i+1)*tree_h)) - 1)) == 0)) { idx_leaf = (idx >> (tree_h * i)) & ((1 << tree_h)-1); idx_tree = (idx >> (tree_h * (i+1))); setLayerADRS(addr, i); setTreeADRS(addr, idx_tree); if (i == (unsigned int) (needswap_upto + 1)) { bds_round(&states[i], idx_leaf, sk_seed, &(params->xmss_par), pub_seed, addr); } updates = bds_treehash_update(&states[i], updates, sk_seed, &(params->xmss_par), pub_seed, addr); setTreeADRS(addr, (idx_tree + 1)); // if a NEXT-tree exists for this level; if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << (h - tree_h * i))) { if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << h)) { bds_state_update(&states[params->d + i], sk_seed, &(params->xmss_par), pub_seed, addr); updates--; } } } else if (idx < (1ULL << h) - 1) { memcpy(&tmp, states+params->d + i, sizeof(bds_state)); memcpy(states+params->d + i, states + i, sizeof(bds_state)); memcpy(states + i, &tmp, sizeof(bds_state)); setLayerADRS(ots_addr, (i+1)); setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * tree_h))); setOTSADRS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1))); get_seed(ots_seed, sk+params->index_len, n, ots_addr); wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, states[i].stack, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); states[params->d + i].stackoffset = 0; states[params->d + i].next_leaf = 0; updates--; // WOTS-signing counts as one update needswap_upto = i; for (j = 0; j < tree_h-k; j++) { states[i].treehash[j].completed = 1; } } } //Whipe secret elements? //zerobytes(tsk, CRYPTO_SECRETKEYBYTES); memcpy(sig_msg, msg, msglen); *sig_msg_len += msglen; return 0; } /** * Verifies a given message signature pair under a given public key. */ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params) { unsigned int n = params->n; unsigned int tree_h = params->xmss_par.h; unsigned int idx_len = params->index_len; uint64_t idx_tree; uint32_t idx_leaf; unsigned long long i, m_len; unsigned long long idx=0; unsigned char wots_pk[params->xmss_par.wots_par.keysize]; unsigned char pkhash[n]; unsigned char root[n]; unsigned char msg_h[n]; unsigned char hash_key[3*n]; unsigned char pub_seed[n]; memcpy(pub_seed, pk+n, n); // Init addresses uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Extract index for (i = 0; i < idx_len; i++) { idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i)); } printf("verify:: idx = %llu\n", idx); sig_msg += idx_len; sig_msg_len -= idx_len; // Generate hash key (R || root || idx) memcpy(hash_key, sig_msg,n); memcpy(hash_key+n, pk, n); to_byte(hash_key+2*n, idx, n); sig_msg += n; sig_msg_len -= n; // hash message (recall, R is now on pole position at sig_msg unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n); m_len = sig_msg_len - tmp_sig_len; h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); //----------------------- // Verify signature //----------------------- // Prepare Address idx_tree = idx >> tree_h; idx_leaf = (idx & ((1 << tree_h)-1)); setLayerADRS(ots_addr, 0); setTreeADRS(ots_addr, idx_tree); setType(ots_addr, 0); memcpy(ltree_addr, ots_addr, 12); setType(ltree_addr, 1); memcpy(node_addr, ltree_addr, 12); setType(node_addr, 2); setOTSADRS(ots_addr, idx_leaf); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr); sig_msg += params->xmss_par.wots_par.keysize; sig_msg_len -= params->xmss_par.wots_par.keysize; // Compute Ltree setLtreeADRS(ltree_addr, idx_leaf); l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); // Compute root validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr); sig_msg += tree_h*n; sig_msg_len -= tree_h*n; for (i = 1; i < params->d; i++) { // Prepare Address idx_leaf = (idx_tree & ((1 << tree_h)-1)); idx_tree = idx_tree >> tree_h; setLayerADRS(ots_addr, i); setTreeADRS(ots_addr, idx_tree); setType(ots_addr, 0); memcpy(ltree_addr, ots_addr, 12); setType(ltree_addr, 1); memcpy(node_addr, ltree_addr, 12); setType(node_addr, 2); setOTSADRS(ots_addr, idx_leaf); // Check WOTS signature wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr); sig_msg += params->xmss_par.wots_par.keysize; sig_msg_len -= params->xmss_par.wots_par.keysize; // Compute Ltree setLtreeADRS(ltree_addr, idx_leaf); l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); // Compute root validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr); sig_msg += tree_h*n; sig_msg_len -= tree_h*n; } for (i = 0; i < n; i++) if (root[i] != pk[i]) goto fail; *msglen = sig_msg_len; for (i = 0; i < *msglen; i++) msg[i] = sig_msg[i]; return 0; fail: *msglen = sig_msg_len; for (i = 0; i < *msglen; i++) msg[i] = 0; *msglen = -1; return -1; } #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/xmss_fast.h100644 001750 001750 0000000003614775415623 0015334xustar0030 atime=1744182234.895335732 openssh-10.0p1/xmss_fast.h010064400017500001750000000072201477541562300137200ustar00djmdjm#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 */ openssh-10.0p1/PaxHeaders.10889/xmss_hash.c100644 001750 001750 0000000003614775415623 0015315xustar0030 atime=1744182234.895335732 openssh-10.0p1/xmss_hash.c010064400017500001750000000064351477541562300137100ustar00djmdjm/* $OpenBSD: xmss_hash.c,v 1.4 2023/12/20 00:06:25 jsg Exp $ */ /* hash.c version 20160722 Andreas Hülsing Joost Rijneveld Public domain. */ #include "includes.h" #ifdef WITH_XMSS #include "xmss_hash_address.h" #include "xmss_commons.h" #include "xmss_hash.h" #include #ifdef HAVE_STDINT_H # include #endif #include #include int core_hash_SHA2(unsigned char *, const unsigned int, const unsigned char *, unsigned int, const unsigned char *, unsigned long long, unsigned int); unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]){ #if IS_LITTLE_ENDIAN==1 int i = 0; for(i=0;i<8;i++) to_byte(bytes+i*4, addr[i],4); return bytes; #else memcpy(bytes, addr, 32); return bytes; #endif } int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){ unsigned long long i = 0; unsigned char buf[inlen + n + keylen]; // Input is (toByte(X, 32) || KEY || M) // set toByte to_byte(buf, type, n); for (i=0; i < keylen; i++) { buf[i+n] = key[i]; } for (i=0; i < inlen; i++) { buf[keylen + n + i] = in[i]; } if (n == 32) { SHA256(buf, inlen + keylen + n, out); return 0; } else { if (n == 64) { SHA512(buf, inlen + keylen + n, out); return 0; } } return 1; } /** * Implements PRF */ int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen) { return core_hash_SHA2(out, 3, key, keylen, in, 32, keylen); } /* * Implements H_msg */ int h_msg(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n) { if (keylen != 3*n){ // H_msg takes 3n-bit keys, but n does not match the keylength of keylen return -1; } return core_hash_SHA2(out, 2, key, keylen, in, inlen, n); } /** * We assume the left half is in in[0]...in[n-1] */ int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) { unsigned char buf[2*n]; unsigned char key[n]; unsigned char bitmask[2*n]; unsigned char byte_addr[32]; unsigned int i; setKeyAndMask(addr, 0); addr_to_byte(byte_addr, addr); prf(key, byte_addr, pub_seed, n); // Use MSB order setKeyAndMask(addr, 1); addr_to_byte(byte_addr, addr); prf(bitmask, byte_addr, pub_seed, n); setKeyAndMask(addr, 2); addr_to_byte(byte_addr, addr); prf(bitmask+n, byte_addr, pub_seed, n); for (i = 0; i < 2*n; i++) { buf[i] = in[i] ^ bitmask[i]; } return core_hash_SHA2(out, 1, key, n, buf, 2*n, n); } int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) { unsigned char buf[n]; unsigned char key[n]; unsigned char bitmask[n]; unsigned char byte_addr[32]; unsigned int i; setKeyAndMask(addr, 0); addr_to_byte(byte_addr, addr); prf(key, byte_addr, pub_seed, n); setKeyAndMask(addr, 1); addr_to_byte(byte_addr, addr); prf(bitmask, byte_addr, pub_seed, n); for (i = 0; i < n; i++) { buf[i] = in[i] ^ bitmask[i]; } return core_hash_SHA2(out, 0, key, n, buf, n, n); } #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/xmss_hash.h100644 001750 001750 0000000003614775415623 0015322xustar0030 atime=1744182234.895335732 openssh-10.0p1/xmss_hash.h010064400017500001750000000015111477541562300137030ustar00djmdjm#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 */ openssh-10.0p1/PaxHeaders.10889/xmss_hash_address.c100644 001750 001750 0000000003614775415623 0017022xustar0030 atime=1744182234.895335732 openssh-10.0p1/xmss_hash_address.c010064400017500001750000000023151477541562300154060ustar00djmdjm/* $OpenBSD: xmss_hash_address.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ /* hash_address.c version 20160722 Andreas Hülsing Joost Rijneveld Public domain. */ #include "includes.h" #ifdef WITH_XMSS #ifdef HAVE_STDINT_H # include #endif #include "xmss_hash_address.h" /* prototypes */ void setLayerADRS(uint32_t adrs[8], uint32_t layer){ adrs[0] = layer; } void setTreeADRS(uint32_t adrs[8], uint64_t tree){ adrs[1] = (uint32_t) (tree >> 32); adrs[2] = (uint32_t) tree; } void setType(uint32_t adrs[8], uint32_t type){ adrs[3] = type; int i; for(i = 4; i < 8; i++){ adrs[i] = 0; } } void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask){ adrs[7] = keyAndMask; } // OTS void setOTSADRS(uint32_t adrs[8], uint32_t ots){ adrs[4] = ots; } void setChainADRS(uint32_t adrs[8], uint32_t chain){ adrs[5] = chain; } void setHashADRS(uint32_t adrs[8], uint32_t hash){ adrs[6] = hash; } // L-tree void setLtreeADRS(uint32_t adrs[8], uint32_t ltree){ adrs[4] = ltree; } // Hash Tree & L-tree void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight){ adrs[5] = treeHeight; } void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex){ adrs[6] = treeIndex; } #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/xmss_hash_address.h100644 001750 001750 0000000003614775415623 0017027xustar0030 atime=1744182234.895335732 openssh-10.0p1/xmss_hash_address.h010064400017500001750000000015041477541562300154120ustar00djmdjm#ifdef WITH_XMSS /* $OpenBSD: xmss_hash_address.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ /* hash_address.h version 20160722 Andreas Hülsing Joost Rijneveld Public domain. */ #ifdef HAVE_STDINT_H #include #endif void setLayerADRS(uint32_t adrs[8], uint32_t layer); void setTreeADRS(uint32_t adrs[8], uint64_t tree); void setType(uint32_t adrs[8], uint32_t type); void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask); // OTS void setOTSADRS(uint32_t adrs[8], uint32_t ots); void setChainADRS(uint32_t adrs[8], uint32_t chain); void setHashADRS(uint32_t adrs[8], uint32_t hash); // L-tree void setLtreeADRS(uint32_t adrs[8], uint32_t ltree); // Hash Tree & L-tree void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight); void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex); #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/xmss_wots.c100644 001750 001750 0000000003614775415623 0015366xustar0030 atime=1744182234.895335732 openssh-10.0p1/xmss_wots.c010064400017500001750000000113621477541562300137540ustar00djmdjm/* $OpenBSD: xmss_wots.c,v 1.3 2018/04/10 00:10:49 djm Exp $ */ /* wots.c version 20160722 Andreas Hülsing Joost Rijneveld Public domain. */ #include "includes.h" #ifdef WITH_XMSS #include #ifdef HAVE_STDINT_H # include #endif #include #include "xmss_commons.h" #include "xmss_hash.h" #include "xmss_wots.h" #include "xmss_hash_address.h" /* libm-free version of log2() for wots */ static inline int wots_log2(uint32_t v) { int b; for (b = sizeof (v) * CHAR_BIT - 1; b >= 0; b--) { if ((1U << b) & v) { return b; } } return 0; } void wots_set_params(wots_params *params, int n, int w) { params->n = n; params->w = w; params->log_w = wots_log2(params->w); params->len_1 = (CHAR_BIT * n) / params->log_w; params->len_2 = (wots_log2(params->len_1 * (w - 1)) / params->log_w) + 1; params->len = params->len_1 + params->len_2; params->keysize = params->len * params->n; } /** * Helper method for pseudorandom key generation * Expands an n-byte array into a len*n byte array * this is done using PRF */ static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, const wots_params *params) { uint32_t i = 0; unsigned char ctr[32]; for(i = 0; i < params->len; i++){ to_byte(ctr, i, 32); prf((outseeds + (i*params->n)), ctr, inseed, params->n); } } /** * Computes the chaining function. * out and in have to be n-byte arrays * * interprets in as start-th value of the chain * addr has to contain the address of the chain */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { uint32_t i, j; for (j = 0; j < params->n; j++) out[j] = in[j]; for (i = start; i < (start+steps) && i < params->w; i++) { setHashADRS(addr, i); hash_f(out, out, pub_seed, addr, params->n); } } /** * base_w algorithm as described in draft. * * */ static void base_w(int *output, const int out_len, const unsigned char *input, const wots_params *params) { int in = 0; int out = 0; uint32_t total = 0; int bits = 0; int consumed = 0; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { total = input[in]; in++; bits += 8; } bits -= params->log_w; output[out] = (total >> bits) & (params->w - 1); out++; } } void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { uint32_t i; expand_seed(pk, sk, params); for (i=0; i < params->len; i++) { setChainADRS(addr, i); gen_chain(pk+i*params->n, pk+i*params->n, 0, params->w-1, params, pub_seed, addr); } } int wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { //int basew[params->len]; int csum = 0; uint32_t i = 0; int *basew = calloc(params->len, sizeof(int)); if (basew == NULL) return -1; base_w(basew, params->len_1, msg, params); for (i=0; i < params->len_1; i++) { csum += params->w - 1 - basew[i]; } csum = csum << (8 - ((params->len_2 * params->log_w) % 8)); int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8; unsigned char csum_bytes[len_2_bytes]; to_byte(csum_bytes, csum, len_2_bytes); int csum_basew[params->len_2]; base_w(csum_basew, params->len_2, csum_bytes, params); for (i = 0; i < params->len_2; i++) { basew[params->len_1 + i] = csum_basew[i]; } expand_seed(sig, sk, params); for (i = 0; i < params->len; i++) { setChainADRS(addr, i); gen_chain(sig+i*params->n, sig+i*params->n, 0, basew[i], params, pub_seed, addr); } free(basew); return 0; } int wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) { int csum = 0; uint32_t i = 0; int *basew = calloc(params->len, sizeof(int)); if (basew == NULL) return -1; base_w(basew, params->len_1, msg, params); for (i=0; i < params->len_1; i++) { csum += params->w - 1 - basew[i]; } csum = csum << (8 - ((params->len_2 * params->log_w) % 8)); int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8; unsigned char csum_bytes[len_2_bytes]; to_byte(csum_bytes, csum, len_2_bytes); int csum_basew[params->len_2]; base_w(csum_basew, params->len_2, csum_bytes, params); for (i = 0; i < params->len_2; i++) { basew[params->len_1 + i] = csum_basew[i]; } for (i=0; i < params->len; i++) { setChainADRS(addr, i); gen_chain(pk+i*params->n, sig+i*params->n, basew[i], params->w-1-basew[i], params, pub_seed, addr); } free(basew); return 0; } #endif /* WITH_XMSS */ openssh-10.0p1/PaxHeaders.10889/xmss_wots.h100644 001750 001750 0000000003614775415623 0015373xustar0030 atime=1744182234.896311829 openssh-10.0p1/xmss_wots.h010064400017500001750000000035631477541562300137650ustar00djmdjm#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 */